本文档指导您在 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

命令串联证书:


<span class="hljs-title">cat</span> example_com.crt COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt &gt; example_com.bundle.crt

如果您收到的是

example_com.ca-bundle

的形式,请直接和

example_com.crt

串联。命令为:


<span class="hljs-title">cat</span> example_com.crt example_com.ca-bundle &gt; example_com.bundle.crt

得到

example_com.bundle.crt

后,和密钥文件

example_com.key

一同上传至服务器并保存在安全的位置,例如

/etc/ssl/private

目录下 (没有此目录请创建)。

# 修改 NGINX 站点配置

下面是一份针对较新版本的 NGINX 的 SSL 部分配置,请将其添加到站点配置文件中

server

的部分,并根据注释和您的需求修改。


<span class="hljs-title">listen</span> <span class="hljs-number">443</span> ssl;    <span class="hljs-comment"># 侦听端口</span>
<span class="hljs-comment"># listen [::]:443 ssl ipv6only=on;    # 如果您希望同时侦听 IPv6,请取消此行注释</span>

<span class="hljs-title">server_name</span> example.com;    <span class="hljs-comment"># 请改为您的域名</span>

<span class="hljs-title">ssl_certificate</span> /etc/ssl/private/example_com.bundle.crt;    <span class="hljs-comment"># 证书链</span>
<span class="hljs-title">ssl_certificate_key</span> /etc/ssl/private/example_com.key;    <span class="hljs-comment"># 密钥</span>
<span class="hljs-title">ssl_protocols</span> TLSv1.<span class="hljs-number">2</span> TLSv1.<span class="hljs-number">1</span> TLSv1;    <span class="hljs-comment"># 支持的协议,Windows XP 不支持</span>
<span class="hljs-title">ssl_prefer_server_ciphers</span> <span class="hljs-built_in">on</span>;    <span class="hljs-comment"># 启用 Forward Secrecy</span>
<span class="hljs-title">ssl_ciphers</span> <span class="hljs-string">"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"</span>;
<span class="hljs-title">keepalive_timeout</span> <span class="hljs-number">70</span>;
<span class="hljs-title">ssl_session_cache</span> shared:SSL:<span class="hljs-number">10m</span>;
<span class="hljs-title">ssl_session_timeout</span> <span class="hljs-number">10m</span>;

如果您希望至少支持一些老式浏览器,并且在能够使用 ECDHE 时尽可能使用此算法,您可以使用下面的配置:


<span class="hljs-title">ssl_ciphers</span> <span class="hljs-string">"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"</span>;

能够最低支持到 Android 2.3 (不支持 IE6) 的方案:


<span class="hljs-title">ssl_ciphers</span> <span class="hljs-string">"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"</span>;

您可能需要使用 LibreSSL 以支持

CHACHA20

算法。

或者使用最简单的方案:


<span class="hljs-title">ssl_ciphers</span> <span class="hljs-string">"EECDH+aRSA+AES"</span>;

# 生成 DHE 参数

为了避免使用 OpenSSL 默认的 1024bit DHE 参数,我们需要生成一份更强的参数文件:


<span class="hljs-built_in">cd</span> /etc/ssl/certs
openssl dhparam -out dhparam.pem <span class="hljs-number">4096</span>

建议您使用性能强劲的平台生成此文件,例如最新版的至强物理机。如果您只有一台小型 VPS,请使用

openssl dhparam -out dhparam.pem 2048

命令生成 2048bit 的参数文件。

完成后,在 SSL 配置下添加一行:


<span class="hljs-title">ssl_dhparam</span> /etc/ssl/certs/dhparam.pem;

# 启用 HSTS

HTTP Strict Transport Security (HSTS) 可以使浏览器第一次访问您的站点后即记住仅通过 HTTPS 与您的站点通信,可以大大提升安全性。

在 SSL 配置下添加:


