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 服务器优化分析
-
SSL 操作会消耗额外的 CPU 资源。在多处理器系统上,应该运行多个 工作进程(worker process),不得少于可用 CPU 核心的数量。大多数 CPU 密集型操作是发生在 SSL 握手时。有种方法可以最大程度地减少每个客户端执行这些操作的次数。
- keepalive指令不会限制一个nginx worker进程到upstream服务器连接的总数量。connections参数应该设置为一个足够小的数字来让upstream服务器来处理新进来的连接。 connections参数设置每个worker进程在缓冲中保持的到upstream服务器的空闲keepalive连接的最大数量.当这个数量被突破时,最近使用最少的连接将被关闭。
启用 keepalive 连接,通过一个连接来发送多个请求,第二个是复用 SSL 会话参数,避免相同的和后续的连接发生 SSL 握手。会话存储在工作进程间共享的 SSL 会话缓存中,由 ssl_session_cache 指令配置。1MB 缓存包含约 4000 个会话。默认缓存超时时间为 5 分钟,可以用 ssl_session_timeout 指令来增加。以下是一个优化具有 10MB 共享会话缓存的多核系统的配置示例: