如何配置 nginx 反向代理以接受具有私钥连接的 HTTPS 客户端

如何配置 nginx 反向代理以接受具有私钥连接的 HTTPS 客户端

我在 Nginx 反向代理配置中遇到了问题,问题很复杂,请阅读原文。

我们公司有一个内部基础设施,在旧的架构中,客户端(实际上,它们是用 NodeJS 编写的服务)直接通过 IP 连接服务器,客户端使用編輯https 模块的选项用于获取私钥以进行身份​​识别。

就像下面的图片一样。

原始建筑

但是我们有一个新的架构,所有的服务器将关闭所有开放的端口,并且只允许内部访问,客户端和服务器之间的连接将引入一个基于域名的nginx反向代理,将来再开放代理。

新架构

问题是旧客户端使用 pfx(私钥)连接服务器,反向代理与服务器的连接断开,它总是无法正确响应,一定是出了什么问题,那么如何配置 nginx 反向代理通过使用 pfx 来实现 https <-> https 连接呢?

我们的客户端访问代码就像

var fs    = require('fs);
var https = require('https');

// Read the private key file
var cert = fs.readFileSync('./client-certification.pfx');

var httpSettings = {
  host: options.host,
  port: options.port,
  path: options.path,
  pfx: cert,                           /* Important */
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  passphrase: "",
  rejectUnauthorized: false,
  agent: false
};

var request = https.request(httpSettings, function(res){
  var str = '';
  res.on('data',function(chunk){
    str += chunk;
  }).on("end", function() {
    try {
      var rt = JSON.parse(str);
      return callback(null, rt);
    }catch (e) {
      return callback(e, null);
    };
  });
});

当前 nginx 配置内容是,但尚未起作用。

map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close; 
}

upstream server1-upstream {
  server 8.8.8.8:443;
  keepalive 16;
}

server {
  listen 443;
  server_name server1.example.com;

  ssl_certificate     server1.example.com.crt;
  ssl_certificate_key server1.example.com.key;

  location / {
    proxy_pass https://server1-upstream;
    proxy_http_version 1.1;
    proxy_read_timeout 60m;
    proxy_pass_request_headers on;
    proxy_set_header Host $http_host;
    proxy_pass_header Date;
    proxy_pass_header Server;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Authorization $http_authorization;
    proxy_set_header Accept-Encoding "";
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header Upgrade $http_upgrade;
  }
}

有谁有过类似经历吗?

答案1

首先,恐怕我有一些不太好的消息。您不能直接nginx在通过其证书进行身份验证的客户端的 HTTPS 链中插入。

我应该提到編輯一开始我真的很困惑,但事实证明,节点.js俚语用这个术语来表示**pkcs12*证书。

客户端证书身份验证的工作原理的简要说明:在 SSL 握手期间,客户端将其证书提供给服务器。如果客户端证书 CA 被识别、受信任、未过期或被撤销,则接受该证书。因此,客户端证书身份验证由启用 SSL 的服务器(在您的情况下为 Web 服务器)完成,因此根据描述当前设置的方案,它应该由 完成nginx。从此时起,nginx 和后端之间的连接可以通过纯 HTTP 完成(当然,如果传输是受信任的),因为两个端点之间使用 HTTPS 毫无意义。出于同样的原因,您无法在后端使用其证书对客户端进行身份验证节点.js服务器:nginxwithh 只需向他们提供它自己的证书,并且只有在配置了的情况下才有效。

那么如何组装这个链?解决方案相当简单:你完全依赖于内部发生的身份验证序列nginx,然后nginx插入标头,指示它是否成功。就像这样:

ssl_stapling on;
ssl_client_certificate /etc/nginx/certs/trusted.pem;
ssl_verify_client optional;
ssl_verify_depth 2;

proxy_set_header X-SSL-Verified $ssl_client_verify;
proxy_set_header X-SSL-Certificate $ssl_client_cert;
proxy_set_header X-SSL-IDN $ssl_client_i_dn;
proxy_set_header X-SSL-SDN $ssl_client_s_dn;

在后端,您依赖这些标题。

相关内容