<span class="hljs-title">add_header</span> Strict-Transport-Security max-age=<span class="hljs-number">63072000</span>;
<span class="hljs-comment"># add_header X-Frame-Options DENY;  # 如果不需要引用 iframe 则可以加上</span>
<span class="hljs-title">add_header</span> X-Content-Type-Options nosniff;

# 强制定向到 HTTPS

您需要一个单独

server

配置用于侦听 HTTP 80 端口,然后所有发送到这里的请求定向到 HTTPS 协议。


<span class="hljs-title">server</span> {
    <span class="hljs-title">listen</span> <span class="hljs-number">80</span>;
    <span class="hljs-comment"># listen [::]:80;    # 如果您需要同时侦听 IPv6,请取消此行注释</span>
    <span class="hljs-title">server_name</span> example.com;    <span class="hljs-comment"># 您的域名</span>

    <span class="hljs-title">location</span> / {
        <span class="hljs-title">return</span> <span class="hljs-number">301</span> <span class="hljs-url">https://example.com<span class="hljs-variable">$request_uri</span></span>;    <span class="hljs-comment"># 要重定向的地址,请将 example.com 改为您的域名</span>
    }
}

或者使用

rewrite

:


<span class="hljs-title">rewrite</span><span class="hljs-regexp"> ^</span> <span class="hljs-url">https://example.com<span class="hljs-variable">$request_uri</span>?</span> <span class="hljs-built_in">permanent</span>;    <span class="hljs-comment"># 请将 example.com 改为您的域名</span>

# 一份完整样例

这里是基于 NGINX 1.4.6 的一份完整配置样例。请根据您的需求修改使用。


<span class="hljs-title">server</span> {
        <span class="hljs-title">listen</span> <span class="hljs-number">80</span>;
        <span class="hljs-comment"># listen [::]:80;</span>
        <span class="hljs-title">server_name</span> www.example.com;
        <span class="hljs-title">rewrite</span><span class="hljs-regexp"> ^</span> <span class="hljs-url">https://www.example.com<span class="hljs-variable">$request_uri</span>?</span> <span class="hljs-built_in">permanent</span>;
}

<span class="hljs-title">server</span> {
        <span class="hljs-title">listen</span> <span class="hljs-number">443</span> ssl;
        <span class="hljs-comment"># listen [::]:443 ssl;</span>

        <span class="hljs-title">server_name</span> www.example.com;

        <span class="hljs-title">ssl</span> <span class="hljs-built_in">on</span>;
        <span class="hljs-title">ssl_certificate</span> /etc/ssl/private/www_example_com.crt;
        <span class="hljs-title">ssl_certificate_key</span> /etc/ssl/private/www_example_com.key;
        <span class="hljs-title">ssl_prefer_server_ciphers</span> <span class="hljs-built_in">on</span>;
        <span class="hljs-title">ssl_dhparam</span> /etc/ssl/certs/dhparam.pem;
        <span class="hljs-title">ssl_protocols</span> TLSv1 TLSv1.<span class="hljs-number">1</span> TLSv1.<span class="hljs-number">2</span>;
        <span class="hljs-title">ssl_ciphers</span> <span class="hljs-string">"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"</span>;
        <span class="hljs-title">keepalive_timeout</span> <span class="hljs-number">70</span>;
        <span class="hljs-title">ssl_session_cache</span> shared:SSL:<span class="hljs-number">10m</span>;
        <span class="hljs-title">ssl_session_timeout</span> <span class="hljs-number">10m</span>;

        <span class="hljs-title">add_header</span> Strict-Transport-Security max-age=<span class="hljs-number">63072000</span>;
        <span class="hljs-comment"># add_header X-Frame-Options DENY;</span>
        <span class="hljs-title">add_header</span> X-Content-Type-Options nosniff;

        <span class="hljs-title">root</span> /var/www/example.com;
        <span class="hljs-title">index</span> index.html;

        <span class="hljs-title">location</span> / {
                <span class="hljs-title">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.html;
        }
}

发表评论