定义
host
= 172.16.1.155 是公网 IP(sed
为了保持一致,我们对其进行了修改)。guest
= 192.168.122.10 是在IP为172.16.1.155的物理机上运行的虚拟机的IP。
情况
对于有问题的两个主机,我有以下规则(转储iptables-save
和过滤)(以及理解上下文所需的所有规则):
*filter
-A INPUT -d 172.16.1.155/32 -p tcp -m multiport --dports 25,465 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -j DROP
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -i _+ -o _+ -j ACCEPT
-A FORWARD -i _+ -o eth0 -j ACCEPT
-A FORWARD -d 192.168.122.10/32 -p tcp -m multiport --dports 25,465 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -j LOG
-A FORWARD -j DROP
COMMIT
*nat
-A PREROUTING -d 172.16.1.155/32 -p tcp -m multiport --dports 25,465 -j DNAT --to-destination 192.168.122.10
COMMIT
这些规则确保来自外界对公共 IP 的任何请求host
实际上都会进入guest
。所有这些都运行良好,符合预期。还有更多规则,但它们仅影响其他客户机或具有不相关的目的。客户机的所有接口都以下划线开头,因此我可以方便地使用它_+
来匹配上述规则中的接口名称。
虚拟机都是 KVM 客户机。桥接接口的名称是virbr0
。每个具有外部 IP 地址的虚拟机都有一个以其命名的接口,但前面带有下划线(因此客户机foo
将具有接口_foo
)。
另外,KVM 为每个客户机创建一个vnetX
(X
一个数字)接口。
host
针对所讨论的问题设定了以下路线guest
:
172.16.1.155 * 255.255.255.255 UH 0 0 0 eth0
192.168.122.0 * 255.255.255.0 U 0 0 0 virbr0
default 172.16.1.155 0.0.0.0 UG 100 0 0 eth0
问题
如果我通过 SSH 进入host
( ssh -D
) 创建 SOCKS 代理,则无法通过该代理进行连接guest
。首先,我认为原因是 SOCKS 代理可能会使用侧面的lo
接口 (确认这一点) ,因此我添加了以下规则(请记住 已经接受输入),但这应该已被 覆盖。因此,我再次删除了该规则并尝试了以下 NAT 规则:以及随后的等效规则(出于所有实际目的)。两者都没有给我想要的结果。tcpdump -i lo
host
iptables -I FORWARD -i lo -p tcp -m multiport --dports 25,465 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A FORWARD -d 192.168.122.10/32 -p tcp -m multiport --dports 25,465 -j ACCEPT
iptables -t nat -I PREROUTING -d 127.0.0.1/24 -p tcp -m multiport --dports 25,465 -j DNAT --to-destination 192.168.122.10
iptables -t nat -I PREROUTING -i lo -p tcp -m multiport --dports 25,465 -j DNAT --to-destination 192.168.122.10
我该如何弥补这种情况下存在的差距?此外,我可以使用 来测试 SOCKS 代理是否正常工作,这一假设是否有效telnet 127.0.0.1 25
?
因此我按照 mgorven 的建议添加了规则iptables -t nat -D OUTPUT -d 127.0.0.1/24 -p tcp -m multiport --dports 25,465 -j DNAT --to-destination 192.168.122.10
。这里的行为显然发生了变化,但还不是我所期望的。
如果没有这条规则我会得到:
$ telnet localhost 25
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
根据该规则我得到:
$ telnet localhost 25
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection timed out
答案1
对于来自主机的数据包,PREROUTING 链不会被遍历(此图对于确定数据包将遍历哪些链很有用)。您需要将这些规则放入nat
表的 OUTPUT 链中。