如何在保留原始IP地址的情况下转发数据包

如何在保留原始IP地址的情况下转发数据包

我需要将数据包从一台服务器(“作为代理”)转发到另一台服务器,同时保留客户端的原始 IP 地址。拓扑为: XXXX - 公共 IP1(“代理服务器”) YYYY - 公共 IP2(虚拟化主机) 172.16.0.2 - 私有 IP(带有 Web 服务器的虚拟机)

some public IP ---> X.X.X.X ---> Y.Y.Y.Y ---> 172.16.0.2 (web server)

在 XXXX 和 YYYY 转发已启用的系统上。

来自某个公共 IP 通过 XXXX 的流量在 XXXX 上路由到 YYYY,但它永远不会到达那里。我用 tcpdump 捕获了它。如果我在“代理服务器”上使用伪装,它可以正常工作,但原始 IP 地址不会保留。如果我对端口 80 使用 DNAT 仅从 YYYY 到 172.16.0.2 -iptables -t nat -A PREROUTING -d Y.Y.Y.Y/32 -i venet0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.16.0.2:80并且我尝试 YYYY:80 它工作正常。问题最有可能出现在具有公共 IP XXXX 的“代理服务器”上

“代理服务器”主机IP XXXX

它只有一个连接互联网的接口 - eth0。

iptables规则:(允许在过滤表中转发)

iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination Y.Y.Y.Y:443

路由表:它使用主表:

default via X.X.X.1 dev eth0 onlink

主机 IP YYYY

它只有一个连接互联网的接口 - venet0。对于VM,使用Qemu和接口br0。

iptables规则:(允许在过滤表中转发)

iptables -t nat -A PREROUTING -d Y.Y.Y.Y/32 -i venet0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 172.16.0.2:443
iptables -t nat -A POSTROUTING -s 172.16.0.0/24 ! -o br0 -j MASQUERADE

路由表:它使用主表:

default via 255.255.255.254 dev venet0

主机IP 172.16.0.2

它只有一个连接到互联网的接口 - ens6 路由表:它使用主表:

default via 172.16.0.1 dev ens6 proto static

根据gapsf回答的iptables规则:

XXXX iptables 规则:

iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination Y.Y.Y.Y
iptables -t nat -A POSTROUTING -s Y.Y.Y.Y/32 -o eth0 -p tcp -m tcp --sport 443 -j SNAT --to-source X.X.X.X
iptables -A FORWARD -d Y.Y.Y.Y/32 -p tcp -m tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s Y.Y.Y.Y/32 -p tcp -m tcp --sport 443 -j ACCEPT

YYYY iptables规则:

iptables -t nat -A PREROUTING -i venet0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 172.16.0.2:443
iptables -t nat -A POSTROUTING -s 172.16.0.2/32 -o venet0 -p tcp -m tcp --sport 443 -j SNAT --to-source Y.Y.Y.Y
iptables -A FORWARD -d 172.16.0.2/32 -i venet0 -o br0 -p tcp -m tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s 172.16.0.2/32 -i br0 -o venet0 -p tcp -m tcp --sport 443 -j ACCEPT

172.16.0.2 iptables规则:

iptables -A INPUT -i ens6 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A OUTPUT -o ens6 -p tcp -m tcp --sport 443 -j ACCEPT

你能帮我吗 - 问题出在哪里?

答案1

在评论中,您已指出要将流量转发到的 Web 服务器没有将数据包直接返回到 Web 客户端的路由。这是一种非常常见的场景,但对于 iptables 来说太复杂了。

通常的解决方案包括:

  1. “DMZ”子网中的硬件或软件负载平衡器产品,该子网是具有 Web 服务器默认路由的计算机。负载均衡器具有客户端知道的公共 XXXX IP 地址,并通过 DNAT 将流量转发到源地址不变的 Web 服务器。负载均衡器是Web服务器的默认网关,因此它们的返回数据包可以通过负载均衡器传回,并且可以对返回流量执行SNAT。这种复杂的软件和/或硬件的成本可能使许多组织无法承受。

  2. 将流量转发到 Web 服务器时执行 SNAT,但使用代理添加 HTTP 标头,通知 Web 服务器软件客户端的真实 IP 地址。我通常看到的用于此目的的标头是X-Forwarded-For:.许多 HTTP 服务器库会自动识别此标头,并使标头中的 IP 地址可供应用程序使用。有些应用程序期望标头中只有一个 IP 地址,有些应用程序可以处理地址列表(因为流量在到达您的代理之前可能会经过代理)。大多数网络代理软件都可以添加此标头。

与其他一切一样,也需要权衡。代理 HTTP 流量并添加标头的第二个选项要求 HTTP 流量符合可接受的标准,以便代理软件可以对其进行操作。如果您的客户端使用松散地基于 HTTP 但不完全兼容的自定义协议,则代理尝试修改请求可能会导致麻烦。例如,如果您的协议使用长度超过 64k 字节的 URL。 (我以前遇到过这个问题,尽管那是几年前的事了)。

鉴于您提到的要求,我认为#2 是最适合您的解决方案。如果您的网络流量增长,您可能会超出它的范围,并且需要更复杂(且成本更高)的负载平衡解决方案。

答案2

你不需要昂贵的硬件——我认为只需要路由+iptables就足够了XXXX主机只有一个接口

于 XXXX

ip route add default via eth0
PREORUTING in eth0 dport 80 DNAT to Y.Y.Y.Y
POSTROUTING out eth0 src Y.Y.Y.Y sport 80 SNAT to X.X.X.X
FORWARD dst Y.Y.Y.Y dport 80 ACCEPT
FORWARD src Y.Y.Y.Y sport 80 ACCEPT

于 YYYY

ip route add default via venet0
ip route add 172.16.0.2 via br0
PREROUTING in venet0 dport 80 DNAT to 172.16.0.2
POSTROUTING out venet0 src 172.16.0.2 sport 80 SNAT to Y.Y.Y.Y
FORWARD in venet0 out br0 dst 172.16.0.2 dport 80 ACCEPT
FORWARD in br0 out venet0 src 172.16.0.2 sport 80 ACCEPT

于 172.16.0.2

ip route add default via 172.16.0.1
INPUT in ens6 dport 80 ACCEPT
OUTPUT out ens6 sport 80 ACCEPT

第2部分
XXXX iptables 规则:

iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination Y.Y.Y.Y
iptables -t nat -A POSTROUTING -s Y.Y.Y.Y/32 -o eth0 -p tcp -m tcp --sport 443 -j SNAT --to-source X.X.X.X
iptables -A FORWARD -d Y.Y.Y.Y/32 -p tcp -m tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s Y.Y.Y.Y/32 -p tcp -m tcp --sport 443 -j ACCEPT

YYYY iptables规则:

iptables -t nat -A PREROUTING -i venet0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 172.16.0.2:443
iptables -t nat -A POSTROUTING -s 172.16.0.2/32 -o venet0 -p tcp -m tcp --sport 443 -j SNAT --to-source Y.Y.Y.Y
iptables -A FORWARD -d 172.16.0.2/32 -i venet0 -o br0 -p tcp -m tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s 172.16.0.2/32 -i br0 -o venet0 -p tcp -m tcp --sport 443 -j ACCEPT

172.16.0.2 iptables规则:

iptables -A INPUT -i ens6 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A OUTPUT -o ens6 -p tcp -m tcp --sport 443 -j ACCEPT

相关内容