nginx ssl设置详解

SSL 协议

SSLv2是不安全的,绝对不能用,SSLv3 能不用则不用,正常情况下用不到的,推荐使用 TLSv1 TLSv1.1 TLSv1.2,附配置代码:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

加密算法

RC4不要用,再就是 OpenSSL 记得更新到最新版,可以避免很多麻烦。别的也没什么了,附代码:

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";

ssl_prefer_server_ciphers on;

ECDHE+AESGCM 加密是首选的。它们是 TLS 1.2 加密算法,现在还没有广泛支持。当然也没有破解的方案。
PFS 加密套件好一些,首选 ECDHE,然后是 DHE
AES 128 要好于 AES 256AES 256 会造成更大的性能消耗,但是带来的安全提升是有限的。反之还能承受更大压力。
在向后兼容的加密套件里面,AES 要优于 3DES。在 TLS 1.1及其以上,减轻了针对 AES 的野兽攻击(BEAST)的威胁,而在 TLS 1.0上则难以实现该攻击。在非向后兼容的加密套件里面,不支持 3DES
RC4 整个不支持了。3DES 用来向后兼容。
强制丢弃的算法
aNULL 包含了非验证的 Diffie-Hellman 密钥交换,这会受到中间人(MITM)攻击
eNULL 包含了无加密的算法(明文)
EXPORT 是老旧的弱加密算法,是被美国法律标示为可出口的
RC4 包含使用了已弃用的 ARCFOUR 的加密算法
DES 包含使用了弃用的数据加密标准(DES)的加密算法
SSLv2 包含了定义在旧版本 SSL 标准中的所有算法,现已弃用
MD5 包含了使用已弃用的 MD5 的所有算法
但是 ECC 证书的部署不大一样,加密套件和 RSA 不一样,用错之后会影响向前安全性(Forward secrecy)。
加密套件应该这么改:

ssl_ciphers "EECDH+CHACHA20 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 !RC4";

而根据https://cipherli.st/的推荐,可以进一步改为:

ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

前向安全性(Forward Secrecy)

首先 Nginx 配置上如下代码:

ssl_dhparam /your/path/to/dhparam.pem;

pem 文件是这样生成的:

openssl dhparam -out dhparam.pem 4096

然后会显示:

This is going to take a long time  
.......+...........................+............................+............................+............++*++*++*

这真的会”take a long time”.但根据每台机器的性能不同而花费的时间不同.

dhparam 算法是在 2^4096 个数字中找出两个质数,所以需要的时间挺长。….. 意思是有可能的质数,+ 是正在测试的质数,* 是已经找到的质数。

前向安全性(Forward Secrecy)的概念很简单:客户端和服务器协商一个永不重用的密钥,并在会话结束时销毁它。服务器上的 RSA 私钥用于客户端和服务器之间的 Diffie-Hellman 密钥交换签名。从 Diffie-Hellman 握手中获取的预主密钥会用于之后的编码。因为预主密钥是特定于客户端和服务器之间建立的某个连接,并且只用在一个限定的时间内,所以称作短暂模式(Ephemeral)。
如果使用前向安全机制,攻击者取得了一个服务器的私钥,他是不能解码之前的通讯信息的。这个私钥仅用于 Diffie Hellman 握手签名,并不会泄露预主密钥。Diffie Hellman 算法会确保预主密钥绝不会离开客户端和服务器,而且不能被中间人攻击所拦截。
所有版本的 nginx 都依赖于 OpenSSL 给 Diffie-Hellman 的输入参数。如果不特别声明,将使用 OpenSSL 的默认设置,1024 位密钥。这绝壁是不安全的,因为我们正在使用 2048 位证书,所以要有一个更强大的 DH

HTTP 严格传输安全(HSTS)(HTTP Strict Transport Security)

HTTP严格传输安全(英语:HTTP Strict Transport Security,缩写:HSTS)是一套由互联网工程任务组发布的互联网安全策略机制。网站可以选择使用HSTS策略,来让浏览器强制使用HTTPS与网站进行通信,以减少会话劫持风险。
HSTS的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。服务器开启HSTS的方法是,当客户端通过HTTPS发出请求时,在服务器返回的超文本传输协议响应头中包含Strict-Transport-Security字段。非加密传输时设置的HSTS字段无效。

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

