NginxConfig

钱,就像一个熨斗,能烫平生活的所有褶皱。------>电影《寄生虫》

Nginx配置

NginxConfig

这里推荐给大家一个生成Nginx配置文件的web工具。

网址是:https://www.digitalocean.com/community/tools/nginx

Nginx介绍

Nginx (engine x) 是一个高性能的 Web 服务器和反向代理服务器,也是一个 IMAP/POP3/SMTP 服务器。它由俄罗斯程序员 Igor Sysoev 于 2002 年开始开发。Nginx 是增长最快的 Web 服务器,市场份额已达 33.3%。全球使用量排名第二,2011 年成立商业公司。

Nginx 分支

  • Openresty:作者 @agentzh(章宜春)开发的,最大特点是引入了 ngx_lua 模块,支持使用 Lua 开发插件,并且集合了很多丰富的模块,以及 Lua 库
  • Tengine:主要是淘宝团队开发。特点是融入了因淘宝自身的一些业务带来的新功能。
  • Nginx 官方版本,更新迭代比较快,并且提供免费版本和商业版本

Nginx支持反向代理、负载均衡,具有高可靠性,是单Master多worker模式。

Nginx具有高可扩展性,且高度模块化。

Nginx是事件驱动的非阻塞I/O模型。

Nginx消耗内存极低,且支持热部署。

Nginx应用

  • 静态文件服务器
  • 反向代理,负载均衡
  • WAF防火墙,安全防御
  • 智能路由(企业级灰度测试、地图 POI 一键切流)
  • 灰度发布
  • 消息推送,推流服务器
  • 图片实时压缩
  • 防盗链
  • 静态化

SSL优化

缓存连接凭据

存 SSL 连接凭据可以避免频繁握手带来的速度降低和性能损耗。

TLS 协议有两类会话缓存机制:会话标识 session ID 与会话记录 session ticket。session ID 由服务器端支持,协议中的标准字段,因此基本所有服务器都支持,服务器端保存会话ID以及协商的通信信息,Nginx 中1M 内存约可以保存4000个 session ID 机器相关信息,占用服务器资源较多;而 session ticket 属于一个 TLS 扩展字段,需要服务器和客户端都支持。

二者对比,主要是保存协商信息的位置与方式不同,类似与 HTTP 中的 session 与 cookie。都存在的情况下,Nginx 优先使用 session_ticket。

# SSL
ssl_session_timeout 1d;
# 过期时间,分钟
ssl_session_cache shared:SSL:10m;
# SSL session 缓存区大小
ssl_session_tickets off;

Forward Secrecy(前向加密)

forward secrecy 也称之为 perfect forward secrecy,或者 PFS。称之为完美远期加密。是在HTTPS基础上进一步保护用户电脑同服务器之间的加密通讯。

其解决的一个安全场景就是,如果服务器同用户间的加密通讯内容被窃听,也被储存下来,这些被加密的内容虽然当时无法被解密,被破解,但是当日后,服务器的SSL密钥被取得后(不管是何种原因被取得密钥),这些过往的内容是可以用这个密钥来解密的。这样虽然时效性可能差些,但是仍然是会有被破解的危险存在。

而采用 完美远期加密 的 SSL 或者 HTTPS 通讯,加密钥匙只是短暂性的,而且不能从服务器的 SSL 密钥中推算出来,这样即使日后 SSL 密钥被第三方取得,过去和未来的 HTTPS 通讯仍然安全,窃听者始终无法破解所窃听的内容(以目前的技术而言)。

目前只有用 ephemeral Diffie-Hellman 的算法才算是完美远期加密

配置方法

在终端运行(建议把这个 Diffie-Hellman 参数文件和证书放在一起)

openssl dhparam -out dhparam.pem 2048

在 Nginx 的配置文件中加入:

# Diffie-Hellman parameter for DHE ciphersuites
ssl_dhparam /etc/nginx/dhparam.pem;

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

HSTS 简单说就是在一定时间内强制客户端使用 HTTPS 访问页面。原理如下:

  • 在服务器响应头中添加 Strict-Transport-Security,可以设置 max-age
  • 用户访问时,服务器种下这个头
  • 下次如果使用 HTTP 访问,只要 max-age 未过期,客户端会进行内部跳转,可以看到 307 Redirect Internel 的响应码(注意是客户端浏览器相应的,这里给服务器省下了一次 302 跳转)
  • 变成 HTTPS 访问源服务器

这个过程有效避免了中间人对 80 端口的劫持。但是这里存在一个问题:如果用户在劫持状态,并且没有访问过源服务器,那么源服务器是没有办法给客户端种下 Strict-Transport-Security 响应头的(都被中间人挡下来了)。如何解决?请自行谷歌 HSTS preload。

需要注意的是,只有启用 preload 之后才是严格意义上安全的 HTTPS。否则都可能在最薄弱环节被攻破。比如:

允许 SSL 连接但不强制从 HTTP 跳转到 HTTPS,用户访问 HTTP 被劫持

