Ubuntu 22.04下KVM虚拟机端口转发问题:虚拟机无法通过宿主机公网IP访问自身映射端口
Ubuntu 22.04下KVM虚拟机端口转发问题:虚拟机无法通过宿主机公网IP访问自身映射端口
你遇到的这个问题其实很典型,属于**Hairpin NAT(发夹NAT)**配置缺失导致的。简单来说,当虚拟机通过宿主机公网IP访问自己的映射端口时,数据包虽然能通过DNAT转到虚拟机,但虚拟机的响应数据包会直接走自己的默认网关(也就是宿主机的虚拟网桥)往外发,不会回到宿主机做反向NAT,导致整个连接的闭环断了,所以才会出现超时。
下面给你一步步解决的方案:
1. 确认宿主机IP转发已开启
首先确保宿主机的IPv4转发功能是打开的,这是所有NAT转发的前提:
- 临时开启:
echo 1 > /proc/sys/net/ipv4/ip_forward
- 永久生效(重启后不失效):
编辑/etc/sysctl.conf文件,找到net.ipv4.ip_forward=1这一行,去掉前面的注释符号#,然后执行:
sysctl -p
2. 添加Hairpin NAT的SNAT规则
你已经配置了PREROUTING和OUTPUT链的DNAT规则,现在需要添加一条POSTROUTING链的SNAT规则,修正虚拟机回包的路径:
iptables -t nat -A POSTROUTING -s 192.168.122.0/24 -d 192.168.122.201 -p tcp --dport 22 -j SNAT --to-source 192.168.122.1
这条规则的作用是:当来自KVM虚拟机网段(192.168.122.0/24)的数据包,目标是你的虚拟机IP(192.168.122.201)的22端口时,把数据包的源地址改成宿主机虚拟网桥的IP(192.168.122.1,这是KVM默认虚拟网桥的地址,如果你的网桥IP不一样,记得替换)。这样虚拟机收到数据包后,会把回应发给宿主机,再由宿主机转发回虚拟机,形成完整的连接闭环。
3. 测试连接
现在回到虚拟机里,再次执行:
ssh -p 1023 222.222.222.222
应该就能正常连接了。
补充说明
为什么宿主机自己能访问?因为宿主机访问自身公网IP时,数据包走的是OUTPUT链的DNAT,回包直接在本地内核处理,不需要经过外部网络,所以没问题。而虚拟机的情况是数据包需要经过宿主机的NAT转换,但回包路径没有被正确修正,所以必须添加这条Hairpin NAT规则。
备注:内容来源于stack exchange,提问作者hwang
相关产品推荐
相关产品推荐

