Secure SSL/TLS settings for Apache 2.4

Last Modified: Mon, 17 Mar 2014 18:59:02 +0000 ; Created: Mon, 17 Mar 2014 18:59:02 +0000

The following is my Apache SSL settings that earn me an A+ score on the Qualys SSL Labs SSL Test. It enforces forward secrecy by limiting to only strong ciphers. Most end-point clients are supported and TLS v1.2 is preferred but TLS v1.0 is supported for older clients.
# Tested with Apache 2.4 and OpenSSL 1.0.1e
#
# 2014-03-11

# Useful references
#   http://httpd.apache.org/docs/2.4/ssl/ssl_howto.html
#   https://www.ssllabs.com/downloads/SSL_TLS_Deployment_Best_Practices_1.3.pdf
#   https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
#   https://www.ssllabs.com/ssltest/
#   https://cc.dcsec.uni-hannover.de
#   https://www.openssl.org/docs/apps/ciphers.html#TLS_v1_2_cipher_suites
#   http://crypto.stackexchange.com/questions/10493/why-is-tls-susceptible-to-protocol-downgrade-attacks

# The following end-clients are supported (older versions are NOT; newer versions probably are):
#   Microsoft Internet Explorer 11
#   Google Chrome 30
#   Google Chrome 31
#   Google Chrome 32
#   Google Chrome 33
#   Mozilla Firefox 27
#   Opera 17
#   Android 4.2.2
#   Java 1.8 (Java 7 defaults to using TLSv1, with TLSv1.2 optional if code enabled; Java 8 defaults to v1.2)
#   iOS 5.0
#   F5 BigIP load balancer 11.4.1
#   Safari 7 on Mac OS X 10.9
# The following obsolete end-clients are supported, but don't support the strongest security options (i.e. TLSv1.2)
#   Microsoft Internet Explorer 8
#   Microsoft Internet Explorer 9
#   Microsoft Internet Explorer 10
#   Mozilla Firefox 26
#   Java 1.7
#   Java 1.6
#   Android 2.3
#   Android 3.x
#   Android 4.0
#   Android 4.1
#   Safari 6 on Mac OS X 10.8


#-------------------------------------------------------------------------------
# Disable insecure client-initiated renegotiation (usually default but make sure)
SSLInsecureRenegotiation off


#-------------------------------------------------------------------------------
# Prevent the CRIME attack
SSLCompression off


#-------------------------------------------------------------------------------
# Reference documents for TLS version support
#   http://en.wikipedia.org/wiki/Transport_Layer_Security#Web_browsers
#   http://op-co.de/blog/posts/android_ssl_downgrade/
#   http://en.wikipedia.org/wiki/Comparison_of_TLS_implementations#Protocol_support
# TLSv1.2 is supported by (configuration enabled by default):
#   Google Chrome 30+
#   Mozilla Firefox 27+
#   Microsoft Internet Explorer 11+
#   Opera 17+
#   Safari 5+ (on Mac or iOS)
#   Android 4.2.2
#   iOS 5.0
#   F5 BigIP load balancer 11.4.1
#   Safari 7 on Mac OS X 10.9
SSLProtocol TLSv1.2 +TLSv1

# Complete prevention (server-side) of BEAST is only possible in TLSv1.1 and later.  Use of TLSv1.0 with CBC ciphers
#   can still leave the issue open.  Use of RC4 as a cipher was recommended, but RC4 is weakened by other attacks.
#   Use of TLSv1.2 with GCM is the best available.  Most web browsers have patches to mitigate client-side.
# Use of GCM AES ciphers are only available in TLSv1.2, but at least we can prefer them.
# Since we must support TLS version 1.0 to handle older browsers at this time we cannot 100% stop BEAST server-side.
# Older clients must have their own client-side patch to prevent the risk of BEAST

#*********
# Support older clients (for a limited time) with lower security version
# Internet Explorer 8 - 10 can do TLS v1.2, but it is disabled by default so only TLSv1.0 is enabled in IE :(
# Other older clients are in a similar situation.
# SSLProtocol has +TLSv1 added above to SSLProtocol for this support.


#-------------------------------------------------------------------------------
# Enable perfect forward secrecy

# Prefer the servers cipher options
SSLHonorCipherOrder On

# Apache 2.4+ has Define directive built-in, you can string concat with it