includeSubDomains是可选的,用来指定是否作用于子域名。支持HSTS的浏览器遇到这个响应头,会把当前网站加入HSTS列表,然后在max-age指定的秒数内,当前网站所有请求都会被重定向为https。即使用户主动输入http://或者不输入协议部分,都将重定向到https://地址。

X-Frame-Options 响应头

X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在 <frame>, <iframe> 或者 <object> 中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。
X-Frame-Options 有三个值:
DENY:表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
SAMEORIGIN:表示该页面可以在相同域名页面的 frame 中展示。
ALLOW-FROM uri:表示该页面可以在指定来源的 frame 中展示。
换一句话说,如果设置为 DENY,不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载。另一方面,如果设置为 SAMEORIGIN,那么页面就可以在同域名页面的 frame 中嵌套。

X-Content-Type-Options 响应头

互联网上的资源有各种类型,通常浏览器会根据响应头的Content-Type字段来分辨它们的类型。例如:”text/html”代表html文档,”image/png”是PNG图片,”text/css”是CSS样式文档。然而,有些资源的Content-Type是错的或者未定义。这时,某些浏览器会启用MIME-sniffing来猜测该资源的类型,解析内容并执行。
例如,我们即使给一个html文档指定Content-Type为”text/plain”,在IE8-中这个文档依然会被当做html来解析。利用浏览器的这个特性,攻击者甚至可以让原本应该解析为图片的请求被解析为JavaScript。通过下面这个响应头可以禁用浏览器的类型猜测行为:

add_header X-Content-Type-Options nosniff;

这个响应头的值只能是nosniff,可用于IE8+和Chrome。

配置 OCSP 装订

ssl_stapling on;  
ssl_stapling_verify on;  
ssl_trusted_certificate /you/path/to/domain.chain.pem;  
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;

domain.chain.pem 里面是域名证书到 ROOT 证书的一个链。
连接到一个服务器时,客户端应该使用证书吊销列表(CRL)或在线证书状态协议(OCSP)记录来校验服务器证书的有效性。CRL 存在一个问题,它已经增长的太快,永远也下载不完。
OCSP 更轻量一些,只需发一个请求。但是副作用是访问一个站点时必须对第三方 OCSP 响应服务器发起 OCSP 请求,这就增加了延迟带来的潜在隐患。事实上,CA 所运营的 OCSP 响应服务器非常不可靠,浏览器如果不能及时收到答复,就会静默失败。攻击者通过 DDoS 攻击一个 OCSP 响应服务器可以禁用其校验功能,这样就降低了安全性。
解决方法是允许服务器在 TLS 握手中发送缓存的 OCSP 记录,以绕开 OCSP 响应服务器。这个机制减少了客户端和 OCSP 响应服务器之间的通讯,称作 OCSP 装订。
客户端会在它的 CLIENT HELLO 中告知其支持 status_request TLS 扩展,服务器仅在客户端请求它的时候才发送缓存的 OCSP 响应。
大多数服务器最长会缓存 OCSP 48 小时。服务器会按照常规的间隔连接到 CA 的 OCSP 响应服务器来获取刷新的 OCSP 记录。OCSP 响应服务器的位置可以从签名的证书中 Authority Information Access 字段中获得。

nginx里边SSL的完整配置

    ssl on;
    #文件位置
    ssl_certificate /path/to/pem;
    ssl_certificate_key /path/to/key;
    ssl_dhparam /path/to/dhparams.pem;
    #会话进程设置
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_session_timeout 5m;
    #加密套件设置
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_prefer_server_ciphers on;
    ssl_ecdh_curve secp384r1;
    #OCSP配置
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 216.69.185.17 208.109.255.17 valid=300s;
    resolver_timeout 5s;
    #HTTP安全配置
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;

文章拼凑来源:
https://cipherli.st/
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/X-Frame-Options
https://okwoo.com/open-the-hsts-http-strict-transport-security-the-importance-of
https://www.pupboss.com/nginx-add-ssl/
https://imququ.com/post/web-security-and-response-header.html

发表评论