我有一个由 Nginx 服务组成的 docker swarm,它充当其他几个上游服务(web 和邮件)的反向代理。web 和邮件服务都需要通过 HTTPS 连接到外部服务才能执行身份验证。邮件服务需要能够通过端口 587 连接到外部服务器才能发送邮件。上游 web 和邮件需要能够获取客户端的 IP 地址,因此我在 Nginx 服务器以及上游 web 和邮件服务器上设置了 IP 透明度,如此处所述https://www.nginx.com/blog/ip-transparency-direct-server-return-nginx-plus-transparent-proxy/(参见方法 1)。到 Web 和邮件的入站连接工作正常。它们经过 Nginx 代理,然后向上游发送到 Web 或邮件,并且两者都可以看到实际客户端的 IP 地址。但是,从 Web 和邮件内部发起的出站连接无法通过。Web 和邮件都将其默认网关设置为使用 Nginx 的 IP 地址。通常,这可以通过添加 SNAT 规则或使用 MASQUERADE 来解决iptables
。但是,如果我这样做,它会破坏 IP 透明度,上游将获取 Nginx 代理的 IP 地址而不是客户端的 IP 地址。按照我链接到的文档中的示例:
# ip rule add fwmark 1 lookup 100
# ip route add local 0.0.0.0/0 dev lo table 100
# iptables -t mangle -A PREROUTING -p tcp -s 172.16.0.0/28 --sport 80 -j MARK --set-xmark 0x1/0xffffffff
在网络上:
# route del default gw 172.16.0.1
# route add default gw 172.16.0.12
邮件中:
# route del default gw 172.16.0.1
# route add default gw 172.16.0.13
在 Nginx 服务器上添加 IP 伪装规则(生产中应重写为 SNAT):
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# iptables -A FORWARD -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -i eth0 -j ACCEPT
我尝试过在伪装规则中过滤标记的数据包,但似乎不起作用。例如:
# iptables -t nat -A POSTROUTING -o eth0 --match mark ! --mark 0x1/0xffffffff -j MASQUERADE
或者
# iptables -t nat -A POSTROUTING -o eth0 --match mark --mark 0x1/0xffffffff -j MASQUERADE
我尝试了和 的不同组合POSTROUTING
,PREROUTING
但无法使它们发挥作用。
除了 SNAT 或 IP 伪装之外,还有其他方法可以将流量从上游服务器转移到互联网吗?或者是否有某种方法可以设置筛选,以便只有未标记的数据包才会被伪装?
编辑:只是一些澄清......
我已经让 IP 透明代理正常工作了。我可以使用适当的端口连接到 Nginx 代理,它会将其转发到上游(邮件或 Web),它会获取客户端的 IP 地址而不是 Nginx 代理的 IP 地址,客户端会毫无问题地从上游获取响应。
问题是上游服务器需要发起与外部服务器的连接。邮件服务器就是这种情况,它需要连接到互联网上的另一台服务器来传递邮件。当上游服务器尝试执行此操作时,数据包不会离开 Docker 网络。
TL;DR:Nginx 代理中的 IP 透明性正在运行。但上游服务器无法连接到互联网,因为它们的默认网关已设置为 Nginx 代理的 IP 地址。
答案1
您是否想发送电子邮件/网络请求并将客户的 IP 作为来源?如果是这样,这将行不通,响应消息永远不会返回给您,而是返回给您的客户。
我相信您需要使用 Nginx 标头才能使其工作并让您的外部 Web /邮件服务器知道这些标头。
在 DNS 解析器中,这被称为客户端子网选项,其中客户端 IP/前缀作为标头捆绑在 DNS 请求消息中,而源 IP 是解析器。