# The latest and strongest OpenSSL (latest version) ciphers are typically not supported by the major web browser clients
# We will add ciphers in order of preference based on the strongest cipher the web client (and version) supports
# We also take into account web server support

# Start with secure clean slate
# (Reminder:  Apache 2.4.7+ always adds "!aNULL:!eNULL:!EXP:")
Define sslCiphers -ALL:!ADH:!aNULL:!EXP:!EXPORT40:!EXPORT56:!RC4:!3DES:!eNULL:!NULL:!DES:!MD5:!LOW


#************
# We'd prefer (where supported):    ECDHE   RSA	AES  GCM    TLSv1.2
#   ECDHE is faster than DHE.  Both provide forward secrecy.
#   RSA has larger key size but verifies faster.  Furthermore ECDSA requires ECDSA certificates which most people are
#       not using with their Apache web server or otherwise.
#   AES is strong algorithm.  128-bit or 256-bit are fine.  Most clients don't do 256-bit yet.
#   GCM over CBC.  CBC has been attacked a few times and NIST prefers GCM.
#   TLS v1.2 avoids a lot of attacks and has newer features/ciphers.

# Our very first and preferred cipher regardless of client
Define sslCiphers ${sslCiphers}:ECDHE-RSA-AES128-GCM-SHA256
# Backup cipher to first preferred
Define sslCiphers ${sslCiphers}:DHE-RSA-AES128-GCM-SHA256
# Warning:  Don't duplicate declare any ciphers or it may end up in a lower priority/preference position


# Google Chrome (Version 33.0.1750.146 m)   Windows 7 64-bit w/SP1
# Already:	ECDHE-RSA-AES128-GCM-SHA256

# Firefox 27    Windows 7 64-bit w/SP1
# Already:	ECDHE-RSA-AES128-GCM-SHA256

# Android 4.2.2; 4.3
# Already:	ECDHE-RSA-AES128-GCM-SHA256

# Opera 20
# Already:	ECDHE-RSA-AES128-GCM-SHA256

#   iOS 5.0
# Already:	ECDHE-RSA-AES128-GCM-SHA256

# F5 BigIP load balancer 11.4.1
#   CBC not GCM
Define sslCiphers ${sslCiphers}:ECDHE-RSA-AES256-SHA


#************
# TLS v1.0 capable only clients

# Microsoft Internet Explorer 8.0.7601.17514	Windows 7 64-bit w/SP1
# Already: ECDHE-RSA-AES256-SHA

# Android 2.3 to 4.0
# Untested due to lack of devices.  Assuming same as IE8.

# Mozilla Firefox 26
# Already:	ECDHE-RSA-AES128-GCM-SHA256

# Java 7 (1.7) doesn't do GCM, that is coming in Java 8
# Also 256-bit isn't available in default setups without "JCE Unlimited Strength Jurisdiction Policy Files"
# Java 7 RFC4492 cipher name:  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
#	http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
# OpenSSL version of the cipher name:  ECDHE-RSA-AES128-SHA 
#	https://www.openssl.org/docs/apps/ciphers.html#CIPHER_SUITE_NAMES
Define sslCiphers ${sslCiphers}:ECDHE-RSA-AES128-SHA


# Java 6 (1.6) doesn't do GCM
# No support at all for TLSv1.1 or later (not even disabled by default like Java 7)
# Also 256-bit isn't available in default setups without "JCE Unlimited Strength Jurisdiction Policy Files"
# Java 7 RFC4492 cipher name:  TLS_DHE_RSA_WITH_AES_128_CBC_SHA
#	http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
# OpenSSL version of the cipher name:  DHE-RSA-AES128-SHA
#	https://www.openssl.org/docs/apps/ciphers.html#CIPHER_SUITE_NAMES
Define sslCiphers ${sslCiphers}:DHE-RSA-AES128-SHA


#*******************************************************************************
# (Reminder:  Multiple SSLCipherSuite are *not* additive but *override/replace* each other)
# (Reminder:  "In per-directory context" behaves special)
# (Reminder:  Apache 2.4.7+ always adds "!aNULL:!eNULL:!EXP:"
SSLCipherSuite ${sslCiphers}


#-------------------------------------------------------------------------------
# Mitigate against BREACH and TIME
SetEnv no-gzip

#-------------------------------------------------------------------------------
# Enable HTTP Strict Transport Security (HSTS) (approximately for 1 year)
Header add Strict-Transport-Security "max-age=31536000 ; includeSubDomains"