在上一节中,我们将两个网段的机器,通过中间机器的网络转发,能达到互通。再来回顾一下这个网络连接的图
上一节我们在防火墙实验中,设置了主机B的的转发规则,我们先清空主机B的转发规则
[root@localhost ~]# iptables -F FORWARD
这时候,A和C也是能够互通的
一、SNAT
查看一下主机B的两个网卡
[root@localhost ~]# ifconfig
enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.56.106 netmask 255.255.255.0 broadcast 192.168.56.255
inet6 fe80::db6e:9a5d:7349:6075 prefixlen 64 scopeid 0x20<link>
ether 08:00:27:c4:c4:34 txqueuelen 1000 (Ethernet)
RX packets 2132 bytes 878351 (857.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1802 bytes 417950 (408.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
enp0s9: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.1.0.11 netmask 255.255.0.0 broadcast 10.1.255.255
inet6 fe80::6f7e:d360:eb44:50d2 prefixlen 64 scopeid 0x20<link>
ether 08:00:27:21:7b:f0 txqueuelen 1000 (Ethernet)
RX packets 3199 bytes 310848 (303.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3080 bytes 963634 (941.0 KiB)
主机C ping 主机A
[root@test-c ~]# ping 192.168.56.104
PING 192.168.56.104 (192.168.56.104) 56(84) bytes of data.
64 bytes from 192.168.56.104: icmp_seq=1 ttl=63 time=1.60 ms
64 bytes from 192.168.56.104: icmp_seq=2 ttl=63 time=1.81 ms
64 bytes from 192.168.56.104: icmp_seq=3 ttl=63 time=1.83 ms
64 bytes from 192.168.56.104: icmp_seq=4 ttl=63 time=1.61 ms
主机A tcpdump查看icmp报文
[root@localhost ~]# tcpdump -i enp0s8 -nn icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s8, link-type EN10MB (Ethernet), capture size 262144 bytes
03:25:52.191447 IP 10.1.0.10 > 192.168.56.104: ICMP echo request, id 2681, seq 8, length 64
03:25:52.191525 IP 192.168.56.104 > 10.1.0.10: ICMP echo reply, id 2681, seq 8, length 64
03:25:53.192233 IP 10.1.0.10 > 192.168.56.104: ICMP echo request, id 2681, seq 9, length 64
可以发现是直连的,IP没有变化
然后开启主机B的NAT后,再在主机A上查看tcpdump的报文
[root@localhost ~]# iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 192.168.56.106
主机A上看到的是106主机B,请求到本机
[root@localhost ~]# tcpdump -i enp0s8 -nn icmp
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s8, link-type EN10MB (Ethernet), capture size 262144 bytes
03:23:08.675793 IP 192.168.56.106 > 192.168.56.104: ICMP echo request, id 2663, seq 1, length 64
03:23:08.675845 IP 192.168.56.104 > 192.168.56.106: ICMP echo reply, id 2663, seq 1, length 64
03:23:09.677209 IP 192.168.56.106 > 192.168.56.104: ICMP echo request, id 2663, seq 2, length 64
03:23:09.677292 IP 192.168.56.104 > 192.168.56.106: ICMP echo reply, id 2663, seq 2, length 64
二、DNAT
在主机B192.168.56.106 上设置转发规则如下
[root@localhost ~]# iptables -t nat -I PREROUTING -d 192.168.56.106 -p tcp --dport 801 -j DNAT --to-destination 10.1.0.10:80
即访问106机器的801端口,会将数据转发到C主机的80端口上
C主机开启httpd服务
这时候,主机A尝试访问一下
[root@localhost ~]# curl -X GET http://192.168.56.106:801
可以访问到数据
同时在主机B上tcpdump查看一下报文
[root@localhost ~]# tcpdump -i enp0s8 -p tcp port 801 -nn
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s8, link-type EN10MB (Ethernet), capture size 262144 bytes
05:06:16.442102 IP 192.168.56.104.35408 > 192.168.56.106.801: Flags [S], seq 2976570142, win 29200, options [mss 1460,sackOK,TS val 3328446820 ecr 0,nop,wscale 7], length 0
05:06:16.443153 IP 192.168.56.106.801 > 192.168.56.104.35408: Flags [S.], seq 2959350184, ack 2976570143, win 28960, options [mss 1460,sackOK,TS val 1165808246 ecr 3328446820,nop,wscale 7], length 0
05:06:16.445879 IP 192.168.56.104.35408 > 192.168.56.106.801: Flags [.], ack 1, win 229, options [nop,nop,TS val 3328446823 ecr 1165808246], length 0
05:06:16.446365 IP 192.168.56.104.35408 > 192.168.56.106.801: Flags [P.], seq 1:83, ack 1, win 229, options [nop,nop,TS val 3328446823 ecr 1165808246], length 82
05:06:16.447290 IP 192.168.56.106.801 > 192.168.56.104.35408: Flags [.], ack 83, win 227, options [nop,nop,TS val 1165808249 ecr 3328446823], length 0
05:06:16.448087 IP 192.168.56.106.801 > 192.168.56.104.35408: Flags [.], seq 1:14481, ack 83, win 227, options [nop,nop,TS val 1165808250 ecr 3328446823], length 14480
05:06:16.448587 IP 192.168.56.104.35408 > 192.168.56.106.801: Flags [.], ack 14481, win 455, options [nop,nop,TS val 3328446826 ecr 1165808250], length 0
05:06:16.450968 IP 192.168.56.106.801 > 192.168.56.104.35408: Flags [.], seq 14481:37649, ack 83, win 227, options [nop,nop,TS val 1165808252 ecr 3328446826], length 23168
05:06:16.451369 IP 192.168.56.104.35408 > 192.168.56.106.801: Flags [.], ack 37649, win 817, options [nop,nop,TS val 3328446829 ecr 1165808252], length 0
05:06:16.451483 IP 192.168.56.106.801 > 192.168.56.104.35408: Flags [P.], seq 37649:43441, ack 83, win 227, options [nop,nop,TS val 1165808253 ecr 3328446826], length 5792
05:06:16.452178 IP 192.168.56.104.35408 > 192.168.56.106.801: Flags [.], ack 43441, win 907, options [nop,nop,TS val 3328446829 ecr 1165808253], length 0
三、动作MASQUERADE
上文中,我们已经描述了SNAT,也就是源地址转换,那么我们现在来认识一个与SNAT类似的动作:MASQUERADE
当我们拨号网上时,每次分配的IP地址往往不同,不会长期分给我们一个固定的IP地址,如果这时,我们想要让内网主机共享公网IP上网,就会很麻烦,因为每次IP地址发生变化以后,我们都要重新配置SNAT规则,这样显示不是很人性化,我们通过MASQUERADE即可解决这个问题,MASQUERADE会动态的将源地址转换为可用的IP地址,其实与SNAT实现的功能完全一致,都是修改源地址,只不过SNAT需要指明将报文的源地址改为哪个IP,而MASQUERADE则不用指定明确的IP,会动态的将报文的源地址修改为指定网卡上可用的IP地址,示例如下:
[root@localhost ~]# iptables -t nat -I POSTROUTING -s 10.1.0.0/24 -o enp0s8 -j MASQUERADE
如上图所示,我们指定,通过外网网卡出去的报文在经过POSTROUTING链时,会自动将报文的源地址修改为外网网卡上可用的IP地址,这时,即使外网网卡中的公网IP地址发生了改变,也能够正常的、动态的将内部主机的报文的源IP映射为对应的公网IP。
可以把MASQUERADE理解为动态的、自动化的SNAT,如果没有动态SNAT的需求,没有必要使用MASQUERADE,因为SNAT更加高效。
四、动作REDIRECT
使用REDIRECT动作可以在本机上进行端口映射
比如,将本机的8081端口映射到本机的80端口上
主机A(192.168.56.104)做如下设置
[root@localhost ~]# iptables -t nat -A PREROUTING -p tcp --dport 8081 -j REDIRECT --to-ports 80
经过上述规则映射后,当别的机器访问本机的8081端口时,报文会被重定向到本机的80端口上。
当其它主机访问下面的地址时(104主机80端口提供服务),能成功请求
[root@test-c ~]# curl -X GET http://192.168.56.104:8081
REDIRECT规则只能定义在PREROUTING链或者OUTPUT链中。
五、小结
为了方便以后回顾,我们对上述命令进行总结。
如果想要NAT功能能够正常使用,需要开启Linux主机的核心转发功能。
echo 1 > /proc/sys/net/ipv4/ip_forward
- SNAT相关操作
配置SNAT,可以隐藏网内主机的IP地址,也可以共享公网IP,访问互联网,如果只是共享IP的话,只配置如下SNAT规则即可。
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP
如果公网IP是动态获取的,不是固定的,则可以使用MASQUERADE进行动态的SNAT操作,如下命令表示将10.1网段的报文的源IP修改为eth0网卡中可用的地址。
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -o eth0 -j MASQUERADE
- DNAT相关操作
配置DNAT,可以通过公网IP访问局域网内的服务。
注:理论上来说,只要配置DNAT规则,不需要对应的SNAT规则即可达到DNAT效果。
但是在测试DNAT时,对应SNAT规则也需要配置,才能正常DNAT,可以先尝试只配置DNAT规则,如果无法正常DNAT,再尝试添加对应的SNAT规则,SNAT规则配置一条即可,DNAT规则需要根据实际情况配置不同的DNAT规则。
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 公网端口 -j DNAT --to-destination 私网IP:端口号
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 8080 -j DNAT --to-destination
10.1.0.1:80iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP
在本机进行目标端口映射时可以使用REDIRECT动作。
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
配置完成上述规则后,其他机器访问本机的80端口时,会被映射到8080端口。