推荐的 ssl_ciphers 用于安全性和兼容性 - 完美的前向保密

信息安全 tls nginx 前向保密
2021-08-24 20:37:58

我目前正在使用具有以下密码的 nginx:

ssl_ciphers HIGH:!aNULL:!eNULL:!LOW:!ADH:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;

我想保持与旧浏览器的兼容性,尤其是旧的移动浏览器,因此不完全禁止 SHA1。

对于 MAC(消息身份验证代码),我如何实现 SHA256 优于 SHA1 并在可能的情况下始终使用。

我可以通过将 SHA256:!SHA: 添加到我的 ssl_ciphers 字符串来强制应用 SHA256,但这也会完全禁止 SHA1。

然而,在开始时使用 ssl_cipher,它往往只使用 SHA1。有什么建议吗?


29.12.2014 更新

感谢大家的建设性意见和讨论。

尽管我仍然认为服务器端 TLS 上Mozilla 页面总体上很好地涵盖了该主题 - 我只推荐现代兼容性,但应从其中删除 DSS 密码并明确禁止(!DSS) Anti-weakpasswords 的评论 - 感谢您发现它。

ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK

有趣的是,ssllabs 并没有为此发出警报或降低利率......

此外,我更喜欢使用自定义生成的 diffie hellman 参数。即使标准的显然被认为是安全的。什么是 OpenSSL 标准 Diffie Hellmann 参数(素数)?

openssl dhparam -check -out /etc/ssl/private/dhparams.pem 2048

如果您愿意,可以将其增加到 4096 以获得偏执和乐趣。

4个回答

首先,让我们非常简要地回顾一下密码套件协商的工作原理。例如,我们可以使用从第 7.4.1.2 节开始的 TLS 1.2 文档 RFC 5246 以简短的形式查看:

  • ClientHello:客户端告诉服务器客户端支持哪些密码套件
  • 现在服务器选择一个
  • 我将讨论如何控制它选择下一个!
  • ServerHello:服务器告诉客户端它选择了哪个密码套件,或者给客户端一个失败消息。

现在,至于实际的选择。我使用了nginx ssl 模块文档Qualys 2013 中关于为前向保密配置 Apache、Nginx 和 OpenSSL 的文章,以及Hynek Hardening Your Web Server's SSL Ciphers文章作为参考。后两者涵盖 Apache 和 Nginx(因为两者都使用 OpenSSL 作为基础)。

本质上,您需要告诉 Nginx 使用您选择的顺序,并且您需要选择一个顺序。要查看该订单的结果,您可以使用 OpenSSL 命令行,例如

openssl ciphers -v 'EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED'

注意:您可能希望从该字符串中删除 :!3DES;3 密钥三重 DES 效率不高,但它本身对于或多或少 112 位的安全性仍然是安全的,并且非常非常普遍。

使用上述命令来确定哪些密码套件在您的配置中最受青睐和最不受青睐,并对其进行更改,直到您喜欢结果为止。我给出的参考文献有自己的字符串;我对其稍作修改以获得上述示例(例如,删除 RC4 和 SEED,并将每个 TLS 1.2 密码套件置于任何“SSLv3”密码套件之上)。

然后,特别是对于 Nginx,您将更改配置文件以包含以下内容:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED";

如果您真的坚持,请将 SSLv3 添加到 ssl_protocols。

ssl_prefer_server_ciphers 将通知 nginx 使用我们指定的顺序,并忽略客户端显示其密码列表的顺序。现在,如果 ClientHello 和 OpenSSL ciphers -v ... 给出的列表之间唯一共享的密码套件是我们最不喜欢的密码,这当然是 nginx 将使用的。如果没有匹配,那么我们向客户端发送失败通知。

ssl_ciphers 命令是这里的选择,因为 nginx 将通知 OpenSSL 我们首选的密码套件列表。请使用 openssl ciphers -v 命令查看您在平台上获得的结果。理想情况下,在更改 OpenSSL 版本后再次检查。

另外,请阅读Scott Helme 关于在 nginx 中设置 HSTS(HTTP 严格传输安全)的文章,这将允许主机在客户端强制使用 HTTPS。确保在带有 ssl listen 语句的 http 块中包含 HSTS 标头。

编辑添加:至少在此之后(如果不是之前),请前往Qualys SSL Labs以查看 HTTPS 安全信息并测试您的服务器,该服务器在过去几年中一直保持最新状态。建议会定期更改,有时甚至会经常自行更改(例如,RC4,几乎会引发鞭打)。您甚至可以测试您的浏览器

Mozilla 有一个在线工具,可以帮助您选择正确的密码套件。

https://mozilla.github.io/server-side-tls/ssl-config-generator/

它会让您输入您的服务器版本、软件版本等,然后在安全性和旧版支持之间进行选择。

对于其他等效的密码套件,OpenSSL 自然会更喜欢更新的 MAC 。例如,openssl ciphers -v您的密码字符串的冗长输出以:

ECDHE-RSA-AES256-GCM-SHA384    TLSv1.2  Kx=ECDH        Au=RSA    Enc=AESGCM(256)    Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AESGCM(256)    Mac=AEAD
ECDHE-RSA-AES256-SHA384        TLSv1.2  Kx=ECDH        Au=RSA    Enc=AES(256)       Mac=SHA384
ECDHE-ECDSA-AES256-SHA384      TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AES(256)       Mac=SHA384
ECDHE-RSA-AES256-SHA           SSLv3    Kx=ECDH        Au=RSA    Enc=AES(256)       Mac=SHA1
ECDHE-ECDSA-AES256-SHA         SSLv3    Kx=ECDH        Au=ECDSA  Enc=AES(256)       Mac=SHA1

当然,TLS 只会使用服务器和客户端相互支持的密码套件,Chrome 和 Firefox 都不支持 HMAC-SHA256 密码套件。由于 HMAC-SHA1(甚至 HMAC-MD5)仍然被认为是安全的,我相信他们的开发人员(以及 NSS 的开发人员,他们都使用的 TLS 库)对浪费开发人员的努力和 TLS 握手大小添加新的、不必要的和向后的内容持怀疑态度-不兼容的密码套件。

例如,按优先顺序查看 Chrome 33 支持的密码套件

  1. ChaCha20-Poly1305 ,
  2. AES-128-GCM,
  3. 带有 HMAC-SHA1 的 AES-256-CBC,
  4. RC4(呃)和带有 HMAC-SHA1 的 AES-128-CBC,...

OpenSSL 不支持 ChaCha20-Poly1305。如果您的也不支持 AES-GCM (???) 并使用 RSA 证书,ECDHE-RSA-AES256-SHA那么 Chrome 将使用密码套件。(Firefox 29 将使用ECDHE-RSA-AES128-SHA.)

(您在其他网站上看到的“SHA-256”密码套件大概是 ChaCha20-Poly1305 或 AES-128-GCM,它们是不使用 HMAC的AEAD ,但其密码套件在PRF

为了获得最佳兼容性,cloudflare-cipher-suite 并不是最好的;我发现以下更好:

# suggestion from sslabs / including PFS, good compatibility
#ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;


# suggestion my mozilla-server-team - good compatibility, pfs
#ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK;

当您使用ssllabs检查每个设置时,您会发现这两个套件的以下语句:

  • 前向保密 是(对于大多数浏览器)稳健

在您建议的 cipher_suite 上,它说:

  • 前向保密 是(使用现代浏览器)

附加信息:Nginx + SSL + SPDY 指南