一个计算机技术爱好者与学习者

0%

好好学Linux:Linux配置SNAT上网

1. 需求描述

有主机A,eth0的IP为内网IP:192.168.56.101,eth1为公网IP:120.77.36.222。
有主机B,eth0的IP为内网IP:192.168.56.102。
主机A可以访问外网,主机B和主机A在同一个局域网。现在我们想让主机B也可以上网,该怎么办?
最简单的方法有两个:1)SNAT;2)代理

本文中,我们学习使用配置SNAT的方式,实现局域网中的所有主机可以上网。

参考文档:

2. SNAT数据包流向

2.1. 发送数据包

B发送数据包时,A也就是NAT主机,分析数据包表头,将此数据包转到可以连接公网的IP上去。由于私有IP与公有IP不能互通,A会通过iptables的NAT table内的Postrounting链将数据包表头伪装成A的公网IP,并且将这两个不同来源的数据包对应关系写入暂存内存中,然后将数据包传送出去。此时传到互联网的这个数据包,已经表现为来自公网IP,而非来自局域网。

2.2. 接收响应包

当互联网把数据响应给B时,会首先进入NAT主机A,A分析数据包的序号,对比刚刚记录到内存中的数据,由于发现该数据包为后端主机之前传送出去的,因此在NAT Prerouting链中,会将目标IP修改成为后端主机,即B的IP,然后发现目标已经不是A的公网IP,开始通过路由分析,将数据包传送到A的局域网接口,再传送到最终目标192.168.56.102上去。

3. snat具体配置

3.1. 主机A

3.1.1. 接收数据包

允许接收局域网网卡的数据包
sudo iptables -I INPUT -i eth0 -j ACCEPT

或者
sudo iptables -P INPUT ACCEPT

3.1.2. 开启路由功能

sudo echo 1 > /proc/sys/net/ipv4/ip_forward
如果报错:-bash: /proc/sys/net/ipv4/ip_forward: Permission denied
那就切换到root用户:
sudo -i
echo 1 > /proc/sys/net/ipv4/ip_forward

要想永久有效,还要把/etc/sysctl.conf文件里边的net.ipv4.ip_forward的值改为1。

3.1.3. 伪装数据包

sudo iptables -t nat -A POSTROUTING -s 192.168.56.102 -o eth1 -j MASQUERADE

或者用SNAT直接修改IP数据包的表头来源IP
sudo iptables -t nat -A POSTROUTING -s 192.168.56.102 -o eth1 -j SNAT --to 192.168.56.101

如果需要支持整个网段:
sudo iptables -t nat -A POSTROUTING -s 192.168.56.0/24 -o eth1 -j SNAT --to 192.168.56.101

如果需要支持连续IP:
sudo iptables -t nat -A POSTROUTING -m iprange --src-range 192.168.56.102-192.168.56.104 -o eth1 -j SNAT --to 192.168.56.101

注意:

  • 亲测以上所有命令中的-o eth1可以省略,所以,在分不清哪个网卡是内网哪个网卡是外网的情况下,直接省略即可。
  • 如果想要允许所有IP,-s 192.168.56.0/24也可以省略。
  • -j SNAT --to 192.168.56.101可以换成-j SNAT --to 120.77.36.222
  • -j SNAT --to 120.77.36.222建议换成-j MASQUERADE,尤其在外网IP非固定的情况下。
  • 综上,最简单的万能SNAT命令为sudo iptables -t nat -A POSTROUTING -j MASQUERADE

3.1.4. 查看与删除

查看NAT表链规则
sudo iptables -t nat -nL --line-number

删除POSTROUTING第一条规则
sudo iptables -t nat -D POSTROUTING 1

3.2. 重启后依旧生效

1、保存规则
sudo chmod a+w -R /opt
sudo iptables-save > /opt/iptables.rules

2、手动导入规则
sudo iptables-restore < /opt/iptables.rules

3、开机自动导入规则
在ubuntu下要把一个程序加入开机启动,一般可以通过修改rc.local来完成,但ubuntu下有两个rc.local文件,分别是/etc/rc.local和/etc/init.d/rc.local。因为/etc/init.d/rc.local调用了/etc/rc.local,所以我们的开机脚本最好直接写入/etc/rc.local,写在exit 0之前即可。

sudo vim /etc/rc.local
在exit 0之前添加:

1
/sbin/iptables-restore < /opt/iptables.rules

3.3. 主机B

3.3.1. centos

如果是centos,那么配置ifcfg文件
sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0

1
2
3
4
5
6
DEVICE=eth0
BOOTPROTO=static
ONBOOT=yes
IPADDR=192.168.56.102
NETMASK=255.255.255.0
GATEWAY=192.168.56.101

然后service network restart

3.3.2. ubuntu

如果是ubuntu,那么配置interfaces文件
sudo vim /etc/network/interfaces

1
2
3
4
5
6
7
8
auto lo
iface lo inet loopback

auto em1
iface em1 inet static
address 192.168.56.102
netmask 255.255.255.0
gateway 192.168.56.101

然后sudo /etc/init.d/networking restart

总之,B主机配置的关键在于网关,网关要设置成主机A的内网IP。

请问,网关不设置成主机A的内网IP可以吗?可以,那就是另外一种稍微复杂的设置方法了。

此时,使用主机B,已经可以ping通外网的IP了。但是ping域名会提示“ping: unknown host”。

4. DNS配置

4.1. 方法一

1、编辑resolv.conf
sudo vim /etc/resolv.conf,添加nameserver的配置

1
2
nameserver 180.76.76.76
nameserver 223.6.6.6

上面的两个IP地址,分别是百度和阿里的公共DNS。

2、测试
ping www.baidu.com

3、不过,这种方法在重启之后会失效。想要永久生效,还需要编辑base文件。
sudo vim /etc/resolvconf/resolv.conf.d/base,添加:

1
2
nameserver 180.76.76.76
nameserver 223.6.6.6

4.2. 方法二

1、编辑interfaces
sudo vim /etc/network/interfaces

2、添加nameserver的配置

1
dns-nameserver 180.76.76.76 223.5.5.5

3、重启服务器
sudo reboot
实际上,重启后的dns配置会写入到resolv.conf中。

4、测试
ping www.baidu.com

5. 结语

至此,snat完美配置成功!在这个过程中,顺带复习了一下iptables,收获满满。感觉iptables和route有很大关系,但是在配置过程中没有用到route。书签中有关于route的文档,用到的时候再深入学习。

  • 本文作者: 好好学习的郝
  • 原文链接: https://www.voidking.com/dev-linux-snat/
  • 版权声明: 本文采用 BY-NC-SA 许可协议,转载请注明出处!源站会即时更新知识点并修正错误,欢迎访问~
  • 微信公众号同步更新,欢迎关注~