完全向前保密

事先申明:这篇文章不是给 PFS 翻译,只是我个人的见解。欲知 PFS 是神马,请自己阅读这里(英文)和这里(英文)。

完全向前保密(Perfect Forward Secrecy,PFS)使用“会话密钥(Session Key)”在会话结束后就过期。“会话密钥”是一个长期密钥(Long-Term Key)的衍生出来的密钥,不会透露额外的密钥。所以,简单来说,黑客今天截取一些通讯资料,明天或者有更好更快的机器帮助他解密,就算破解到这个“会话密钥”,他也只能看到这个会话的内容,其他的通讯是不能用这个已破解的密钥来解密。如果你没有使用 PFS,一旦解密密钥被破解,网站的加密也统统给破解掉了。

软件需求:

  • nginx 1.1.13+
  • nginx 的 ngx_http_ssl_module 模块
  • 一个有效的 SSL 证书
  • OpenSSL 1.0.1+

Forward Secrecy

因为 PFS 使用了『迪菲-赫尔曼加密法』,所以需要一些额外的配置。

1、需要生成一个 dhparam.pem 文件。这个文件在 DH 握手时会跟传给客户端。这是“DHE加密法”需要用上的东西。
2、告诉 Nginx 使用不要使用默认的加密算法。

# Nginx 默认加密算法
ssl_ciphers HIGH:!aNULL:!MD5;

生成 dhparam.pem

输入:openssl dhparam 2048

$ openssl dhparam 2048
Generating DH parameters, 2048 bit long safe prime, generator 2
..+..+...............+
-----BEGIN DH PARAMETERS-----
MBYCEQCHU6UNZoHMF6bPtj21Hn/bAgEC.....
......
-----END DH PARAMETERS-----

保存结果到一个文件叫做:dhparam.pem。内容大概(是一段乱码),这里省掉几百个字母数字:

-----BEGIN DH PARAMETERS-----
MBYCEQCHU6UNZoHMF6bPtj21Hn/bAgEC.....
......
-----END DH PARAMETERS-----

注意:使用 ssl_dhparam 会让 Java6 不能链接到服务器的,使用 Java6 的客户端不支持大于 1024 位的 dhparam。

Forward Secrecy 的加密算法

Julien Vehent 的算法

ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK

Mozilla OpSec 的算法

ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK

注意:这些算法随时都在更新,请留意他们的网页。

在线证书状态协议 OCSP Stapling

给 SSL 加速(可用)。服务器来缓存证书的认证,来做到省掉跟 SSL 发行商的沟通。

NGINX 配置

server {

    listen 443;
    ssl on;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /path/to/signed_cert_plus_intermediates;

    ssl_certificate_key /path/to/private_key;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /path/to/dhparam.pem;

    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:50m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK';

    ssl_prefer_server_ciphers on;
 

    # Enable this if your want HSTS (recommended, but be careful)
    add_header Strict-Transport-Security max-age=15768000;
 

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;
    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
    resolver 8.8.8.8;

    ...
}

参考:
Mozilla Wiki

扩展阅读:
jve.linuxwall.info

qualys.com

测试 SSL 服务器:
https://www.ssllabs.com/ssltest/
https://sslcheck.globalsign.com/


更新了一些 PFS 的见解。

Published by

Galovia

九十度博客站长。