I wrote a bash script to test cipher suites. It gets a list of supported cipher suites from OpenSSL and tries to connect using each one. If the handshake is successful, it prints YES
. If the handshake isn't successful, it prints NO
, followed by the OpenSSL error text.
#!/usr/bin/env bash
# OpenSSL requires the port number.
SERVER=$1
DELAY=1
ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')
echo Obtaining cipher list from $(openssl version).
for cipher in ${ciphers[@]}
do
echo -n Testing $cipher...
result=$(echo -n | openssl s_client -cipher "$cipher" -connect $SERVER 2>&1)
if [[ "$result" =~ ":error:" ]] ; then
error=$(echo -n $result | cut -d':' -f6)
echo NO \($error\)
else
if [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher :" ]] ; then
echo YES
else
echo UNKNOWN RESPONSE
echo $result
fi
fi
sleep $DELAY
done
Here's sample output showing 3 unsupported ciphers, and 1 supported cipher:
[@linux ~]$ ./test_ciphers 192.168.1.11:443
Obtaining cipher list from OpenSSL 0.9.8k 25 Mar 2009.
Testing ADH-AES256-SHA...NO (sslv3 alert handshake failure)
Testing DHE-RSA-AES256-SHA...NO (sslv3 alert handshake failure)
Testing DHE-DSS-AES256-SHA...NO (sslv3 alert handshake failure)
Testing AES256-SHA...YES
EDIT: Add flexibility as host and port are provided as parameter to the script
While installing the renewed certificate, I discovered that the problem was caused by specifying (for the domain and for each subdomain) in ISPConfig the entire set of data necessary for HTTPS: certificate, private key, CA chain, etc.
Put differently, removing the set of data led to the Qualys test to grade the domain A and at the same time remove the warnings about RC4. Putting the details back leads to the warnings coming back and the grade being capped at B again, which leaves no place for doubts as to the causality link.
It's as if the giving of the details for each vhost somehow created a new environment in which some defaults have overridden the cipher suite that I've specified in ssl.conf. Weird.
The solution is to add the SSLCipherSuite specification in the Apache Directives textarea for each vhost. This is what I have in the configuration that gets me an A grade:
SSLProtocol ALL -SSLv2 -SSLv3
SSLHonorCipherOrder on
# Compression is disabled by default on my distribution (CentOS 6)
# SSLCompression off
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
EDIT (2017-05-16): An additional finding about this problem: the specifying of SSLCipherSuite
is mandatory. I can't fathom why that specific directive, although specified at the server level does not automatically apply to virtual host configurations. I am running Apache 2.2.15 on CentOS 6.9.
EDIT (2018-06-18): More information. I've just discovered that the SSLCipherSuite
directive can be specified a single time and it will apply to all virtual hosts: in the base mod_ssl configuration file (on CentOS 6, the file is found at /etc/httpd/conf.d/ssl.conf
), you simply have to specify the directive outside of the default virtualhost. The Apache 2.2 documentation states that the default value of this directive is SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
. I reckon that this is where the RC4 cipher comes from: in the absence of any specification, which was the case for me since no specification was in the "global" context, the default value applies. This understanding ends what has been a mystery for me. Ironically, I'm about to switch to CentOS 7 when I find this explanation! HTH.
Best Answer
To add those directives to Apache via WHM you'd add them via :
Apache Configuration > Include Editor > Pre Main Include
and of course with the new issue with Poodle and disabling SSL v3 you'd probably want to make it :
However I believe you may also need to update the SSL Cipher suite settings within
Apache Configuration > Global Configuration > SSL Cipher Suite
to something like this :
Certainly when I updated my servers to disable SSLv3 and also disable the ciphers that allow anonymous authentication, doing the first bit alone still showed my server as reported them as being available, but doing the second part as well fixed it.