![无法通过虚拟网桥将端口转发到 Tap 接口](https://linux22.com/image/120021/%E6%97%A0%E6%B3%95%E9%80%9A%E8%BF%87%E8%99%9A%E6%8B%9F%E7%BD%91%E6%A1%A5%E5%B0%86%E7%AB%AF%E5%8F%A3%E8%BD%AC%E5%8F%91%E5%88%B0%20Tap%20%E6%8E%A5%E5%8F%A3.png)
我在 Ubuntu 16.04 上开箱即用地安装了 libvirt,它在 192.168.122.0/24 处创建了一个 virbr0 虚拟桥,这是一个服务于该范围的 dnsmasq 实例,并设置了基本的 NAT 伪装。
我在其下方创建了一个点击界面,供我的虚拟化软件使用。该软件本身能够完美地访问互联网和网络的其余部分,因此伪装工作正常。我还可以使用该软件声明的 IP 地址从主机访问虚拟化软件 ssh 端口。所以我认为“开箱即用”的路由表通常是正确的。
我想要做的是将入站 ssh 连接从外部端口转发到该软件以及整个主机系统。现在主机系统当然有 ssh,我需要它才能工作。所以我尝试使用另一个端口,例如端口 2022。
我在 iptables 中创建了一条 DNAT 规则,将端口 2022 上的入站流量定向到端口 22 处的软件的 IP 地址。当我尝试从外部(例如下面的计算机 A)登录时,我无法访问目标。看起来地址转换正常进行,但在遍历到 iptables 中的“FORWARD”步骤后,我立即开始收到出站无法访问的 ICMP 数据包。
我对如何继续感到困惑。我尝试过一些 SNAT 规则,但要么我搞砸了,要么这不是问题。有人对此有想法吗?
更新:tap0 上的 Wireshark 未显示已收到转发的数据包。返回数据包的内容与虚拟化软件无关。
这是我的网络的图片:
----------
| Internet |
----------
|
|
--------
| Router | 10.211.255.1
--------
|
|
____________|_______________
| |
---------- ---------
| | | enp0s5 | 10.211.255.4
| Computer | 10.211.255.2 | Host | 192.168.122.1
| A | | virbr0 |
---------- ---------
|
| LAN NAT 192.168.122.0/24
|
----------
| tap0 |
| Guest OS | 192.168.122.118
| |
----------
这是我的 IP 表规则:
Chain INPUT (policy ACCEPT)
target prot opt source destination
LOG all -- anywhere anywhere LOG level debug prefix "INTRACE: "
ACCEPT udp -- anywhere anywhere udp dpt:domain
ACCEPT tcp -- anywhere anywhere tcp dpt:domain
ACCEPT udp -- anywhere anywhere udp dpt:bootps
ACCEPT tcp -- anywhere anywhere tcp dpt:bootps
Chain FORWARD (policy ACCEPT)
target prot opt source destination
LOG all -- anywhere anywhere LOG level debug prefix "FORTRACE: "
ACCEPT all -- anywhere 192.168.122.0/24 ctstate RELATED,ESTABLISHED
ACCEPT all -- 192.168.122.0/24 anywhere
ACCEPT all -- anywhere anywhere
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
LOG all -- anywhere anywhere LOG level debug prefix "OUTTRACE: "
ACCEPT udp -- anywhere anywhere udp dpt:bootpc
NAT tables:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
LOG tcp -- anywhere anywhere tcp dpt:2022 LOG level debug prefix "NATPTRACE: "
DNAT tcp -- anywhere anywhere tcp dpt:2022 to:192.168.122.118:22
Chain INPUT (policy ACCEPT)
target prot opt source destination
LOG all -- anywhere anywhere LOG level debug prefix "NATITRACE: "
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
LOG all -- anywhere anywhere LOG level debug prefix "NATOTRACE: "
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
LOG all -- anywhere anywhere LOG level debug prefix "NATQTRACE: "
SNAT tcp -- anywhere anywhere tcp spt:ssh to::2022
RETURN all -- 192.168.122.0/24 base-address.mcast.net/24
RETURN all -- 192.168.122.0/24 broadcasthost.localdomain
MASQUERADE tcp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
MASQUERADE udp -- 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24
最后,这是我在 syslog 中看到的具有上述规则的示例:
Oct 20 09:49:15 ubuntu kernel: [85149.812291] RAWPTRACE: IN=enp0s5 OUT= MAC=00:1c:42:3a:00:df:00:1c:42:00:00:08:08:00 SRC=10.211.55.2 DST=10.211.55.4 LEN=64 TOS=0x00 PREC=0x00 TTL=64 ID=40132 DF PROTO=TCP SPT=53245 DPT=2022 WINDOW=65535 RES=0x00 SYN URGP=0
Oct 20 09:49:15 ubuntu kernel: [85149.812318] MGPTRACE: IN=enp0s5 OUT= MAC=00:1c:42:3a:00:df:00:1c:42:00:00:08:08:00 SRC=10.211.55.2 DST=10.211.55.4 LEN=64 TOS=0x00 PREC=0x00 TTL=64 ID=40132 DF PROTO=TCP SPT=53245 DPT=2022 WINDOW=65535 RES=0x00 SYN URGP=0
Oct 20 09:49:15 ubuntu kernel: [85149.812326] NATPTRACE: IN=enp0s5 OUT= MAC=00:1c:42:3a:00:df:00:1c:42:00:00:08:08:00 SRC=10.211.55.2 DST=10.211.55.4 LEN=64 TOS=0x00 PREC=0x00 TTL=64 ID=40132 DF PROTO=TCP SPT=53245 DPT=2022 WINDOW=65535 RES=0x00 SYN URGP=0
Oct 20 09:49:15 ubuntu kernel: [85149.812336] MGFTRACE: IN=enp0s5 OUT=virbr0 MAC=00:1c:42:3a:00:df:00:1c:42:00:00:08:08:00 SRC=10.211.55.2 DST=192.168.122.118 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=40132 DF PROTO=TCP SPT=53245 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0
Oct 20 09:49:15 ubuntu kernel: [85149.812340] FORTRACE: IN=enp0s5 OUT=virbr0 MAC=00:1c:42:3a:00:df:00:1c:42:00:00:08:08:00 SRC=10.211.55.2 DST=192.168.122.118 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=40132 DF PROTO=TCP SPT=53245 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0
Oct 20 09:49:15 ubuntu kernel: [85149.812354] RAWOTRACE: IN= OUT=enp0s5 SRC=10.211.55.4 DST=10.211.55.2 LEN=92 TOS=0x00 PREC=0xC0 TTL=64 ID=50608 PROTO=ICMP TYPE=3 CODE=3 [SRC=10.211.55.2 DST=192.168.122.118 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=40132 DF PROTO=TCP SPT=53245 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0 ]
Oct 20 09:49:15 ubuntu kernel: [85149.812357] MGOTRACE: IN= OUT=enp0s5 SRC=10.211.55.4 DST=10.211.55.2 LEN=92 TOS=0x00 PREC=0xC0 TTL=64 ID=50608 PROTO=ICMP TYPE=3 CODE=3 [SRC=10.211.55.2 DST=192.168.122.118 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=40132 DF PROTO=TCP SPT=53245 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0 ]
Oct 20 09:49:15 ubuntu kernel: [85149.812361] OUTTRACE: IN= OUT=enp0s5 SRC=10.211.55.4 DST=10.211.55.2 LEN=92 TOS=0x00 PREC=0xC0 TTL=64 ID=50608 PROTO=ICMP TYPE=3 CODE=3 [SRC=10.211.55.2 DST=192.168.122.118 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=40132 DF PROTO=TCP SPT=53245 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0 ]
Oct 20 09:49:15 ubuntu kernel: [85149.812364] MGQTRACE: IN= OUT=enp0s5 SRC=10.211.55.4 DST=10.211.55.2 LEN=92 TOS=0x00 PREC=0xC0 TTL=64 ID=50608 PROTO=ICMP TYPE=3 CODE=3 [SRC=10.211.55.2 DST=192.168.122.118 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=40132 DF PROTO=TCP SPT=53245 DPT=22 WINDOW=65535 RES=0x00 SYN URGP=0 ]
答案1
问题出在 FORWARD 规则中。由于我没有设置它们,所以我误解了 的输出iptables --list
。
该列表中的规则 4 如下:
ACCEPT all -- anywhere anywhere
这似乎接受从任何地方绑定到任何地方的所有传入数据包。
然而,如果我看看iptables -S
规则 4 实际上是:
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
这不会与从 enp0s5 传入、发往 vibr0 的数据包匹配。因此它遇到了 REJECT 规则 5,这实际上是拒绝所有发往 vibr0 的数据包。
我学到的教训是不要相信输出,而是在出现问题时iptables --list
检查输出。iptables -S