Luc*_*Luc 2 iptables linux-networking dnat
我有一台具有两个接口的计算机,这两个接口具有不同的可路由 IPv4 地址。为了在正确的接口上返回流量,我使用了这个答案和评论,它有效:我可以使用任一 IP 地址 ssh 进入机器。(我不知道这是否有任何影响,但可能有。)
现在我使用此答案添加了以下用于反向代理/DNAT 的 iptables 规则。我的启动脚本现在看起来像:
# eth0 is automatically brought up and gets 192.168.1.2 as IP
sudo ip link set eth1 up
sudo ip addr add 192.168.2.2/24 dev eth1
sudo ip rule add from 192.168.2.2 table frometh1
sudo ip route add default via 192.168.2.1 dev eth1 table frometh1
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.0.1:443
sudo iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.0.0.1:443
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
Run Code Online (Sandbox Code Playgroud)
最初,-i eth*被省略,DNAT 规则只是一个命令。MASQUERADE 规则也是通过交换 来-o eth*实现的一个命令-d 10.0.0.1。我将它们分开,试图使接口显式化,以防 iptables 隐式采用其中一个接口。
当我尝试到达 时192.168.1.2:443,流量会按预期转发和伪装。PREROUTING 表中正确 DNAT 规则的命中计数器递增,并且正确的 MASQUERADE 规则递增。我可以成功建立 TCP 连接。
当尝试到达 时192.168.2.2:443,我可以看到接口上传入的流量,并且 PREROUTING 表中正确 DNAT 规则的命中计数器会增加。但是没有传出数据包,并且 POSTROUTING 中的两个 MASQUERADE 规则都没有增加。TCP SYN 永远不会到达远程系统 ( 10.0.0.1)。
请注意,转发是通过 eth0 还是 eth1 并不重要,可以通过10.0.0.1eth0 或 eth1 将流量转发到目标 ( )。
为什么 iptables 规则仅适用于 eth0 而不适用于 eth1?
编辑:了解用户空间中的代理工作正常可能是相关的:
mkfifo /tmp/fifo
sudo nc -kvlp 443 </tmp/fifo | nc 10.0.0.1 443 >/tmp/fifo
Run Code Online (Sandbox Code Playgroud)
允许流量双向流动,如本博客中所述。此解决方案的问题在于远程端只能看到一个持久的 TCP 连接。它应该为每个客户端看到一个连接并同时处理多个客户端。
首先,让我们绘制您的网络拓扑。
我认为这是反向路径过滤器的副作用,因为数据包在路由决策步骤中被丢弃。
检查命令的输出nstat -az 'TcpExtIPReversePathFilter'。它可能显示非零计数器,该计数器在检查时递增。
使用命令检查路由ip route get 10.0.0.1 from <external-host-ip> iif eth1。我想它会显示类似的东西invalid cross-device link。
rp_filter您可以在命令输出中查看接口的当前状态ip netconf show。
禁用rp_filter或最好将其设置为loose模式。这rp_filter可以防止下游网络中的 IP 地址欺骗,这种欺骗广泛用于 DDoS 放大攻击。在您的情况下,调整不会增加新的风险,因为您的 Linux 主机不是连接网络的主要网关。
这不是您设置中的最后一个问题。如果存在,请修复问题rp_filter,我将扩展答案以使您的配置正常工作。
现在,rp_filter问题解决后,让我们尝试使配置按预期工作。
让我们从描述正在发生的事情和出错的地方开始。
ext2.IP。原始数据包看起来像C.IP:<someport> -> <ext2.IP>:443
GW2并通过端口转发后将如下所示,并将被发送到 Linux 主机。C.IP:<someport> -> 192.168.2.2:443
10.0.0.1:443. 现在我们有以下形式的数据包:C.IP:<someport> -> 10.0.0.1:443
只有在目的地重写后linux才会查找路由(路由决定)。由于数据包中的源地址仍然是原始的,因此不会涉及您的附加路由规则,并且数据包将通过主路由表进行路由(我假设将GW1使用)。我们会改进它,因为问题的根本原因就在于此。
数据包被发送到GW1througheth0接口。源地址将被-o eth0 -j MASQUERADE规则重写。数据包将被转换为:
192.168.1.2:<otherport> -> 10.0.0.1:443的目标 MAC 地址GW1。
GW1通过额外的源地址重写将该数据包转发到外部网络。<ext1.IP>:<otherport2> -> 10.0.0.1:443
SYN-ACK。答案将如下所示:10.0.0.1:443 -> <ext1.IP>:<otherport2>
GW1到答案,对目标地址进行反向地址转换,并将答案进一步发送到linux主机:10.0.0.1:443 -> 192.168.1.2:<otherport>
SYN-ACK,也进行反向地址转换,并尝试查找路由以进一步转发答案。但是在这一步之后出现了问题,但这只是步骤4问题的结果。为了更好地理解需要检查防火墙规则集。10.0.0.1:443 -> <C.IP>:<someport>
主要目标是通过接收这些数据包的同一接口将数据包路由回。为此,我们将使用简单的路由规则。
ip route add 192.168.1.0/24 dev eth0 table 10
ip route add 0/0 via 192.168.1.1 dev eth0 table 10
ip route add 192.168.2.0/24 dev eth1 table 11
ip route add 0/0 via 192.168.2.1 dev eth1 table 11
Run Code Online (Sandbox Code Playgroud)
ip rule add iif eth0 lookup 10 pref 1010
ip rule add iif eth1 lookup 11 pref 1011
Run Code Online (Sandbox Code Playgroud)
在特定接口上接收到的所有数据包将通过有限的路由表进行路由,其中仅存在单个接口的路由。这是最简单的解决方案,但它消除了 Linux 主机在接口之间转发数据包的能力(从eth0到eth1,反之亦然)。如果这不适合你,还有另一种方法,但它更复杂。如果你需要的话我会描述它。
| 归档时间: |
|
| 查看次数: |
2393 次 |
| 最近记录: |