我在 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服务器:nginx
withh 只需向他们提供它自己的证书,并且只有在配置了的情况下才有效。
那么如何组装这个链?解决方案相当简单:你完全依赖于内部发生的身份验证序列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;
在后端,您依赖这些标题。