配置SNAT转发实现无公网IP机器上网

发布于:9/19/2019, 10:18:07 PM @孙博
技术分享 | 运维,后端,阿里云,SNAT
许可协议:署名-非商业性使用(by-nc)

SNAT全称为Source Network Address Translation,其实就是源地址转换,通过iptables配置转发规则,使内网转发到网关的请求IP地址可以变更为指定的地址。大家自家家里的路由器往往就可以看做是一个NAT网关,路由器通过拨号从ISP那里获得一个外网IP地址(如 45.67.8.90),由路由器通过DHCP协议为子网内的机器分配内网地址(如 192.168.0.123 等),同时路由器也会为自己分配一个同一网段的地址(如192.168.0.1),如果子网内的机器想要访问外部网络,比如想要打开本站(www.luckystarry.com),那么在浏览器发出请求后,DNS会先将域名转化为IP地址121.196.193.53,其网络流量会先发送到网关——即路由器192.168.0.1,由路由器将请求来源地址192.168.0.123修改为45.67.8.90后,再将其转发到真实的外部地址,在服务器返回响应时,也是先返回至路由器,由路由器将数据包的目的IP修改为内网机器的IP后192.168.0.123,内网机器便可收到此次请求的响应。

通过SNAT,我们仅需有一台具备外网IP的机器,便可让同一子网的所有机器都能与外部通信,如果是建立在阿里云的VPC条件时,就意味着我们不需要为每台机器都绑定一个外网网卡,也能让所有机器对外发送请求。虽然阿里云提供了成熟的NAT网关服务,但其高昂的售价(306元一个月)对于流量较小的站长来说,既不必要也不实惠。

本文以阿里云VPC环境为例,测试需要VPC中有至少一台自带公网带宽的ECS,或绑定了EIP的ECS


环境介绍

  • ECS两台:10.100.1.23610.100.1.237
  • EIP一个:121.41.23.23实验完成后释放),已绑定在10.100.1.237机器上

我们分别登陆到两台机器,并尝试访问百度。

首先是有公网IP的机器

[root@iZbp15wvwv3b9n7p9le33lZ ~]# ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=50 time=37.3 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=2 ttl=50 time=37.4 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=3 ttl=50 time=37.9 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=4 ttl=50 time=37.3 ms
^C
--- baidu.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 37.317/37.533/37.975/0.323 ms
[root@iZbp15wvwv3b9n7p9le33lZ ~]# 

然后是没有公网IP的机器

[root@iZbp15wvwv3b9n7p9le33kZ ~]# ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
^C
--- baidu.com ping statistics ---
33 packets transmitted, 0 received, 100% packet loss, time 31999ms
[root@iZbp15wvwv3b9n7p9le33kZ ~]#    

很明显可以看出没有公网IP的机器是无法联网的。

我们为带有公网的机器配置SNAT转发

如果机器没有iptables可自行安装,CentOS下安装命令为:yum install iptables-services

我们可以先查一下当前的NAT配置

[root@iZbp15wvwv3b9n7p9le33lZ ~]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
[root@iZbp15wvwv3b9n7p9le33lZ ~]# 

打开并编辑/etc/sysctl.conf,添加或修改项目 net.ipv4.ip_forward 使其值等于 1

[root@iZbp15wvwv3b9n7p9le33lZ ~]# cat /etc/sysctl.conf 
vm.swappiness = 0
net.ipv4.neigh.default.gc_stale_time = 120

# see details in https://help.aliyun.com/knowledge_detail/39428.html
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2

net.ipv4.ip_forward = 1

# see details in https://help.aliyun.com/knowledge_detail/41334.html
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

kernel.sysrq = 1

[root@iZbp15wvwv3b9n7p9le33lZ ~]# 

重新加载配置使其生效

[root@iZbp15wvwv3b9n7p9le33lZ ~]# sysctl -p
vm.swappiness = 0
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
net.ipv4.ip_forward = 1
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
kernel.sysrq = 1
[root@iZbp15wvwv3b9n7p9le33lZ ~]# 

配置转发规则,使子网网段的所有请求全部将请求源IP改为网关IP。

[root@iZbp15wvwv3b9n7p9le33lZ ~]# iptables -t nat -I POSTROUTING -s 10.100.1.0/24 -j SNAT --to-source 10.100.1.237
[root@iZbp15wvwv3b9n7p9le33lZ ~]# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
SNAT       all  --  10.100.1.0/24        anywhere             to:10.100.1.237
[root@iZbp15wvwv3b9n7p9le33lZ ~]# 

修改子网中的路由表

我们打开VPC的后台管理,在路由表中新增加一条条目:将发往0.0.0.0/0的请求下一跳设置为网关的那台ECS。

设置完成后我们再次尝试访问百度

[root@iZbp15wvwv3b9n7p9le33kZ ~]# ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=49 time=38.2 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=2 ttl=49 time=37.8 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=3 ttl=49 time=37.7 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=4 ttl=49 time=38.0 ms
^C
--- baidu.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 37.700/37.950/38.245/0.283 ms
[root@iZbp15wvwv3b9n7p9le33kZ ~]#

现在可以看到即使是没有公网IP的机器也可以访问外网了。通过traceroute也可以看到,第一跳确实也是被发往了带有公网IP的那台主机。

[root@iZbp15wvwv3b9n7p9le33kZ ~]# traceroute baidu.com
traceroute to baidu.com (220.181.38.148), 30 hops max, 60 byte packets
1  10.100.1.237 (10.100.1.237)  0.828 ms  0.810 ms  0.799 ms
2  * * *
3  * * *
4  11.220.5.5 (11.220.5.5)  8.423 ms  7.996 ms 11.220.4.5 (11.220.4.5)  7.431 ms
5  11.220.4.54 (11.220.4.54)  7.291 ms 11.220.5.54 (11.220.5.54)  7.414 ms 11.220.4.134 (11.220.4.134)  6.420 ms
6  11.220.6.18 (11.220.6.18)  3.132 ms  2.258 ms 11.220.6.26 (11.220.6.26)  2.112 ms
7  119.38.215.154 (119.38.215.154)  3.404 ms  3.751 ms 119.38.215.130 (119.38.215.130)  3.446 ms
8  116.251.105.225 (116.251.105.225)  3.384 ms * 116.251.105.245 (116.251.105.245)  4.528 ms
9  122.224.214.77 (122.224.214.77)  3.612 ms 115.238.21.126 (115.238.21.126)  3.610 ms 115.236.101.214 (115.236.101.214)  4.166 ms
10  220.191.200.89 (220.191.200.89)  7.498 ms 220.191.200.105 (220.191.200.105)  6.180 ms 220.191.200.81 (220.191.200.81)  11.068 ms
11  202.97.68.125 (202.97.68.125)  38.807 ms 202.97.68.165 (202.97.68.165)  29.166 ms  27.333 ms
12  * * 220.181.177.222 (220.181.177.222)  40.424 ms
13  * * 218.30.112.141 (218.30.112.141)  37.761 ms
14  * * *
15  * 220.181.17.18 (220.181.17.18)  43.488 ms 220.181.182.166 (220.181.182.166)  35.481 ms
16  * * *
17  * * *
18  * * *
19  * * *
20  * * *
21  * * *
22  * * *
23  * * *
24  * * *
25  * * *
26  * * *
27  * * *
28  * * *
29  * * *
30  * * *
[root@iZbp15wvwv3b9n7p9le33kZ ~]#

本文相关的所有ECS、EIP及VPC均为临时购置,本文完成均被释放,请勿尝试访问。

优惠购买阿里云机器:https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=oifnap1a