写点什么

深入浅出学习透析 Nginx 服务器的基本原理和配置指南「Https 安全控制篇」

作者:洛神灬殇
  • 2022-11-21
    江苏
  • 本文字数:4421 字

    阅读完需:约 15 分钟

深入浅出学习透析Nginx服务器的基本原理和配置指南「Https安全控制篇」

Https 反向代理

之前的内容中我们主要针对于一些对安全性要求比较高的站点,可能会使用 HTTPS(一种使用 SSL 通信标准的安全 HTTP 协议),针对于 HTTP 协议和 SSL 标准相信大家都知道了,在这里我就不为大家进行介绍了,如果需要了解,大家可以查看一下相关的资料哈,但是对于使用 Nginx 配置 https 需要了解一下基础内容的。


生产环境一般都是购买的商业版 SSL 证书,本文主要是将自己配置 Nginx  https 证书的过程记录。我们开发过程的时候一般采用自制 SSL 证书。Nginx 实现 https 需要 http_ssl_module 模块支持,该模块是默认编译模块,不需要我们再次编译。

Https 反向代理的配置规则

  • HTTPS 的默认端口号是 443,不同于 HTTP 的默认端口(80)

  • SSL 标准需要引入安全证书,所以在 Nginx.conf 中你需要指定证书和它对应的 key

  • 其他和 http 反向代理基本一样,只是在 Server 部分配置有些不同。

之前案例的 Http 配置模板

以下是我们之前章节案例的配置基本模板信息,用于作为我们 https 模式的改造的标准话模板参考。


