Nginx服务器中关于SSL的安全配置详解
本⽂向你们展⽰如何在nginx的web服务器上设置更强的SSL。我们是通过使SSL⽆效来减弱CRIME攻击的这种⽅法实现。不使⽤在协议中易受攻击的SSLv3以及以下版本并且我们会设置⼀个更强的密码套件为了在可能的情况下能够实现Forward Secrecy,同时我们还启⽤HSTS和HPKP。这样我们就有了⼀个更强、不过时的SSL配置并且我们在Qually Labs SSL 测试中得到了A等级。
我们在nginx的设置⽂档中如下编辑
复制代码代码如下:
/etc/nginx/sited-enabled/yoursite (On Ubuntu/Debian)
或者在
复制代码代码如下:
/etc/nginx/conf.f (On RHEL/CentOS).nginx ssl证书配置
对于整个说明⽂档,你需要编辑服务器配置的服务器那块和443端⼝(SSL配置)。在说明⽂档的最后,你会发现实现了样例的配置。
确保在编辑之前做了备份!
BEAST攻击和RC4算法
简⾔之,就是通过篡改加密算法CBC密码块的加密模式,部分加密流量可以被偷偷地解密。更多的信息请参照以上链接。
禁⽤RC4有⼏个结果。⼀、使⽤差劲⼉浏览器的⽤户将使⽤3DES来代替。3-DES⽐RC4更安全。但是就意味着更加昂贵。你的服务器会因为这样的⽤户开销更⼤。⼆、RC4可以缓解BEAST攻击。因此,禁⽤RC4使TLS 1⽤户容易受到攻击,通过移动他们AES-CBC(通常的服务器端的BEAST“修复”是优先考虑⾼于⼀切的RC4)。我很确信,在BEAST上RC4上的缺陷明显⼤于风险。确实,客户端的缓解(chrome和⽕狐都提供)BEAST已不再是个问题。但对于增长RC4的风险:随着时间的推移更多的密码分析将很表⾯化。
FREAK攻击
FREAK是在密码专家⼩组在所发现的⼀种中间⼈攻击。FREAK就是“Factoring RSA-EXPORT Keys .”。这种攻击可以追溯到90世纪90年代,也就是在美国政府禁⽌出售加密软件到海外的时候,除⾮输出的密码套件中加密密钥的长度不超过512位。被证明是⼀些先进的TLS客户端-包括苹果的SecureTra
nsport和OpenSSL-有⼀个Bug在⾥⾯。这个Bug造成了它们接受了RSA密钥的输出等级甚⾄当客户端都不要求RSA的密钥输出等级。这个Bug造成的影响还是相当严重的:假如客户端是易受攻击的并且服务器⽀持输出RSA,它允许第三⼈通过⼀个活跃的攻击者来减弱连接的质量进⾏攻击。
这⾥是两部分服务器必须接受的“RSA输出等级”攻击。
MITM攻击过成如下:
在客户端的Hello消息中,它请求⼀个标准的“RSA”密码套件。
MITM攻击者改变这个消息为了得到“RSA的输出”.
服务器返回⼀个512位的RSA输出密钥,并⽤它的永久密钥签名。
由于OpenSSL和SecureTransport存有bug,客户端就接受了这个弱密钥。
攻击者分析RSA模块为了恢复正在通信时RSA的解密密钥。
当客户端把加密的“预备主密钥”发送给服务器时,攻击者现在可以解密它从⽽得到TLS的“主密钥”。
从现在起,攻击者就可以看到明⽂了,并且可以注⼊任何他想的东西。
这个页⾯上提供密码套件但是⽀持密码输出等级。确保你的OpenSSl是最近更新过的版本⽽且你的客户端也要使⽤最新的软件。
Heartbleed(⼼脏出⾎)
Hearbleed是⼀个在2014年四⽉OpenSSL密码库⾥被发现的安全漏洞,它被⼴泛⽤在运输层(TLS)协议的实施中。Heartbleed可能被使⽤不管是否使⽤了⼀个易受攻击的OpenSSL,⽐如说在⼀个服务器或者客户端使⽤。它是在DTLS⼼跳扩展(RFC6520)由不合适的输⼊确认(因为没有边界检查)所造成,因此这个漏洞的名字为“⼼跳”.这个漏洞被划为⼀个重读的缓冲区,更多超出允许的数据被读出。
哪些版本的OpenSSL被Heartbleed影响?
不同版本的情况:
OpenSSL 1.0.1 到 1.0.1f (包括) 受攻击。
OpenSSL 1.0.1g不受攻击。
OpenSSL 1.0.0的分⽀不受攻击。
OpenSSL 0.9.8 的分⽀不受攻击。
OpenSSL在2011年12⽉发现这个漏洞⽽且在2012年3⽉14⽇发布OpenSSL1.0.1之前⼀直没有采取措施。2014年4⽉7号发布的OpenSSL1.0.1g修复了这个漏洞。
通过更新OpenSSL就可以免受这个漏洞带来的攻击。
SSL 压缩(犯罪攻击)
通常来说,犯罪攻击使⽤ SSL 压缩来施展它的魔法。SSL 压缩在 nginx1.1.6+/1.0.9+ 中默认是关闭的(如果使⽤ openssl 1.0.0+).
如果你正在使⽤ nginx 或者 OpenSSL 其他早期版本,并且你的发⾏版并没有回迁此选项,那么你需要重新编译不⽀持 ZLIB 的 OpenSSL。这将禁⽌使⽤DEFLATE压缩⽅法来使⽤ OpenSSL。如果你这样做,那么你仍然可以使⽤常规的HTML DEFLATE压缩。
SSLV2 与 SSLv3
SSL v2 并不安全,因此我们需要禁⽤它。我们也可以禁⽤ SSL v3,当 TLS 1.0 遭受⼀个降级攻击时,可以允许⼀个攻击者强迫使⽤ SSL v3 来连接,因此禁⽤“向前保密”。
再次编辑此配置⽂件:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
贵宾⽝攻击和TLS-FALLBACK-SCSV
SSLv3允许利⽤“,这是禁⽤它的⼀个主要原因。Google已经提议⼀种叫的SSL/TLS的拓展,旨在防⽌强制SSL降级。以下是升级后⾃动启⽤的OpenSSL版本:
OpenSSL 1.0.1 有 TLSFALLBACKSCSV 在 1.0.1j 及更⾼的版本.
OpenSSL 1.0.0 有 TLSFALLBACKSCSV 在 1.0.0o 及更⾼的版本.
OpenSSL 0.9.8 有 TLSFALLBACKSCSV 在 0.9.8zc 及更⾼的版本.
密码套件
Forward Secrecy 确保了在永久密钥被泄漏的事件中,会话密钥的完整性。PFS 实现这些是通过执⾏推导每个会话的新密钥来完成。
这意味着当私有密钥被泄露不能⽤来解密SSL流量记录。
密码套件提供 Perfect Forward Secrecy 暂时使⽤ Diffie-Hellman 密钥交换的形式。他们的缺点是开销⼤,这可以通过使⽤椭圆曲线的变异的改进。
我建议以下两个密码套件,后者来⾃ Mozilla 基⾦会。
推荐的密码套件:
复制代码代码如下:
ssl_ciphers 'AES128+EECDH:AES128+EDH';
推荐的密码套件向后兼容(IE6 / WinXP):
复制代码代码如下:
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-
SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-
RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-
SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-
SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
如果您的 OpenSSL 是旧版本,不可⽤密码将被⾃动丢弃。总是使⽤完整的密码套件,让OpenSSL选它所⽀持的。
密码套件的顺序⾮常重要,因为它决定在优先级算法将被选中。上⾯的建议重视算法提供完美的向前保密。
⽼版本的 OpenSSL 可能不会返回算法的完整列表。AES-GCM 和⼀些 ECDHE 相当近,⽽不是出现在⼤多数版本的 Ubuntu OpenSSL 附带或 RHEL。
优先级逻辑
⾸先选择 ECDHE + AESGCM 密码。这些都是 TLS 1.2 密码并没有受到⼴泛⽀持。这些密码⽬前没有已知的攻击⽬标。
PFS 密码套件是⾸选,ECDHE 第⼀,然后 DHE。
AES 128 更胜 AES 256。有讨论是否 AES256 额外的安全是值得的成本,结果远不明显。⽬前,AES128 是⾸选的,因为它提供了良好的安全,似乎真的是快,更耐时机攻击。
向后兼容的密码套件,AES 优先 3DES。暴⼒攻击 AES 在 TLS1.1 及以上,减轻和 TLS1.0 中难以实现。向后不兼容的密码套件,3DES 不存在.
RC4 被完全移除. 3DES ⽤于向后兼容。
强制性的丢弃
aNULL 包含未验证 diffie - hellman 密钥交换,受到中间⼈这个攻击
eNULL 包含未加密密码(明⽂)
EXPORT 被美国法律标记为遗留弱密码
RC4 包含了密码,使⽤废弃ARCFOUR算法
DES 包含了密码,使⽤弃⽤数据加密标准
SSLv2 包含所有密码,在旧版本中定义SSL的标准,现在弃⽤
MD5 包含所有的密码,使⽤过时的消息摘要5作为散列算法
其它的设置
确保你已经添加了以下⼏⾏:
复制代码代码如下:
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
在SSLv3或这是TLSv1握⼿时选择⼀个密码,通常是使⽤客户端的偏好。如果这个指令是启⽤的,那么服务器反⽽是使⽤服务器的偏好。
更多关于SSL preferserver密码的信息
更多关于SSL密码的信息
向前保密(Forward Secrecy)与Diffie Hellman Ephemeral Parameters
向前保密的概念很简单:客户端和服务器协商⼀个可靠的密钥,并在会话结束后销毁。服务器中的RSA私钥⽤来签名客户端和服务器之间交换的Diffie-Hellman密钥。副主密钥从Diffie-Hellman握⼿中得到,并⽤于加密。由于副主密钥在客户端和服务器之间的连接中是明确具体的,并⽤于有限的时间,因此被叫作Ephemeral(短暂的)。
由于有Forward Secrecy,即使攻击者持有服务器的私钥,也不能够解密过去的会话。私钥仅仅⽤来签名DH(Diffie-Hellman)的握⼿,它并没有泄漏副主密钥。Diffie-Hellman确保了副主密钥不会离开客户端和服务器,也不会被中间⼈截获。
1.4.4所有的nginx版本在往Diffiel-Hellman输⼊参数时依赖OpenSSL。不幸的时,这就意味着Ephemeral Diffiel-
Hellman(DHE)会使⽤OpenSSL的这⼀缺陷,包括⼀个1024位的交换密钥。由于我们正在使⽤⼀个2048位的证书,DHE客户端⽐⾮ephemeral客户端将使⽤⼀个更弱的密钥交换。
我们需要产⽣⼀个更强的DHE参数:
cd /etc/ssl/certs
openssl dhparam -out dhparam.pem 4096
然后告诉nginx在DHE密钥交换的时候使⽤它:
复制代码代码如下:
ssl_dhparam /etc/ssl/certs/dhparam.pem;
OCSP 适⽤
在和服务器连接的时候,客户端通过使⽤证书撤销列表(CRL)来验证服务器证书的有效性,或者是使⽤在线证书状态协议(OCSP)记录。但是CRL的问题是:CRL的列表项不断增多,⽽且需要不断地下载。
OCSP是更轻量级的,因为它⼀次只获取⼀条记录。但是副作⽤是,当连接到服务器的时候,OCSP请求必须发送到第三⽅响应者,这增加了延迟,以及失败的可能。实际上,OCSP响应者由CA操控,由于它常常不可靠,导致浏览器由于收不到适时的响应⽽失败。这减少了安全性,因为它允许攻击者对OCSP响应者进⾏DoS攻击来取消验证。
解决⽅案是在TLS握⼿期间,允许服务器发送缓存的OCSP记录,这样来绕过OCSP响应者。这个技术节省了在客户端和OCSP响应者之间的⼀个来回,称为OCSP闭合(OCSP Stapling)。
服务器只在客户端请求的时候,发送⼀个缓存的OCSP响应,通过对CLIENT HELLO的status_request TLS拓展来声明⽀持。⼤多数服务器都会缓存OCSP响应到48⼩时。在常规间隔,服务器会连接到CA的OCSP响应者来获取最新的OCSP记录。OCSP响应者的位置是从签名证书的Authority Information Access 字段来获取。
HTTP Strict Transport Security
如果可能,你应该开启,它指⽰浏览器只通过HTTPS来访问你的站点。
HTTP Public Key Pinning Extension
你同样应该开启。
Public Key Pinning 意味着证书链必须包含处于⽩名单之中的公钥。它确保只在⽩名单中的CA可以对*.example进⾏签名,⽽不是浏览器中保存的任何⼀个CA。
复制代码代码如下:
server {
listen [::]:443 default_server;
ssl on;
ssl_certificate_key /etc/ssl/cert/raymii_org.pem;
ssl_certificate /etc/ssl/cert/ca-bundle.pem;
ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 10s;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
root /var/www/;
index index.html index.htm;
server_;
}
结论
如果你应⽤了上⾯的配置⽂件,你需要重启nginx:
复制代码代码如下:
# Check the config first:
/etc/init.d/nginx configtest
# Then restart:
/etc/init.d/nginx restart
现在使⽤看看你是否得到⼀个漂亮的A。同时,当然,拥有⼀个安全的,牢靠的,作为未来样例的SSL配置。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。