Create this vhost file (caution, lines may wrap, in particular LogFormat: it should be one long line):
cat > /etc/apache2/sites-available/cert-auth-test.conf <<EOF
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
LogLevel info ssl:warn
ServerAdmin webmaster@localhost DocumentRoot /var/www/html
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" protocol=%{SSL_PROTOCOL}x commonName=%{SSL_CLIENT_S_DN_CN}x" combined-ssl
ErrorLog \${APACHE_LOG_DIR}/error.log
CustomLog \${APACHE_LOG_DIR}/access.log combined-ssl
SSLEngine on SSLCertificateFile /etc/apache2/ubuntu.pem SSLCertificateKeyFile /etc/apache2/ubuntu.key SSLCACertificateFile /etc/apache2/cacert.pem
<FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch>
<Directory /usr/lib/cgi-bin> SSLOptions +StdEnvVars </Directory>
<Location /> SSLRenegBufferSize 1024 SSLVerifyClient require Require ssl-verify-client
</Location>
</VirtualHost>
</IfModule>
EOF
Enable the ssl module and this new vhost we just created:
a2enmod ssl && a2ensite cert-auth-test.conf
Restart apache2:
systemctl restart apache2
Verify that cert authentication is required:
root@ubuntu:~# curl --output index.html https://ubuntu/ --cacert /etc/apache2/cacert.pem --tlsv1.3 -f
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (56) OpenSSL SSL_read: error:1409445C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required, errno 0
Verify that a GET request with the client certificate works:
root@ubuntu:~# curl --output index.html https://ubuntu/ --cacert /etc/apache2/cacert.pem --cert client-auth.pem --key client-auth.key --tlsv1.3 -f
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
100 10918 100 10918 0 0 969k 0 --:--:-- --:--:-- --:--:-- 969k
Verify that POST request with the client certificate fails:
root@ubuntu:~# curl --output index.html https://ubuntu/ --cacert /etc/apache2/cacert.pem --cert client-auth.pem --key client-auth.key --tlsv1.3 -f -F bug=true
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
100 142 0 0 100 142 0 12909 --:--:-- --:--:-- --:--:-- 14200
curl: (22) The requested URL returned error: 403 Forbidden
Server logs for the above:
==> /var/log/apache2/error.log <==
[Mon Apr 13 14:49:03.357183 2020] [ssl:error] [pid 12248:tid 139782462109440] [client 10.0.100.38:41002] AH02263: Re-negotiation handshake failed: Client certificate missing
With the fixed packages, the POST request works:
root@ubuntu:~# curl --output index.html https://ubuntu/ --cacert /etc/apache2/cacert.pem --cert client-auth.pem --key client-auth.key --tlsv1.3 -f -F bug=true
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
100 11060 100 10918 100 142 101k 1352 --:--:-- --:--:-- --:--:-- 102k
And the server log confirms it was a POST request, using certificates, and TLSv1.3:
==> /var/log/apache2/access.log <==
10.0.100.38 - - [13/Apr/2020:14:52:26 +0000] "POST / HTTP/1.1" 200 17118 "-" "curl/7.68.0" protocol=TLSv1.3 commonName=client-auth
Apache is lacking proper support for post-handhake-auth in TLSv1.3 POST requests using certificate authentication.
This was fixed in debian[1] via patches from upstream[2].
Test case:
$ lxc launch ubuntu-daily:focal ubuntu
Enter the container as root:
$ lxc exec ubuntu bash
Verify hostname is "ubuntu":
# hostname
ubuntu
Install apache2:
apt update && apt install apache2
Download the following files from this other bug report and place them in /etc/apache2: /bugs.launchpad .net/ubuntu/ +source/ apache2/ +bug/1833039/ +attachment/ 5274492/ +files/ cacert. pem https:/ /bugs.launchpad .net/ubuntu/ +source/ apache2/ +bug/1833039/ +attachment/ 5274493/ +files/ ubuntu. pem https:/ /bugs.launchpad .net/ubuntu/ +source/ apache2/ +bug/1833039/ +attachment/ 5274494/ +files/ ubuntu. key
cd /etc/apache2
wget https:/
These certs are luckily still valid until june 2020, so they can be used for this bug as well.
Adjust permissions of the key file: ubuntu. key ubuntu. key
chmod 0640 /etc/apache2/
chgrp www-data /etc/apache2/
Download the client certificate and key files and place them in /root: /bugs.launchpad .net/ubuntu/ +source/ apache2/ +bug/1833039/ +attachment/ 5274495/ +files/ client- auth.pem https:/ /bugs.launchpad .net/ubuntu/ +source/ apache2/ +bug/1833039/ +attachment/ 5274496/ +files/ client- auth.key
cd /root
wget https:/
Create this vhost file (caution, lines may wrap, in particular LogFormat: it should be one long line): sites-available /cert-auth- test.conf <<EOF
DocumentRoot /var/www/html %{SSL_PROTOCOL} x commonName= %{SSL_CLIENT_ S_DN_CN} x" combined-ssl LOG_DIR} /error. log LOG_DIR} /access. log combined-ssl
SSLCertificate File /etc/apache2/ ubuntu. pem
SSLCertificate KeyFile /etc/apache2/ ubuntu. key
SSLCACertifica teFile /etc/apache2/ cacert. pem shtml|phtml| php)$">
SSLOptions +StdEnvVars
</FilesMatch>
SSLOptions +StdEnvVars
</Directory>
SSLRenegBuffe rSize 1024
SSLVerifyClie nt require
Require ssl-verify-client
cat > /etc/apache2/
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
LogLevel info ssl:warn
ServerAdmin webmaster@localhost
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" protocol=
ErrorLog \${APACHE_
CustomLog \${APACHE_
SSLEngine on
<FilesMatch "\.(cgi|
<Directory /usr/lib/cgi-bin>
<Location />
</Location>
</VirtualHost>
</IfModule>
EOF
Enable the ssl module and this new vhost we just created:
a2enmod ssl && a2ensite cert-auth-test.conf
Restart apache2:
systemctl restart apache2
Verify that cert authentication is required: /ubuntu/ --cacert /etc/apache2/ cacert. pem --tlsv1.3 -f
Dload Upload Total Spent Left Speed ssl3_read_ bytes:tlsv13 alert certificate required, errno 0
root@ubuntu:~# curl --output index.html https:/
% Total % Received % Xferd Average Speed Time Time Time Current
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (56) OpenSSL SSL_read: error:1409445C:SSL routines:
Verify that a GET request with the client certificate works: /ubuntu/ --cacert /etc/apache2/ cacert. pem --cert client-auth.pem --key client-auth.key --tlsv1.3 -f
Dload Upload Total Spent Left Speed
root@ubuntu:~# curl --output index.html https:/
% Total % Received % Xferd Average Speed Time Time Time Current
100 10918 100 10918 0 0 969k 0 --:--:-- --:--:-- --:--:-- 969k
Verify that POST request with the client certificate fails: /ubuntu/ --cacert /etc/apache2/ cacert. pem --cert client-auth.pem --key client-auth.key --tlsv1.3 -f -F bug=true
Dload Upload Total Spent Left Speed
root@ubuntu:~# curl --output index.html https:/
% Total % Received % Xferd Average Speed Time Time Time Current
100 142 0 0 100 142 0 12909 --:--:-- --:--:-- --:--:-- 14200
curl: (22) The requested URL returned error: 403 Forbidden
Server logs for the above: apache2/ error.log <==
==> /var/log/
[Mon Apr 13 14:49:03.357183 2020] [ssl:error] [pid 12248:tid 139782462109440] [client 10.0.100.38:41002] AH02263: Re-negotiation handshake failed: Client certificate missing
==> /var/log/ apache2/ access. log <== 2020:14: 49:03 +0000] "POST / HTTP/1.1" 403 3798 "-" "curl/7.68.0" protocol=TLSv1.3 commonName=-
10.0.100.38 - - [13/Apr/
With the fixed packages, the POST request works: /ubuntu/ --cacert /etc/apache2/ cacert. pem --cert client-auth.pem --key client-auth.key --tlsv1.3 -f -F bug=true
Dload Upload Total Spent Left Speed
root@ubuntu:~# curl --output index.html https:/
% Total % Received % Xferd Average Speed Time Time Time Current
100 11060 100 10918 100 142 101k 1352 --:--:-- --:--:-- --:--:-- 102k
And the server log confirms it was a POST request, using certificates, and TLSv1.3: apache2/ access. log <== 2020:14: 52:26 +0000] "POST / HTTP/1.1" 200 17118 "-" "curl/7.68.0" protocol=TLSv1.3 commonName= client- auth
==> /var/log/
10.0.100.38 - - [13/Apr/