我想将 ssh 流量从 A 端口 2222 转发到 B 端口 22。我在两个接口上都已将 ipv4 转发设置为 1。但仍然不起作用。哪里出了问题?
机器A:eth0 192.168.0.150
eth1217.27.166.110
机器B:eth0192.168.0.200
iptables -L
:
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT icmp -- anywhere anywhere icmp echo-request
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- anywhere 192.168.0.200 tcp dpt:ssh state NEW,RELATED,ESTABLISHED
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
iptables -L -t nat
:
root@lbpub01:~# iptables -L -tnat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere 217.27.166.110 tcp dpt:2222 to:192.168.0.200:22
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 217.27.166.110 192.168.0.200 tcp dpt:ssh
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
更新
我得到了 irc@freenode 的好心人的帮助,所以这是我的工作iptables-save
文件:
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp -d 217.27.166.110 --dport 2222 -j DNAT --to-destination 192.168.0.200:22
-A POSTROUTING -o eth+ -j MASQUERADE
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp --dport http -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -j DROP
COMMIT
答案1
我已经研究这个问题一段时间了。对我来说似乎有效的解决方案(至少在我使用虚拟机演示时)最终看起来与您在此处发布的内容有很大不同。
很快,以下是我的配置:
iptables -L
:
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
iptables -S
:
-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
(需要澄清的是,最后的 INPUT 规则是允许 ssh 访问机器 A。)
iptables -t nat -L
:
Chain PREROUTING (policy ACCEPT) target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:2222 to:192.168.0.200:22Chain INPUT (policy ACCEPT) target prot opt source destination
Chain OUTPUT (policy ACCEPT) target prot opt source destination
Chain POSTROUTING (policy ACCEPT) target prot opt source destination
SNAT tcp -- anywhere anywhere tcp dpt:22 to:217.27.166.110
iptables -t nat -S
:
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A PREROUTING -i eth0 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 192.168.0.200:22
-A POSTROUTING -p tcp -m tcp --dport 22 -j SNAT --to-source 217.27.166.110
因此,有趣的是,我不需要 FORWARD 链中的任何东西,但看起来 PREROUTING 规则足以将来自客户端的第一个数据包转发到机器 B。
iptables -t nat -A PREROUTING -i <external_interface> -p <tcp/udp> --dport <port_to_accept_connections_through> -j DNAT --to <destination_address:destination_port>
那么,问题就是响应数据包在通过网关时丢失了。直到我使用 Wireshark 测试了机器 A 上的 eth1 并注意到发往机器 B 的数据包上的源地址仍然是客户端机器的源地址时,我才意识到这一点。然后我使用 POSTROUTING 表将源地址更改为 eth1 上机器 A 的 IP 地址,这样机器 B 就知道将响应发送到机器 A 而不是网关。
iptables -t nat -A POSTROUTING -p <tcp/udp> --dport <destination_port> -j SNAT --to <internal_IP_address_of_machine_a>
此时,我能够从与机器 A 的 eth0 接口位于同一网络上的客户端与机器 B 建立连接。虽然我不能 100% 确定防火墙如何处理从机器 B 发送到客户端机器的响应数据包,但我认为最可能的原因是 INPUT 链中的规则允许通过防火墙建立连接:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT