在我们的 lighttpd 2 开发分支中,我们使用模块来实现 SSL 支持;这使我们能够支持不同的 SSL 库,今天我想谈谈 mod_gnutls。
SSL/TLS 遇到了一些问题。一方面是 BEAST 攻击 1,它建议对 SSL3.0 和 TLS1.0 连接使用 RC4;另一方面,TLS 中的 RC4 已被攻破 2。
因此,虽然有些客户端可能支持 TLS1.1 甚至 TLS1.2,但你仍然需要为不支持的客户端支持 RC4,同时你也不希望允许支持 TLS1.1 或 TLS1.2 的客户端使用 RC4。大多数服务器配置无法处理这种情况——但 mod_gnutls 可以,它利用了 GnuTLS 中的一个巧妙的钩子函数3(PolarSSL 也直接支持此功能,Hiawatha 正在使用它)。
基本上,如果连接使用 TLS1.0 或 SSL3.0,它将把 ":-CIPHER-ALL:+ARCFOUR-128"
添加到你的 优先级字符串 4(类似于 OpenSSL 中的密码套件)。
我建议在 lighttpd2 中将 "NORMAL:-VERS-SSL3.0:-CIPHER-ALL:-SHA1:-MD5:+SHA1:+AES-256-GCM:+AES-256-CBC:+CAMELLIA-256-CBC:%SERVER_PRECEDENCE"
作为 GnuTLS 的优先级字符串,mod_gnutls 将为你修复 BEAST 攻击。
- SSL3.0 已被禁用 – 所有客户端现在至少应该支持 TLS1.0。
-SHA1:-MD5:+SHA1
重新排序了密码套件,使得 SHA1 靠后,并移除了 MD5 密码套件(只有一个支持的 MD5 密码套件:TLS_RSA_ARCFOUR_MD5
)。-CIPHER-ALL:+AES-256-GCM:+AES-256-CBC:+CAMELLIA-256-CBC
选择了我们希望支持的 3 种密码套件。如果你愿意,你也可以添加 128 位密码套件::+AES-128-GCM:+AES-128-CBC:+CAMELLIA-128-CBC
。%SERVER_PRECEDENCE
告诉 GnuTLS 服务器根据其自身偏好重新排序密码套件。- 你可以添加 “:-RSA” 来强制进行 DHE/ECDHE 密钥交换,这应该能提供完美前向保密(Perfect Forward Secrecy)。
推荐的优先级字符串应产生以下密码列表
TLS_ECDHE_ECDSA_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_AES_256_CBC_SHA1 TLS_ECDHE_RSA_AES_256_GCM_SHA384 TLS_ECDHE_RSA_AES_256_CBC_SHA1 TLS_DHE_RSA_AES_256_CBC_SHA256 TLS_DHE_RSA_AES_256_CBC_SHA1 TLS_DHE_RSA_CAMELLIA_256_CBC_SHA1 TLS_DHE_DSS_AES_256_CBC_SHA256 TLS_DHE_DSS_AES_256_CBC_SHA1 TLS_DHE_DSS_CAMELLIA_256_CBC_SHA1 TLS_RSA_AES_256_CBC_SHA256 TLS_RSA_AES_256_CBC_SHA1 TLS_RSA_CAMELLIA_256_CBC_SHA1
对于 TLS1.0,它将改为使用此功能(SSL3.0 已禁用)
TLS_DHE_DSS_ARCFOUR_SHA1 TLS_RSA_ARCFOUR_SHA1
使用标准 RSA 密钥,它将使用以下密码套件(更新:我们现在支持 DHE)
TLS_ECDHE_RSA_AES_256_GCM_SHA384 TLS_ECDHE_RSA_AES_256_CBC_SHA1 TLS_DHE_RSA_AES_256_CBC_SHA256 TLS_DHE_RSA_AES_256_CBC_SHA1 TLS_DHE_RSA_CAMELLIA_256_CBC_SHA1 TLS_RSA_AES_256_CBC_SHA256 TLS_RSA_AES_256_CBC_SHA1 TLS_RSA_CAMELLIA_256_CBC_SHA1
以及对于 TLS1.0
TLS_RSA_ARCFOUR_SHA1
lighttpd 2 配置示例
setup { module_load "mod_gnutls"; gnutls [ "priority" => "NORMAL:-VERS-SSL3.0:-CIPHER-ALL:-SHA1:-MD5:+SHA1:+AES-256-GCM:+AES-256-CBC:+CAMELLIA-256-CBC:%SERVER_PRECEDENCE", "listen" => "0.0.0.0:443", "pemfile" => "/ssl/certs/lighttpd_server.pem" ]; }
现在你可以测试你的服务器了(需要足够新的 GnuTLS 版本,至少包含对 TLS1.1 的支持,已使用 gnutls 3.0.22 测试)。
gnutls-cli --priority="NORMAL:-CIPHER-ALL:+ARCFOUR-128" example.com gnutls-cli --priority="NORMAL:-CIPHER-ALL:+ARCFOUR-128:-VERS-TLS-ALL:+VERS-TLS1.0" example.com gnutls-cli --priority="NORMAL:-ARCFOUR-128:-VERS-TLS-ALL:+VERS-TLS1.0" example.com
第一个应该失败;GnuTLS 应该使用 TLS1.2 进行连接,并且 RC4 将不可用。第二个命令应该成功——它应该使用 TLS1.0 进行连接,并且只有 RC4 可用,这就是为什么第三个命令应该再次失败的原因。
Qualys SSL Labs 服务器测试 5 应该会检测到此设置,它将在“仅用于 BEAST 缓解的套件(TLS 1.0 及更早版本)”下显示 "SSL_RSA_WITH_RC4_128_MD5"
。