问题

问题

问题

我正在设置Nginx 代理在我的服务器上的 docker 中。NginX-Proxy 旨在可从 Web 直接访问,我想在它前面放置一个代理。

所需的连接流量

理想情况下,NginX(主机)应该是面向 Web 的服务器,并反向代理回到由环回地址(127.0.0.2)提供服务的 NginX-Proxy(Docker)。

本质上,我需要为无法识别的子域配置代理,将这些请求传递给托管这些子域的 NginX-Docker 代理,其中任何一个子域可能启用了或未启用 SSL。

家庭作业

NginX 支持各种方式的代理,但似乎都不太适合我的用例。

  1. 我希望主机上的 NginX 能够使用类似于以下配置来透明地代理 docker 实例丹尼尔·詹姆斯。此配置在主机上执行 SSL 终止,这似乎不是特别 DRY,因为通过 Nginx-Proxy 路由的 docker 容器本身(可能)正在执行 SSL 终止。通常,这似乎是通过 301 重定向(由于旧版本的 Nginx 的限制)来完成的,以强制所有传入的客户端流量使用 https,并强制后端/上游仅使用 HTTP 或 HTTPS。我想避免在 NginX(主机)终止并让 Nginx-Proxy 处理它。这里的优点是可以过滤域名,例如.domain.tld*.domain.tld模式。我见过这被称为中间人代理。

中间人代理

  1. NginX 在它的代理协议docs。我尝试设置如图所示的流,但似乎无法在服务器块内按域名过滤流。虽然它似乎可以转发 HTTP 和 HTTPS 流量而无需更改。我理解这是一种直通代理(更多地用于负载平衡/整形)。

通过代理

  1. IP 透明度似乎提供了一个更符合我要求的解决方案。但它的缺点是 NginX(主机)运行程序/线程必须以 root 权限运行,我不确定这会带来什么安全隐患(并不是说我托管的是绝密内容,但漏洞就是漏洞)。它还要求修改 docker 容器路由/IP 表,我不确定这是否可行。

  2. IP 透明度doc 还提到 DSR 是代理另一台服务器的替代方法,但随后统计显示 NginX 不支持此功能。我不知道这是什么。

平均能量损失

在我最初的努力中,我曾将以下内容组合在一起,它通过 HTTP 返回网站,但无法通过 HTTPS 返回网站。这采用了 MitM/反向代理策略。我保留了这一点以与评论保持一致。

server {
 server_name .domain.tld;
 # note : .domain.tld matches both *.domain.tld and domain.tld
 listen X.X.X.X:80;
 listen [X:X:X:X:X:X:X]:80;
 listen X.X.X.X:443 ssl;
 listen [X:X:X:X:X:X:X]:443 ssl;

 server_tokens off;

 # Logging
 access_log /var/log/nginx/docker_proxy-access.log main;
 error_log /var/log/nginx/docker_proxy-error.log info;

 location / {
  proxy_pass $scheme://127.X.X.X; # Local service IP Address 
  # Alternatively : proxy_pass $scheme://$http_host$uri$is_args$args;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header Host $host;
 }
}

我应该如何传递请求的域?使用127.X.X.X似乎会混淆需要域名来解析提供服务的docker容器的上游服务(这已在评论中解决)。我不确定我是否应该配置上游服务或proxy_bind在此处使用?我也应该设置proxy_redirect属性吗?我应该为HTTP和HTTPS设置单独的服务器块吗?

答案1

自从我第一次提出这个问题以来,我尝试了 @c4f4t0r 的建议,直接使用 Traefik。这在很大程度上是可行的,但 Traefik 是一个 7 级代理,也就是说它在应用层而不是传输层运行。它无法将任何 HTTPS 流量重定向到主机上与其一起的本地 Web 服务器。因此 SSL-Pass through (SNI) 在这里不是一种选择。似乎可以执行 SSL-Bridging,即在 Traefik 终止 SSL 连接并创建一个到本地服务器的新连接。

我从@Ernest Kiwele 的建议中错过的是检查上游服务器是否处理代理协议,它确实处理了代理协议,但我不知道它这样做了,也没有在当时启用它。

这里还有一个微妙之处,在上面的配置中,我基本上终止了 HTTP 连接,修改了 Header 并建立了一个新的连接。这是通过代理协议到上游服务完成的。由于它是 HTTP,因此以这种方式桥接连接是很常见的。HTTPS 还需要在每个终止/启动阶段重新加密。我希望在不解密/重新加密流量的情况下将其传递过去。事实证明,使用 NginX 流可以做到这一点,如下所示回答

为了解决我的问题,我必须同时创建一个http{server{}}服务器块和一个stream{server{}}块。前者在 NginX 的代理协议中桥接和包装 HTTP 连接。后者将 HTTPS 流包装在由 SNI 确定的代理协议包装器中,并将其直接传递给相关后端,有效地传递了 NginX 以及桥接和解密的需要。

相关内容