本文默认两台服务器都已经安装了 Nginx,且网关服务器已经申请并获得了 SSL证书。
那么现在,就可以按步骤进行操作了。
注:关于 Nginx 更详细的安装和介绍,可以参考文章:Linux nginx的安装与入门
注:本文默认两台服务器不在一个局域网内,交互时是通过对方的公网IP地址。
注:本文只是一个场景示例,你完全可以把本文提及的网关服务器当作A服务器,应用服务器当作B服务器。不必纠结于生产实际是否长这样(其实一般比较完善的话,真不长这样)。
最终效果
如下图所示:
实际访问交互流程:
用户例如使用浏览器,先访问到网关服务器。
浏览器校验网关服务器提供的域名证书。
在网关服务器内部,与应用服务器进行HTTPS双向认证交互。
网关服务器把请求代理转发到应用服务器去。
应用服务器进行真正的业务处理,然后应答。
网关服务器接收到应用服务器的应答后,将应答返回给用户的浏览器。
申请域名及SSL证书
参考另外的文档:免费SSL证书申请(华为云)
记得把申请到的证书下载下来,然后上传到服务器上。(放置位置随便你,能找得到就行)
比如这是我申请到的博客服务的 SSL证书 和 私钥:
生成双向认证需要的文件
如果已有相关证书文件,则不需要这一步。
如果没有,则可以参考这份文档进行生成:OpenSSL 生成双向认证使用的证书
参考文章操作前,先看以下注意点:
随便你怎么弄,只要能弄出来完整证书链,后面能用,就没问题。
应用服务器作为被访问者,可以类比为服务端
网关服务器作为访问者,可以类比为客户端
建议在 网关服务器 和 应用服务器 上分别生成相应的 私钥 和 CSR (不建议在外部(如本机)上生成然后上传到服务器)。
CSR 的 CN 建议都用 对应服务器的公网IP,不然等下双向校验可能过不去。(如果两台服务器在一个局域网内,直接用 内网IP 交互,则这里 CSR 的 CN 应该写的是 内网IP)
按照安全规范,私钥应该安全保管,所以不要尝试在网上去生成密钥,也不要把私钥随便发到服务器之外。
记得将刚刚在服务器上生成的两个 CSR 都下载到本地。
签发证书时
不建议用 RootCA 这一级证书签发,一般是至少第2级CA来签发(通常是TLS CA)。(当然,你非要用 RootCA 签发末端证书,我也没法拦你)
可以使得两个服务器的证书的颁发者CA是同一本。
签发后,记得把证书上传到服务器上(可以放在和 密钥 同一个文件夹底下)。
Nginx上配置的证书链是一个文件,且需要从Root到最后一级颁发者CA(题外话:有些工具是需要弄成 jks 或者 p12 文件,不一定一样)
没问题的话,证书链文件也要上传到服务器上(可以放在服务器证书同一目录,主要是为了方便找到它)。
配置防火墙
在正式配置两台服务器代理和被代理之前,我们需要确保两台服务器之间是能通信的。
此时,我们应该想到的第一件事,就是——防火墙。
你要先确保 应用服务器上Nginx监听的端口 允许 网关服务器 进行访问。也要确保 网关服务器对外开放了Nginx监听的端口 (不然浏览器怎么访问)
以下是防火墙的管理命令简单示例,更复杂的请借助搜索引擎:
Ubuntu查看防火墙信息(允许访问的端口信息),命令:sudo ufw status
Ubuntu允许外部访问端口(以12300为例):sudo ufw allow 12300
Ubuntu删除增加的规则(以12300为例):sudo ufw delete allow 12300
如果是云服务器,则还要保证安全组配置了访问白名单!!!
注:由于不同云服务商的操作步骤不同,所以这不做安全组配置的展示。
如果是阿里云服务器,可以参考这篇文章:云服务器的入门配置及SSH连接(基于阿里云服务器)
如果是华为云服务器,可以参考这篇文章:云服务器的入门配置及SSH连接(基于华为云服务器)
Nginx代理配置(应用服务器)
先进入到存放服务器证书和证书链的文件夹,记录一下路径。
然后进入到nginx的配置文件路径:cd /etc/nginx/conf.d/
编辑生成一个新的配置文件:vi xxx.conf
注:配置文件的文件名请自定义。
注:下面配置仅为示例,可以自行补充扩展,以及注意地址、域名要改成正确的。
注:关于 Nginx 更详细的介绍,可以参考文章:Linux nginx的安装与入门
配置文件内容如下:
server {
# 这里任意没被用过的端口都行
listen 4433 ssl;
# IPv6地址格式,这里忽略
# listen [::]:4433 ssl;
server_name 5.6.7.8; # 有域名写域名,无域名写自身IP地址,需要和服务器证书的CN保持匹配
# 允许客户端与服务端的连接保持活跃时长,以减少频繁的SSL握手
keepalive_timeout 75s;
# on为开启将客户端请求头中带有下划线的字段标识为无效字段,默认为off
underscores_in_headers on;
# 服务端证书配置
ssl_certificate /path/ssl/5678.crt; # 证明自身的服务器证书
ssl_certificate_key /path/ssl/5678.key; # 证明自身的私钥
# 验证客户端的CA链
ssl_client_certificate /path/ssl/1234CaChain.pem;
# 开启校验客户端
ssl_verify_client on;
# ssl协议
ssl_protocols TLSv1.2 TLSv1.3;
# ssl cipher套接字
ssl_ciphers HIGH:!aNULL:!MD5;
# 设置验证客户端证书链的深度,默认是1
ssl_verify_depth 10;
charset utf-8;
# 设置客户端请求body的最大允许大小,默认1m
client_max_body_size 100m;
# 内部进行转发
location / {
proxy_pass http://127.0.0.1:8080; # 服务器内部真正处理业务的服务
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
执行nginx校验配置文件命令:nginx -t
如果没问题,就热更新nginx配置,执行命令:nginx -s reload
Nginx代理配置(网关服务器)
先进入到存放服务器证书和证书链的文件夹,记录一下路径。
然后进入到nginx的配置文件路径:cd /etc/nginx/conf.d/
编辑生成一个新的配置文件:vi xxx.conf
注:下面配置仅为示例,可以自行补充扩展,以及注意地址、域名要改成正确的。
注:关于 Nginx 更详细的介绍,可以参考文章:Linux nginx的安装与入门
配置文件内容如下:
server {
listen 443 ssl; # https默认是443端口
# IPv6地址格式,这里忽略
# listen [::]:443 ssl;
server_name example.com; # 有域名写域名,没域名写自身IP,需要和服务器证书的CN保持匹配
# on为开启将客户端请求头中带有下划线的字段标识为无效字段,默认为off
underscores_in_headers on;
# 服务端证书配置(网关的SSL证书,给浏览器验证的)
ssl_certificate /path/ssl/example.crt;
ssl_certificate_key /path/ssl/example.key;
# ssl协议
ssl_protocols TLSv1.2 TLSv1.3;
# ssl 加密套件
ssl_ciphers HIGH:!aNULL:!MD5;
charset utf-8;
# 设置客户端请求body的最大允许大小,默认1m
client_max_body_size 100m;
# 内部进行转发
location / {
# 代理转发的目标应用服务器地址和端口,注意是https
proxy_pass https://5.6.7.8:4433;
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 作为客户端去访问被代理的服务器时进行的https双向认证配置
proxy_ssl_certificate /path/clientSSL/1234.crt; # 自身的证书
proxy_ssl_certificate_key /path/clientSSL/1234.key; # 自身证书对应的私钥
proxy_ssl_trusted_certificate /path/clientSSL/5678CaChain.pem; # 验证应用服务器的证书链
proxy_ssl_verify on; # 开启对被代理服务的验证
proxy_ssl_verify_depth 10; # 对代理服务的验证深度为10
proxy_ssl_protocols TLSv1.2 TLSv1.3; # 协议版本
}
}
执行nginx校验配置文件命令:nginx -t
如果没问题,就热更新nginx配置,执行命令:nginx -s reload
实际测试
启动应用服务器的业务处理服务,然后用浏览器访问网关服务器,如果访问正常,就说明配置正确。
访问示例:https://example.com