In the past days, I was halfway successful with securing my websites. So far, I have achieved the following:
Get a certificate from letsencrypt.org, securing the domains example1.com, example2.com and example3.com (RSA key size is 4096 bits, example1.com is the CN of the certificate, example2.com and example3.com are subjectAltNames)
Configure Apache to use only TLSv1.2
Configure Apache to use only ciphers which I am considering secure (i.e. no RC4, no SHA1, no ciphers with CBC and so on) and which provide PFS (i.e. only ciphers which offer DHE or ECDHE key exchange)
Configure the virtual hosts in Apache so that there is a HTTP host and a HTTPS host for example1.com, but still only HTTP hosts for example2.com and example3.com
Please note that all three domains / virtual hosts are running on the same IP address and that I use the Apache SSL module (mod_ssl).
This configuration is working in the sense that I can view http://example1.com, http://example2.com, http://example3.com and https://example1.com exactly as intended from within the current (most recent) versions of IE 11, FF and Chrome (I am currently not interested into making things work with other browsers).
The following are the relevant snippets from my Apache configuration.
Configuration file for example1.com:
<Directory /home/www/example1>
Require all granted
AllowOverride none
Options IncludesNOEXEC
DirectoryIndex index.shtml
</Directory>
<VirtualHost example1.com:80>
ServerAdmin ...
DocumentRoot /home/www/example1
ServerName example1.com
ServerAlias *.example1.com
CustomLog ...
ErrorLog ...
</VirtualHost>
<VirtualHost example1.com:443>
ServerAdmin ...
DocumentRoot /home/www/example1
ServerName example1.com
ServerAlias *.example1.com
CustomLog ...
ErrorLog ...
SSLEngine on
SSLCompression off
SSLHonorCipherOrder on
SSLInsecureRenegotiation off
SSLOptions +StrictRequire
SSLCertificateFile /etc/letsencrypt/live/example1.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example1.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example1.com/chain.pem
SSLProtocol TLSv1.2
SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256
</VirtualHost>
Configuration file for example2.com (like above, but without the SSL virtual host section):
<Directory /home/www/example2>
Require all granted
AllowOverride none
Options IncludesNOEXEC
DirectoryIndex index.shtml
</Directory>
<VirtualHost example2.com:80>
ServerAdmin ...
DocumentRoot /home/www/example2
ServerName example2.com
ServerAlias *.example2.com
CustomLog ...
ErrorLog ...
</VirtualHost>
The configuration file for example3.com is like that for example2.com with all occurrences of "example2" replaced by "example3".
The problem:
As soon as I add the SSL virtual host section for example2.com or / and example3.com, nor FF nor Chrome will connect to any of the HTTPS sites, i.e. this breaks https://example1.com which formerly has been working. In other words, if I change the example2.com configuration file to
<Directory /home/www/example2>
Require all granted
AllowOverride none
Options IncludesNOEXEC
DirectoryIndex index.shtml
</Directory>
<VirtualHost example2.com:80>
ServerAdmin ...
DocumentRoot /home/www/example2
ServerName example2.com
ServerAlias *.example2.com
CustomLog ...
ErrorLog ...
</VirtualHost>
<VirtualHost example2.com:443>
ServerAdmin ...
DocumentRoot /home/www/example2
ServerName example2.com
ServerAlias *.example2.com
CustomLog ...
ErrorLog ...
SSLEngine on
SSLCompression off
SSLHonorCipherOrder on
SSLInsecureRenegotiation off
SSLOptions +StrictRequire
SSLCertificateFile /etc/letsencrypt/live/example1.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example1.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example1.com/chain.pem
SSLProtocol TLSv1.2
SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256
</VirtualHost>
and do the same thing for example3.com, this breaks all HTTPS sites. Sometimes, IE, FF and Chrome will be able to connect to one of these HTTPS sites, but it can't be predicted to which one and under what circumstances (perhaps a cache thing - I am not completely sure).
I have sniffed the respective traffic with Wireshark, but unfortunately, that didn't lead to anything: Apache just aborts the SSL connection handshake with error code 40 / "handshake failure".
The weird thing is that all HTTPS connections (i.e. https://example1.com, https://example2.com and https://example3.com) work reliably with all three browsers if I remove the SSLCipherSuite
directive from each configuration file.
I am aware that SNI would need TLSv1, but my feeling is that this is not an SNI issue. According to multiple articles, I do not need SNI even when running multiple virtual SSL hosts on the same IP address if all domain names (virtual host names) are in the same certificate, and that is exactly my situation. I'd like to stress again that using the directive
SSLCertificateFile /etc/letsencrypt/live/example1.com/cert.pem
in all three configuration files is not a typo since that one certificate carries the three domain names in it.
So, could please anybody explain what is going on there and perhaps give some hints how to achieve my goal (server side cipher suite and TLS protocol restriction like shown above, all domain names in one certificate, all virtual hosts (domains) at the same IP address)? I already have done tests with Apache 2.2 and 2.4, but to no avail.