网上有不少文章,介绍通过设置防火墙规则中的端口转发实现外部主机访问内网的NAT主机,在实际使用中发现会遇到问题,这篇文章主要是想记录一下自己的使用场景、遇到的问题以及解决方法。
1.拓扑环境及需求
如下图所示。我本人有一个主机(地址192.168.131.178),还有一台服务器(地址192.168.131.222),服务器能够通过另一个接口访问互联网。现在需要在服务器上创建一些虚拟机给自己和他人使用,图中显示是1台虚拟机的情形。虚拟机通过NAT方式连接到virbr0桥上,因此也能够访问互联网。
现在需求是让192.168.131.0/24网段的其他主机也能够直接通过SSH访问到虚拟机,相当于让其他人以为自己都有一台自己可以控制的、能够联网的服务器。
2.设置防火墙规则及问题
由于虚拟机是在服务器的NAT后面,地址为192.168.122.0/24网段的地址,所以192.168.131.0/24网段的主机是无法直接访问到虚拟机的,需要用到端口转发的方式。
在服务器上通过添加防火墙规则设置端口转发如下:
firewall-cmd --zone=public --add-forward-port=port=1122:proto=tcp:toport=22:toaddr=192.168.122.25
上述命令的目的是:对于服务器收到的目的端口为1122的数据包,修改数据包的目的端口为22(SSH服务端口),修改数据包目的IP地址为192.168.122.25,即虚拟机的地址。
这样做了以后,服务器会根据本地的路由表,使数据包通过virbr0接口发出,送到virbr0桥上(这里需要理解virbr0接口和virbr0桥的关系),最终送到虚拟机接口。
但实际使用过程中,我发现添加了上述规则后仍然无法通过192.168.131.222:1122去实现虚拟机的SSH访问。
3.分析和解决办法
最终通过分析和查看防火墙中的丢包情况,发现是因为忽略了另一个规则:允许转发。
实际上步骤2中设置的防火墙规则只是做了一个DNAT,在服务器内核修改了数据包的目的端口和目的IP后,将数据包发送到虚拟机,实际上是数据包从服务器一个接口进、从另一个接口(虚拟)出的转发过程,因此,需要在FORWARD链中再添加一条规则,允许从em2接口过来的、到virbr0 接口的、目的端口为22的TCP数据包通过。规则如下(注意该条规则插入的位置是与服务器防火墙规则设置有关的,请根据实际情况确定):
iptables -t filter -I FORWARD 3 -i em2 -o virbr0 -p tcp --dport=22 -j ACCEPT
添加上述规则后便可以直接通过SSH访问192.168.131.222:1122去控制虚拟机。
下面给出部分截图。