我在 nginx 反向代理后面有一组虚拟主机。每个虚拟主机的末尾都有一台服务器,该服务器具有给定虚拟域的有效证书。
例如
api.example.com->proxy_passhttps://api.example.com; # 在本地解析为具有 api.example.com 证书的 docker 实例
现在,我的问题是,代理服务器本身似乎需要自己的证书,但我不明白为什么。由于域名和子域名不会通过 https 加密,为什么我不能简单地转发每个代理服务器的证书?或者我可以吗?怎么做?
这是我目前所拥有的:
server {
listen 80;
listen [::]:80;
server_name *.example.com;
location / {
proxy_pass http://$http_host$uri$is_args$args;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name *.example.com;
location / {
proxy_pass https://$http_host$uri$is_args$args;
}
}
但第二项指令要求证书。
答案1
想想使用反向代理会发生什么:
- 客户端连接到代理并请求资源。
- 代理获取此 URL 并向后端服务器发送不同的请求,获取返回的结果并将其发送给客户端。
- 具体来说,不会发生的事情是网络连接只是通过 IP 级别(第 4 层)转发到后端服务器。
因此,来自客户端的 HTTPS 连接在代理处终止,因此代理需要拥有该域的有效证书。
为什么不能直接将当前在 docker 容器中的证书部署到代理?这是正常方法。从代理到后端的连接不需要在安全网络中加密(例如,在 docker 容器在同一主机上运行的情况下)。
答案2
Nginx 实际上能够做到这一点。不是在 http 级别,而是在流级别。配置本身并不那么困难。这里有完整的教程教你如何操作
另外,还可以找到另一个关于如何实现这一点的例子这里。为了完整起见,我将把这个例子复制到这里。
stream {
map $ssl_preread_server_name $name {
vpn1.app.com vpn1_backend;
vpn2.app.com vpn2_backend;
https.app.com https_backend;
default https_default_backend;
}
upstream vpn1_backend {
server 10.0.0.3:443;
}
upstream vpn2_backend {
server 10.0.0.4:443;
}
upstream https_backend {
server 10.0.0.5:443;
}
upstream https_default_backend {
server 127.0.0.1:443;
}
server {
listen 10.0.0.1:443;
proxy_pass $name;
ssl_preread on;
}
}
对于那些投反对票的人:我可能没有在问题中很好地解释这一点,但这正是我想要的。