部署了 HSTS,但用户第一次访问是 HTTP 的,Strict-Transport-Security 的响应头没有作用的机会,还是被劫持

开启HSTS

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

Nginx ocsp Stapling

OCSP (Online Certificate Status Protocol) 通常由 CA 提供,用于在线实时验证证书是否合法有效,这样客户端就可以根据证书中的 OCSP 信息,发送查询请求到 CA 的验证地址,来检查此证书是否有效。

然而这些默认查询 OCSP 的客户端在获得查询结果的响应前势必会一直阻塞后续的事件,在网络情况堪忧的情况下(尤其是大陆地区)会造成较长时间的页面空白。

而 OCSP Stapling ,顾名思义,是将查询 OCSP 接口的工作交给服务器来做,服务器除了可以直接查询 OCSP 信息,还可以仅进行少数次查询并将响应缓存起来。当有客户端向服务器发起 TLS 握手请求时,服务器将证书的 OCSP 信息随证书链一同发送给客户端,从而避免了客户端验证会产生的阻塞问题。由于 OCSP 响应是无法伪造的,因此这一过程也不会产生额外的安全问题。

在服务器上部署ocsp装订,能大大缓解链接数与高并发量。省去多次握手操作,使网站访问速度更快。

  1. 获取证书

    在您完成服务证书的申请之后,一般会给您两个文件,一个是crt或者pem格式结尾的是站点本身的证书文件,例如www.domainname.com.crt; 还有填写csr之后以key格式结尾并下载的私钥文件,例如www.domainname.com.key; 除了站点证书以外,我们还需要中级证书以及根证书。首先打开浏览器,输入您之前部署好的证书的站点网址,这里以本博客为例,如下图所示:

    NginxConfig

    NginxConfig

    然后点击查看证书,选择-详细信息,最后复制到文件;

    NginxConfig

    如下图中,编码格式选择Base64-cer格式;

    !NginxConfig

    选择要导出的文件名,然后保存!

    NginxConfig

    NginxConfig

    PS: 然后按照相同的操作,导出根证书。中级证书名称为:issuer.crt.cer 根证书名称为:root.crt.cer

  2. 将三份证书上传到服务器,生成OCSP Stapling验证文件。即是将中级证书与根证书合并一起。注意,中级证书在上、根证书在下。

    Linux中使用如下命令:

    cat issuer.crt.cer >> chain.crt
    cat root.crt.cer >> chain.crt

    Windows下使用文本编辑打开中级证书与根证书分别按照中级证书在上、根证书在下的顺序排列合并,然后重命名即可.

    最后合并生成的chain.crt就是所需的ocsp stapling验证文件.

  3. Nginx 启用 OCSP Stapling

    在nginx的主配置文件中,http模块中添加如下配置;这里需要注意的是在HTTP模块中,就代表所有的站点都将启用OCSP Stapling。

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 223.5.5.5 223.6.6.6 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 114.114.114.114 valid=60s;
    resolver_timeout 2s;

    然后在该站点的server模块中配置如下,前两行是您之前的HTTPS配置,ssl_trusted_certificate是您要添加的配置:

    # SSL
    ssl_certificate /etc/pki/nginx/ihere.io/fullchain.crt;
    ssl_certificate_key /etc/pki/nginx/ihere.io/privkey.key;
    ssl_trusted_certificate /etc/pki/nginx/ihere.io/chain.crt;

    然后检测配置并重载:

    nginx -t
    nginx -s reload

    PS: 如果只针对该站点启用,而不想对该nginx下的所有站点启用,之需要在该站点的server添加如下内容:

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /path/to/certs/chained.pem;
  4. 随后验证OCSP Stapling是否开启

    手动验证

    echo QUIT | openssl s_client -connect ihere.io:443 -status 2> /dev/null | grep -A 17 ‘OCSP response:‘

    若出现一下内容,则开启成功:

    OCSP response: 
    ======================================
    OCSP Response Data:
        OCSP Response Status: successful (0x0)
        Response Type: Basic OCSP Response
        Version: 1 (0x0)
        Responder Id: 9058FFB09C75A8515477B1EDF2A34316389E6CC5
        Produced At: Mar 23 18:04:01 2020 GMT
        Responses:
        Certificate ID:
          Hash Algorithm: sha1
          Issuer Name Hash: 777A7BA877D6F10F1CE9202196FB6B1A6E37F5ED
          Issuer Key Hash: 9058FFB09C75A8515477B1EDF2A34316389E6CC5
          Serial Number: 08BF04E59C7D7A734E3EF18507AC59E6
        Cert Status: good
        This Update: Mar 23 18:04:01 2020 GMT
        Next Update: Mar 30 17:19:01 2020 GMT

    使用 SSLLAB 自动验证

    访问 https://www.ssllabs.com/ssltest/ ,输入欲测试的域名,稍等片刻后,如果发现结果中出现如下内容则证明已成功开启 OCSP Stapling:

    NginxConfig