NGINX安全性配置

本文将介绍一些SSL安全性的配置,以此提升网站的安全等级。先给出本博客的SSL配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
server {
listen 443 ssl;
server_name www.wonsikin.com;
server_tokens off;
# 中间证书 + 站点证书
ssl_certificate /home/webapp/ssl/wonsikin.chained.crt;
# 生成证书的密钥
ssl_certificate_key /home/webapp/ssl/wonsikin.com.key;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 60m;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
access_log logs/wonsikin.log main;
if ($request_method !~ ^(GET|HEAD|POST|OPTIONS|DELETE|PUT)$ ) {
return 444;
}
location / {
alias /home/webapp/wonsikin/;
index index.html;
}
}

说明

掩藏NGINX版本号

隐藏NGINX版本号可以增加黑客利用该版本已知的漏洞来攻击服务器的代价。

1
server_tokens off;

禁用不安全的HTTP方法

TRACE 方法是让 Web 服务器端将之前的请求通信环回给客户端的方法。但是一般很少用到,而且容易引发XST(Cross-Site Tracing,跨站追踪)攻击。

1
2
3
if ($request_method !~ ^(GET|HEAD|POST|OPTIONS|DELETE|PUT)$ ) {
return 444;
}

以上配置表明服务器会对GET、HEAD、POST、OPTIONS、DELETE、PUT返回444的状态码,444 是 Nginx 定义的响应状态码,会立即断开连接,没有响应正文。

openssl

心血漏洞(Heartbleed) 是一个于2014年4月公布的 OpenSSL 加密库的漏洞,它是一个被广泛使用的传输层安全(TLS)协议的实现。无论是服务器端还是客户端在 TLS 中使用了有缺陷的 OpenSSL,都可以被利用该缺陷。

升级服务器安装的openssl 到最新版本可以避免这个漏洞。

注意:启用最新版本的openssl,需要把 NGINX 关闭,然后再开启,不是简单的 reload 就可以的。

1
2
3
4
5
./sbin/nginx -s stop
./sbin/nginx
# 执行以下命令是不能启用最新版本的openssl的
./sbin/nginx -s reload

加密套件

设置更健壮的加密套件(cipher suite)来尽可能启用前向安全性(Forward Secrecy)。前向安全性(Forward Secrecy)用于在长期密钥被破解时确保会话密钥的完整性。PFS(完备的前向安全性)是指强制在每个/每次会话中推导新的密钥。
如何设置可以参考Cipherli.st - Strong Ciphers for Apache, nginx and Lighttpd这个网址。
推荐的ssl_ciphers 设置如下:

1
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

同时,确保也添加了如下的配置:

1
2
3
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 60m;

TLS 会话恢复的目的是为了简化 TLS 握手,有两种方案:Session Cache 和 Session Ticket。他们都是将之前握手的 Session 存起来供后续连接使用,所不同是 Cache 存在服务端,占用服务端资源;Ticket 存在客户端,不占用服务端资源。另外目前主流浏览器都支持 Session Cache,而 Session Ticket 的支持度一般。

TLS握手过程中选择一个加密算法时,一般使用客户端的首选算法。如果设置了上述配置,则会替代地使用服务器端的首选算法。

SSL协议

SSLv2 已被证实是不安全的,同时因为 TLS 1.0 在遭受到降级攻击时,会允许攻击者强制连接使用 SSLv3,从而禁用了前向安全性(forward secrecy)。所以ssl_protocols 的配置如下:

1
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

OCSP Stapling

当客户端连接到服务器的时候,客户端会使用 Certificate Revocation List(CRL) 或者 Online Certificate Status Protocol(OCSP)记录校验服务器证书的合法性。CRL 的问题是证书吊销列表已经变得很大,下载太费时。

OCSP相比之下就比较轻量级,因为一次只检索一条记录。但是副作用就是客户端连接服务器的时候,OCSP 请求必须发送到第三方OCSP响应器(OCSP responder),这就可能会存在请求失败的隐患。实际上,证书颁发机构运转的OCSP响应器经常是不可靠的,以至于当浏览器没有及时收到响应的时候就会静默失败。

解决方法是在TLS握手的时候允许服务器发送缓存的OCSP记录,以此绕过OCSP响应器。这种机制就叫做OCSP Stapling,它省掉了客户端和OCSP响应器之间的一个交互。大部分服务器会缓存OCSP响应将近48小时,然后在快过期的时候会连接到OCSP响应器检索最新的OCSP纪录。

在NGINX中增加一下配置来启用OCSP Stapling

1
2
3
4
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

要使OCSP Stapling正常工作,需要知道服务器证书颁布者的证书。如果在ssl_certificate文件中没有包含中级证书( intermediate certificates),需要在ssl_trusted_certificate文件中服务器证书颁布者的证书。

1
ssl_trusted_certificate /etc/ssl/certs/domain.chain.stapling.pem;

可以使用以下命令测试OCSP Stapling是否正常:

1
openssl s_client -connect example.org:443 -tls1 -tlsextdebug -status

以上的配置就能够保证你的网站在 SSL Server Test (Powered by Qualys SSL Labs)中的测试得到A的评分。

SSL Labs评分

参考