NAT分SNAT和DNAT两种。从名字上区分:
-
SNAT将源IP地址替换为出口网络的IP地址,以便内网地址可以访问外网服务。一般受限于公网IP有限,一个内网集合想访问外网服务,则用统一的出口做代理。出口配置公网IP,帮助从此发出的包找到回来的路。
-
DNAT将目的IP地址替换为真实服务的IP地址,以便外网地址可以访问内网服务。一般情况用于内网服务要暴露到公网,提供统一的入口地址。
我们用PC1、和EXT模拟两个不同的子网环境(也可以看作内网和外网)。PXY作为网关
先创建实验需要的namespace
ip netns add PC1
ip netns add PXY
ip netns add EXTip link add PC1_PXY type veth peer name PXY_PC1
ip link add PXY_EXT type veth peer name EXT_PXYip link set PC1_PXY netns PC1
ip link set EXT_PXY netns EXT
ip link set PXY_PC1 netns PXY
ip link set PXY_EXT netns PXY
SNAT实验
要达到的目的:在PC1里面要能ping同EXT里面的2.2.2.2、100.100.100.2
基础配置
PC1配置
[root@i-pvirg1hu ~]# ip netns exec PC1 bash
[root@i-pvirg1hu ~]# ip address add 192.168.1.1/24 dev PC1_PXY
[root@i-pvirg1hu ~]# ip link set PC1_PXY up
配置到网关的路由
[root@i-pvirg1hu ~]# ip route add default dev PC1_PXY via 192.168.1.254
PXY配置
[root@i-pvirg1hu ~]# ip netns exec PXY bash
[root@i-pvirg1hu ~]# ip address add 192.168.1.254/24 dev PXY_PC1
[root@i-pvirg1hu ~]# ip address add 100.100.100.1/24 dev PXY_EXT
[root@i-pvirg1hu ~]# ip link set PXY_PC1 up
[root@i-pvirg1hu ~]# ip link set PXY_EXT up
查看下当前路由信息
[root@i-pvirg1hu ~]# ip r
100.100.100.0/24 dev PXY_EXT proto kernel scope link src 100.100.100.1
192.168.1.0/24 dev PXY_PC1 proto kernel scope link src 192.168.1.254
配置网关的默认路由
[root@i-pvirg1hu ~]# ip route add default dev PXY_EXT via 100.100.100.2
EXT配置
[root@i-pvirg1hu ~]# ip netns exec EXT bash
[root@i-pvirg1hu ~]# ip address add 100.100.100.2/24 dev EXT_PXY
[root@i-pvirg1hu ~]# ip link set EXT_PXY up
SVR相关
[root@i-pvirg1hu ~]# ip link add SVR type dummy
[root@i-pvirg1hu ~]# ip address add 2.2.2.2/32 dev SVR
[root@i-pvirg1hu ~]# ip link set SVR up
查看下当前路由信息
[root@i-pvirg1hu ~]# ip r
100.100.100.0/24 dev EXT_PXY proto kernel scope link src 100.100.100.2
[root@i-pvirg1hu ~]#
以上基础配置完毕后,我们还不能在PC1上ping通2.2.2.2和100.100.100.2
配置SNAT
现在我们做SNAT在PXY上
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to 100.100.100.1
做了SNAT后,就能ping通2.2.2.2和100.100.100.2
详细解释一下这条 iptables
命令:
-
iptables -t nat
: 这个选项指定了要操作的iptables
表为nat
表。nat
表主要用于对数据包的源地址或目的地址进行转换。 -
-A POSTROUTING
: 这个选项指定了要添加规则的链为POSTROUTING
链。POSTROUTING
链是在数据包从本机转发出去之前最后一个可以修改的位置。 -
-s 192.168.1.0/24
: 这个选项指定了规则的匹配条件为数据包的源地址在192.168.1.0/24
网段内。也就是说,这条规则只会对从192.168.1.0/24
网段发出的数据包起作用。 -
-j SNAT --to 100.100.100.1
: 这个选项指定了如何处理匹配到的数据包。-j SNAT
表示要对数据包执行 SNAT(Source Network Address Translation)操作,也就是修改数据包的源 IP 地址。--to 100.100.100.1
表示把数据包的源 IP 地址修改为100.100.100.1
。
总的来说,这条 iptables
规则的作用是:
在 iptables
的 nat
表的 POSTROUTING
链上,对从 192.168.1.0/24
网段发出的数据包执行 SNAT 操作,将源 IP 地址修改为 100.100.100.1
。
这种 SNAT 操作通常用于实现内网用户访问外网时,将内网地址转换为公网地址的功能。例如,内网用户通过 NAT 访问外网时,可以将内网 IP 地址修改为公网 IP 地址 100.100.100.1
。这样可以隐藏内网用户的真实 IP 地址,提高安全性。
抓包看看
在PC1上ping -c 5 100.100.100.2
然后在EXT上抓包看看tcpdump -i EXT_PXY -nel。可以看到确实将源地址转为了100.100.100.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on EXT_PXY, link-type EN10MB (Ethernet), capture size 262144 bytes
16:05:07.133629 1a:80:9a:d3:7c:a5 > 92:b9:5f:97:29:de, ethertype IPv4 (0x0800), length 98: 100.100.100.1 > 100.100.100.2: ICMP echo request, id 13262, seq 1, length 64
16:05:07.133641 92:b9:5f:97:29:de > 1a:80:9a:d3:7c:a5, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 100.100.100.1: ICMP echo reply, id 13262, seq 1, length 64
16:05:08.160148 1a:80:9a:d3:7c:a5 > 92:b9:5f:97:29:de, ethertype IPv4 (0x0800), length 98: 100.100.100.1 > 100.100.100.2: ICMP echo request, id 13262, seq 2, length 64
16:05:08.160173 92:b9:5f:97:29:de > 1a:80:9a:d3:7c:a5, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 100.100.100.1: ICMP echo reply, id 13262, seq 2, length 64
16:05:09.185148 1a:80:9a:d3:7c:a5 > 92:b9:5f:97:29:de, ethertype IPv4 (0x0800), length 98: 100.100.100.1 > 100.100.100.2: ICMP echo request, id 13262, seq 3, length 64
16:05:09.185186 92:b9:5f:97:29:de > 1a:80:9a:d3:7c:a5, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 100.100.100.1: ICMP echo reply, id 13262, seq 3, length 64
16:05:10.208447 1a:80:9a:d3:7c:a5 > 92:b9:5f:97:29:de, ethertype IPv4 (0x0800), length 98: 100.100.100.1 > 100.100.100.2: ICMP echo request, id 13262, seq 4, length 64
16:05:10.208497 92:b9:5f:97:29:de > 1a:80:9a:d3:7c:a5, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 100.100.100.1: ICMP echo reply, id 13262, seq 4, length 64
16:05:11.232869 1a:80:9a:d3:7c:a5 > 92:b9:5f:97:29:de, ethertype IPv4 (0x0800), length 98: 100.100.100.1 > 100.100.100.2: ICMP echo request, id 13262, seq 5, length 64
16:05:11.232910 92:b9:5f:97:29:de > 1a:80:9a:d3:7c:a5, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 100.100.100.1: ICMP echo reply, id 13262, seq 5, length 64
16:05:12.224767 1a:80:9a:d3:7c:a5 > 92:b9:5f:97:29:de, ethertype ARP (0x0806), length 42: Request who-has 100.100.100.2 tell 100.100.100.1, length 28
16:05:12.224863 92:b9:5f:97:29:de > 1a:80:9a:d3:7c:a5, ethertype ARP (0x0806), length 42: Reply 100.100.100.2 is-at 92:b9:5f:97:29:de, length 28
深入
todo
DNAT实验
要达到的效果是在EXT里面ping 100.100.100.1时在PC1上能收到对应的包
我们在PXY上做DNAT
iptables -t nat -A PREROUTING -d 100.100.100.1 -j DNAT --to-destination 192.168.1.1
这条 iptables
命令的作用是设置 DNAT(目标 NAT)规则,用于将目的地址为 100.100.100.1
的数据包重定向到 192.168.1.1
。具体来说:
-
iptables -t nat -A PREROUTING
: 这部分表示添加一条 NAT 表的PREROUTING
链规则。PREROUTING
链是在数据包进入本机时被调用的。 -
-d 100.100.100.1
: 这部分指定了目的地址为100.100.100.1
的数据包才会被这条规则匹配到。 -
-j DNAT
: 这部分指定了当规则被匹配时要执行的动作是DNAT
。DNAT
动作会将数据包的目的 IP 地址转换为指定的地址。 -
--to-destination 192.168.1.1
: 这部分指定了数据包的目的地址要转换为192.168.1.1
。
综合起来,这条命令的作用是:当数据包的目的地址为 100.100.100.1
时,将其目的地址转换为 192.168.1.1
。这通常用于实现端口转发或虚拟主机等功能,例如将访问 100.100.100.1:80
的流量转发到内部的 192.168.1.1:80
。
添加规则后,用检查下iptables -t nat -vnL检查下,可以看到成功添加
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)pkts bytes target prot opt in out source destination 0 0 DNAT all -- * * 0.0.0.0/0 100.100.100.1 to:192.168.1.1Chain INPUT (policy ACCEPT 0 packets, 0 bytes)pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)pkts bytes target prot opt in out source destination 4 336 SNAT all -- * * 192.168.1.0/24 0.0.0.0/0 to:100.100.100.1Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)pkts bytes target prot opt in out source destination
接着我们去EXT上ping -c 5 100.100.100.1,然后在PC1上抓包看效果
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on PC1_PXY, link-type EN10MB (Ethernet), capture size 262144 bytes
14:39:51.535160 96:20:c1:bf:de:38 > f2:59:8f:fd:4c:1f, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 192.168.1.1: ICMP echo request, id 5192, seq 1, length 64
14:39:51.535174 f2:59:8f:fd:4c:1f > 96:20:c1:bf:de:38, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 100.100.100.2: ICMP echo reply, id 5192, seq 1, length 64
14:39:52.570353 96:20:c1:bf:de:38 > f2:59:8f:fd:4c:1f, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 192.168.1.1: ICMP echo request, id 5192, seq 2, length 64
14:39:52.570377 f2:59:8f:fd:4c:1f > 96:20:c1:bf:de:38, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 100.100.100.2: ICMP echo reply, id 5192, seq 2, length 64
14:39:53.594362 96:20:c1:bf:de:38 > f2:59:8f:fd:4c:1f, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 192.168.1.1: ICMP echo request, id 5192, seq 3, length 64
14:39:53.594386 f2:59:8f:fd:4c:1f > 96:20:c1:bf:de:38, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 100.100.100.2: ICMP echo reply, id 5192, seq 3, length 64
14:39:54.618336 96:20:c1:bf:de:38 > f2:59:8f:fd:4c:1f, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 192.168.1.1: ICMP echo request, id 5192, seq 4, length 64
14:39:54.618363 f2:59:8f:fd:4c:1f > 96:20:c1:bf:de:38, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 100.100.100.2: ICMP echo reply, id 5192, seq 4, length 64
14:39:55.642347 96:20:c1:bf:de:38 > f2:59:8f:fd:4c:1f, ethertype IPv4 (0x0800), length 98: 100.100.100.2 > 192.168.1.1: ICMP echo request, id 5192, seq 5, length 64
14:39:55.642371 f2:59:8f:fd:4c:1f > 96:20:c1:bf:de:38, ethertype IPv4 (0x0800), length 98: 192.168.1.1 > 100.100.100.2: ICMP echo reply, id 5192, seq 5, length 64
用nc验证下,在PC1监听一个端口
nc -l -p 9999
在EXT去用nc连接
nc 100.100.100.1 9999
然后从PC1发消息EXT也能正常收到,DNAT成功