本文档指导您在 NGINX HTTP 服务器上安装并配置 SSL 证书,关于 NGINX 在各个平台上的安装不再涉及。
由于近年 OpenSSL 高危漏洞不断,因此强烈推荐您在开始配置之前首先升级 OpenSSL 到最新版本。
#### 配置 SSL 证书
完整的 SSL 证书分为四个部分:
* CA 根证书 (root CA)
* 中级证书 (Intermediate Certificate)
* 域名证书
* 证书密钥 (仅由您持有)
以 COMODO PositiveSSL 证书为例,您将收到四份文件:
* 根证书 - `AddTrustExternalCARoot.crt`
* 中级证书 - `COMODORSAAddTrustCA.crt`
* 中级证书 - `COMODORSADomainValidationSecureServerCA.crt`
* 您的域名证书 - `example_com.crt`
**或者,您会收到 2 个文件(新签发证书大部分会收到两个文件)**
* CA 证书串 - `example_com.ca-bundle`
* 您的域名证书 - `example_com.crt`
您要依照 **域名证书 -> 中间证书 -> 根证书** 的顺序串联为证书链,才能被绝大多数浏览器信任。使用 `cat` 命令串联证书:
```
cat example_com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > example_com.bundle.crt
```
如果您收到的是 `example_com.ca-bundle` 的形式,请直接和 `example_com.crt` 串联。命令为:
```
cat example_com.crt example_com.ca-bundle > example_com.bundle.crt
```
得到 `example_com.bundle.crt` 后,和密钥文件 `example_com.key` 一同上传至服务器并保存在安全的位置,例如 `/etc/ssl/private` 目录下(没有此目录请创建)。
#### 修改 NGINX 站点配置
下面是一份针对较新版本的 NGINX 的 SSL 部分配置,请将其添加到站点配置文件中 `server` 的部分,并根据注释和您的需求修改。
```
listen 443 ssl; # 侦听端口
# listen [::]:443 ssl ipv6only=on; # 如果您希望同时侦听 IPv6,请取消此行注释
server_name example.com; # 请改为您的域名
ssl_certificate /etc/ssl/private/example_com.bundle.crt; # 证书链
ssl_certificate_key /etc/ssl/private/example_com.key; # 密钥
ssl_protocols TLSv1.2 TLSv1.1 TLSv1; # 支持的协议,Windows XP 不支持
ssl_prefer_server_ciphers on; # 启用 Forward Secrecy
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 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
keepalive_timeout 70;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
```
如果您希望至少支持一些老式浏览器,并且在能够使用 ECDHE 时尽可能使用此算法,您可以使用下面的配置:
```
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 +RC4 RC4";
```
能够最低支持到 Android 2.3 (_不支持 IE6_) 的方案:
```
ssl_ciphers "CHACHA20:ECDH+AESGCM:ECDH+AES256:RSA+AESGCM:RSA+AES:DH+AESGCM:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+3DES:!aNULL:!eNULL:!EXPORT:!CAMLLIA:!DES:!MD5:!PSK:!RC4";
```
您可能需要使用 LibreSSL 以支持 `CHACHA20` 算法。
或者使用最简单的方案:
```
ssl_ciphers "EECDH+aRSA+AES";
```
#### 生成 DHE 参数
为了避免使用 OpenSSL 默认的 1024bit DHE 参数,我们需要生成一份更强的参数文件:
```
cd /etc/ssl/certs
openssl dhparam -out dhparam.pem 4096
```
**建议您使用性能强劲的平台生成此文件**,例如最新版的至强物理机。如果您只有一台小型 VPS,请使用 `openssl dhparam -out dhparam.pem 2048` 命令生成 2048bit 的参数文件。
完成后,在 SSL 配置下添加一行:
```
ssl_dhparam /etc/ssl/certs/dhparam.pem;
```
#### 启用 HSTS
HTTP Strict Transport Security (HSTS) 可以使浏览器第一次访问您的站点后即记住仅通过 HTTPS 与您的站点通信,可以大大提升安全性。
在 SSL 配置下添加:
```
add_header Strict-Transport-Security max-age=63072000;
# add_header X-Frame-Options DENY; # 如果不需要引用 iframe 则可以加上
add_header X-Content-Type-Options nosniff;
```
#### 强制定向到 HTTPS
您需要一个单独 `server` 配置用于侦听 HTTP 80 端口,然后所有发送到这里的请求定向到 HTTPS 协议。
```
server {
listen 80;
# listen [::]:80; # 如果您需要同时侦听 IPv6,请取消此行注释
server_name example.com; # 您的域名
location / {
return 301 https://example.com$request_uri; # 要重定向的地址,请将 example.com 改为您的域名
}
}
```
或者使用 `rewrite`:
```
rewrite ^ https://example.com$request_uri? permanent; # 请将 example.com 改为您的域名
```
#### 一份完整样例
这里是基于 NGINX 1.4.6 的一份完整配置样例。请根据您的需求修改使用。
```
server {
listen 80;
# listen [::]:80;
server_name www.example.com;
rewrite ^ https://www.example.com$request_uri? permanent;
}
server {
listen 443 ssl;
# listen [::]:443 ssl;
server_name www.example.com;
ssl on;
ssl_certificate /etc/ssl/private/www_example_com.crt;
ssl_certificate_key /etc/ssl/private/www_example_com.key;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
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 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
keepalive_timeout 70;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security max-age=63072000;
# add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
```