http {    upstream nginxServerConfig {        least_conn;        server www.address1.com; // 或者ip+端口 , 不需要加入http/https前缀        server www.address2.com;        server www.address3.com;    }    server {        listen 80;        location / {            proxy_pass http://loadBalanceServer;        }    }}
复制代码

配置 HTTPS 服务器

要配置 HTTPS 服务器,必须在 server 块中的 监听套接字 上启用 ssl 参数,并且指定服务器证书 和 私钥文件 的位置:

启用 SSL 功能

添加 ssl 指令的参数 on,代表开启状态,目前新版本已经不需要进行指定了,默认可以自己检测和开启状态,此处只是说明以下有这个指令介绍。


ssl on;
复制代码


注意:在 0.7.14 之前,无法为各个 socket 选择性地启用 SSL,如上所示。只能使用 ssl 指令为整个服务器启用 SSL,从而无法设置单个 HTTP/HTTPS 服务器。可以通过添加 listen 指令的 ssl 参数来解决这个问题。因此,不建议在现在的版本中使用 ssl 指令

监听默认端口修改

上面说的配置:HTTPS 的默认端口号是 443,不同于 HTTP 的默认端口(80),需要将原有的 80 端口的监听 443 端口。443 为知名端口号,主要用于 HTTPS 协议。


需要将 listen 80; 改为  listen  443 ssl;
复制代码


并且需要再后面再添加一个 ssl 标识,代表着监听此类端口为 Https 模式协议机制。

制作 SSL 证书文件

我们都知道在公钥密码学(也称为非对称密码术)中,加密机制依赖于两个相关的密钥,一个公钥和一个私钥。公钥用于加密消息,而只有私钥的所有者才能解密消息。而针对于 Https 加密机制,需要引入证书,而证书就是针对于公钥和私钥的载体。所以我们需要配置对应的 ssl 证书文件。


SSL 证书,就是遵守 SSL 安全套接层协议的服务器数字证书,由浏览器受信任的根证书颁发机构在验证服务器身份后颁发,具有网站身份验证和加密传输等功能。SSL 证书并不是什么高深的技术产品,只需要成功申请下发后,安装到网站服务器即可。当你访问一个网站时,如果发现浏览器的地址栏中显示的是“https://”(绿色小锁图标),就说明这个网站已经安装部署了 SSL 证书


  • PEM:用 ASCLL(BASE64)编码的证书;PEM 扩展名用于不同类型的 X.509v3 文件,这些文件包含前缀为“-BEGIN …”行的 ASCII(Base64)数据。

  • CER/CRT:存放公钥,没有私钥(编码方式不一定,有可能是.pem,也有可能是.der)。


在制作 SSL 证书之前需要线生成对应的私钥文件 key 信息数据。

openssl 生成 RSA 私钥文件

openssl  alexlibo  -out mysecurity.key 2048
复制代码


生成对应的私钥文件的基本结构信息如下:



当然也可以参考使用 acme.sh 给 Nginx 安装 Let’ s Encrypt 提供的免费 SSL 证书,生成对应的较为专业的 SSL 证书。针对于该脚本【acme.sh】的 github 仓库地址 https://github.com/acmesh-official/acme.sh,有兴趣的小伙伴可以试试看。

生成 pem 文件

PEM 文件格式

PEM 格式通常用于数字证书认证机构(Certificate Authorities,CA),扩展名为.pem, .crt, .cer, and .key。内容为 Base64 编码的 ASCII 码文件,有类似"-----BEGIN CERTIFICATE-----" 和 "-----END CERTIFICATE-----"的头尾标记。服务器认证证书,中级认证证书和私钥都可以储存为 PEM 格式(认证证书其实就是公钥)。Apache 和类似的服务器使用 PEM 格式证书。


openssl  req  -new -x509  -days 3650  -key mysecurity.key  -out mysecurity.pem
复制代码
PEM 文件内容

以下就是类似的 pem 文件的内容


添加对应的 SSL 证书

将生成的 key、pem 文件拷贝到 nginx 的 conf 目录下,为了管理多个 SSL 证书,可以在 nginx 的 conf 目录下建立 cert 目录专门存放 SSL 证书相关文件。

设置 ssl 证书文件位置

我们采用在 server 指令块内部定义【ssl_certificate 指令】对应的 value 值,sl_certificate 处写我们生成的 pem 文件,一般我们常见证书文件格式为:crt/pem。


ssl_certificate      path/mysecurity.pem;
复制代码


或者


ssl_certificate      path/mysecurity.crt;
复制代码


这里注意以下:对应的证书位置是针对于 nginx,conf 文件的相对位置或者觉得路径也可以。

设置 ssl 证书私钥文件的位置

ssl_certificate_key 写我们生成的 key 文件。配置完成后检查 nginx 的配置文件 然后重启 Nginx.


ssl_certificate_key path/mysecurity.key;
复制代码


注意:服务器证书是一个公共实体。它被发送到每个连接到服务器的客户端。私钥是一个安全实体,存储在一个访问受限的文件中,但是它对 nginx 的主进程必须是可读的。私钥也可以存储在与证书相同的文件中:


ssl_certificate     xxx.cert;ssl_certificate_key xxx.cert;
复制代码


这种情况下,文件的访问也应该被限制。虽然证书和密钥存储在一个文件中,但只有证书能被发送给客户端。

SSL 指令来限制连接

ssl_protocols 和 ssl_ciphers 指令来限制连接,使其仅包括 SSL/TLS 的版本和密码

ssl_protocols

默认情况下,Nginx 使用版本为 ssl_protocols TLSv1 TLSv1.1 TLSv1.2,如下所示。


ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
复制代码
ssl_ciphers

默认情况下,Nginx 密码为 ssl_ciphers HIGH:!aNULL:!MD5


ssl_ciphers HIGH:!aNULL:!MD5
复制代码


ssl_prefer_server_ciphers


指定是否使用服务器的 SSL 密码,on 为开启状态


ssl_prefer_server_ciphers  on;
复制代码


通常不需要配置它们以上两者的值。请注意,这些指令的默认值已经被更改多次。


最终案例展示


server {    listen              443 ssl;    server_name       www.address1.com;    ssl_certificate      path/mysecurity.pem;    ssl_certificate_key path/mysecurity.key;    ssl_ciphers         HIGH:!aNULL:!MD5;    ...}
复制代码

ssl 配置参数(选择性配置)

ssl 的会话相关的配置

ssl_session_cache


设置 ssl 的 session 会话的缓存


启用 SSL Session 缓存可以大大减少 TLS 的反复验证,减少 TLS 握手的 roundtrip。虽然 session 缓存会占用一定内存,但是用 1M 的内存就可以缓存 4000 个连接,可以说是非常非常划算的。对于绝大多数网站和服务,要达到 4000 个同时连接本身就需要非常非常大的用户基数,因此可以放心开启。


ssl_session_cache    shared:SSL:1m;
复制代码


  • shared:SSL:1m:代表着缓存属于 SSL 之内进行共享,总体大小为 1M。


ssl_session_timeout


设置 ssl 的会话超时时间为 5 分钟


ssl_session_timeout  5m; 
复制代码



同时建立 HTTP/HTTPS 服务器

可以配置单个服务器来处理 HTTP 和 HTTPS 请求:


server {    listen              80;    listen              443 ssl;    server_name         www.example.com;    ssl_certificate     www.example.com.crt;    ssl_certificate_key www.example.com.key;    ...}
复制代码

基于名称的 HTTPS 服务器

当配置两个或多个 HTTPS 服务器监听单个 IP 地址时,会出现一个常见问题:


server {    listen          443 ssl;    server_name     www.address1.com;    ssl_certificate address1.crt;    ...}server {    listen          443 ssl;    server_name     www.address1.org;    ssl_certificate address1.crt;    ...}
复制代码


使用了此配置,浏览器会接收默认服务器的证书,即 www.address1.com,而无视所请求的服务器名称。这是由 SSL 协议行为引起的。SSL 连接在浏览器发送 HTTP 请求之前建立,nginx 并不知道请求的服务器名称。因此,它只能提供默认服务器的证书。最古老、最强大的解决方法是为每个 HTTPS 服务器分配一个单独的 IP 地址:


server {    listen          192.168.1.1:443 ssl;    server_name     www.address1.com;    ssl_certificate address1.crt;    ...}server {    listen          192.168.1.2:443 ssl;    server_name     www.address1.org;    ssl_certificate address1.crt;    ...}
复制代码


一般情况下如果作为统一的公私钥配置,那么最好是将证书文件与名称、私钥文件放置在 http 级配置,以便在所有服务器中继承其单个内存副本,如下所示


ssl_certificate     mysecurity.crt;ssl_certificate_key mysecurity.key;server {    listen          443 ssl;    server_name     www.address1.com;    ...}server {    listen          443 ssl;    server_name     www.address2.org;    ...
复制代码

Https 服务配置模式最终案例

  #HTTP服务器  server {      #监听443端口。443为知名端口号,主要用于HTTPS协议      listen       443 ssl;      #定义使用www.xx.com访问      server_name  www.xx.com;      #ssl证书文件位置(常见证书文件格式为:crt/pem)      ssl_certificate      cert.pem;      #ssl证书key位置      ssl_certificate_key  cert.key;      #ssl配置参数(选择性配置)      ssl_session_cache    shared:SSL:1m;      ssl_session_timeout  5m;      #数字签名,此处使用MD5      ssl_ciphers  HIGH:!aNULL:!MD5;      ssl_prefer_server_ciphers  on;      location / {          root   /root;          index  index.html index.htm;      }  }
复制代码

HTTPS 服务器优化分析

  1. SSL 操作会消耗额外的 CPU 资源。在多处理器系统上,应该运行多个 工作进程(worker process),不得少于可用 CPU 核心的数量。大多数 CPU 密集型操作是发生在 SSL 握手时。有种方法可以最大程度地减少每个客户端执行这些操作的次数。

  2. keepalive 指令不会限制一个 nginx worker 进程到 upstream 服务器连接的总数量。connections 参数应该设置为一个足够小的数字来让 upstream 服务器来处理新进来的连接。 connections 参数设置每个 worker 进程在缓冲中保持的到 upstream 服务器的空闲 keepalive 连接的最大数量.当这个数量被突破时,最近使用最少的连接将被关闭。


启用 keepalive 连接,通过一个连接来发送多个请求,第二个是复用 SSL 会话参数,避免相同的和后续的连接发生 SSL 握手。会话存储在工作进程间共享的 SSL 会话缓存中,由 ssl_session_cache 指令配置。1MB 缓存包含约 4000 个会话。默认缓存超时时间为 5 分钟,可以用 ssl_session_timeout 指令来增加。以下是一个优化具有 10MB 共享会话缓存的多核系统的配置示例

用户头像

洛神灬殇

关注

🏆InfoQ写作平台-签约作者🏆 2020-03-25 加入

【个人简介】酷爱计算机科学、醉心编程技术、喜爱健身运动、热衷悬疑推理的“极客达人” 【技术格言】任何足够先进的技术都与魔法无异 【技术范畴】Java领域、Spring生态、MySQL专项、微服务/分布式体系和算法设计等

评论

发布
暂无评论
深入浅出学习透析Nginx服务器的基本原理和配置指南「Https安全控制篇」_nginx_洛神灬殇_InfoQ写作社区