yokila
yokila
Published on 2024-03-20 / 41 Visits
0
0

Nginx HTTPS转发HTTPS

本文默认两台服务器都已经安装了 Nginx,且网关服务器已经申请并获得了 SSL证书

那么现在,就可以按步骤进行操作了。

注:关于 Nginx 更详细的安装和介绍,可以参考文章:Linux nginx的安装与入门

注:本文默认两台服务器不在一个局域网内,交互时是通过对方的公网IP地址。

注:本文只是一个场景示例,你完全可以把本文提及的网关服务器当作A服务器,应用服务器当作B服务器。不必纠结于生产实际是否长这样(其实一般比较完善的话,真不长这样)。

最终效果

如下图所示:

实际访问交互流程:

  1. 用户例如使用浏览器,先访问到网关服务器。

  2. 浏览器校验网关服务器提供的域名证书。

  3. 在网关服务器内部,与应用服务器进行HTTPS双向认证交互。

  4. 网关服务器把请求代理转发到应用服务器去。

  5. 应用服务器进行真正的业务处理,然后应答。

  6. 网关服务器接收到应用服务器的应答后,将应答返回给用户的浏览器。

申请域名及SSL证书

参考另外的文档:免费SSL证书申请(华为云)

记得把申请到的证书下载下来,然后上传到服务器上。(放置位置随便你,能找得到就行)

比如这是我申请到的博客服务的 SSL证书私钥

生成双向认证需要的文件

如果已有相关证书文件,则不需要这一步。

如果没有,则可以参考这份文档进行生成:OpenSSL 生成双向认证使用的证书

参考文章操作前,先看以下注意点:

  1. 随便你怎么弄,只要能弄出来完整证书链,后面能用,就没问题。

  2. 应用服务器作为被访问者,可以类比为服务端

  3. 网关服务器作为访问者,可以类比为客户端

  4. 建议在 网关服务器 应用服务器 上分别生成相应的 私钥CSR (不建议在外部(如本机)上生成然后上传到服务器)。

    • CSR 的 CN 建议都用 对应服务器的公网IP,不然等下双向校验可能过不去。(如果两台服务器在一个局域网内,直接用 内网IP 交互,则这里 CSR 的 CN 应该写的是 内网IP)

    • 按照安全规范,私钥应该安全保管,所以不要尝试在网上去生成密钥,也不要把私钥随便发到服务器之外。

    • 记得将刚刚在服务器上生成的两个 CSR 都下载到本地。

  5. 签发证书时

    • 不建议用 RootCA 这一级证书签发,一般是至少第2级CA来签发(通常是TLS CA)。(当然,你非要用 RootCA 签发末端证书,我也没法拦你)

    • 可以使得两个服务器的证书的颁发者CA是同一本。

  6. 签发后,记得把证书上传到服务器上(可以放在和 密钥 同一个文件夹底下)。

  7. Nginx上配置的证书链是一个文件,且需要从Root到最后一级颁发者CA(题外话:有些工具是需要弄成 jks 或者 p12 文件,不一定一样)

    • 没问题的话,证书链文件也要上传到服务器上(可以放在服务器证书同一目录,主要是为了方便找到它)。

配置防火墙

在正式配置两台服务器代理和被代理之前,我们需要确保两台服务器之间是能通信的

此时,我们应该想到的第一件事,就是——防火墙

你要先确保 应用服务器上Nginx监听的端口 允许 网关服务器 进行访问。也要确保 网关服务器对外开放了Nginx监听的端口 (不然浏览器怎么访问)

以下是防火墙的管理命令简单示例,更复杂的请借助搜索引擎:

  • Ubuntu查看防火墙信息(允许访问的端口信息),命令:sudo ufw status

  • Ubuntu允许外部访问端口(以12300为例):sudo ufw allow 12300

  • Ubuntu删除增加的规则(以12300为例):sudo ufw delete allow 12300

如果是云服务器,则还要保证安全组配置了访问白名单!!!

注:由于不同云服务商的操作步骤不同,所以这不做安全组配置的展示。

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


Comment