Linux配置SNAT上网

作者: VoidKing | 来源:发表于2018-05-08 17:39 被阅读20次

    前言

    一个局域网中,主机之间互联,其中只有一台主机可以上网,其他主机想要上网怎么办?答:使用SNAT。

    原文地址:http://www.voidking.com/2018/04/27/deve-linux-snat/

    情景模拟

    有主机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也可以上网。

    数据包流向

    发送数据包

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

    接收响应包

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

    iptables小班

    snat的配置,主要用到iptables命令,之前在《CentOS7中firewall的使用》简单提过iptables,今天再认真学习一下。

    主要参考文档:
    iptables详解
    ipatebles详解(1):iptales概念
    iptables命令
    25个iptables常用示例
    Linux防火墙iptables学习笔记(三)iptables命令详解和举例

    历史

    防火墙,其实说白了讲,就是用于实现Linux下访问控制的功能的,它分为硬件的或者软件的防火墙两种。无论是在哪个网络中,防火墙工作的地方一定是在网络的边缘。而我们的任务就是需要去定义到底防火墙如何工作,这就是防火墙的策略,规则,以达到让它对出入网络的IP、数据进行检测。

    iptables的前身叫ipfirewall (内核1.x时代),这是一个作者从freeBSD上移植过来的,能够工作在内核当中的,对数据包进行检测的一款简易访问控制工具。但是ipfirewall工作功能极其有限(它需要将所有的规则都放进内核当中,这样规则才能够运行起来,而放进内核,这个做法一般是极其困难的)。当内核发展到2.x系列的时候,软件更名为ipchains,它可以定义多条规则,将他们串起来,共同发挥作用,而现在,它叫做iptables,可以将规则组成一个列表,实现绝对详细的访问控制功能

    原理

    五个关卡

    iptables工作在用户空间中,是定义规则的工具,本身并不算是防火墙。它定义的规则,可以让内核空间中的netfilter来读取,并且实现让防火墙工作。netfilter的架构就是在整个网络流程的若干位置设置一些关卡(HOOK),而在每个关卡上登记了一些规则,所以这些关卡的术语规则链。

    在内核空间中,netfilter选择了5个位置,来作为控制的关卡,专业点叫做规则链。朱双印大神的博客中给出了直观的图像:


    image

    根据上图,我们能够想象出某些常用场景中,报文的流向:
    到本机某进程的报文:PREROUTING --> INPUT
    由本机转发的报文:PREROUTING --> FORWARD --> POSTROUTING
    由本机的某进程发出报文(通常为响应报文):OUTPUT --> POSTROUTING

    五个规则链的作用如下:
    INPUT链:处理输入数据包。
    OUTPUT链:处理输出数据包。
    PORWARD链:处理转发数据包。
    PREROUTING链:用于目标地址转换(DNAT)。
    POSTOUTING链:用于源地址转换(SNAT)。

    表的概念

    我们再想想另外一个问题,我们对每个"链"上都放置了一串规则,但是这些规则有些很相似,比如,A类规则都是对IP或者端口的过滤,B类规则是修改报文,那么这个时候,我们是不是能把实现相同功能的规则放在一起呢,必须能的。

    我们把具有相同功能的规则的集合叫做"表",所以说,不同功能的规则,我们可以放置在不同的表中进行管理,而iptables已经为我们定义了4种表,每种表对应了不同的功能,而我们定义的规则也都逃脱不了这4种功能的范围,所以,学习iptables之前,我们必须先搞明白每种表的作用。
    iptables为我们提供了如下规则的分类,或者说,iptables为我们提供了如下"表":

    • filter表:负责过滤功能,防火墙;内核模块:iptables_filter
    • nat表:network address translation,网络地址转换功能;内核模块:iptable_nat
    • mangle表:拆解报文,做出修改,并重新封装的功能;iptable_mangle
    • raw表:关闭nat表上启用的连接追踪机制;iptable_raw

    也就是说,我们自定义的所有规则,都是这四种分类中的规则,或者说,所有规则都存在于这4张"表"中。

    数据包流向

    可以将数据包通过防火墙的流程总结为下图:


    image

    我们在写iptables规则的时候,要时刻牢记这张路由次序图,灵活配置规则。

    规则

    规则:根据指定的匹配条件来尝试匹配每个流经此处的报文,一旦匹配成功,则由规则后面指定的处理动作进行处理。规则由匹配条件和处理动作组成。

    匹配条件分为基本匹配条件与扩展匹配条件:
    基本匹配条件包括源地址Source IP和目标地址 Destination IP。

    扩展匹配条件包括源端口Source Port,目标端口Destination Port等等。

    动作也可以分为基本动作和扩展动作,此处列出一些常用动作:
    ACCEPT:允许数据包通过。
    DROP:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应。
    REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。
    SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。
    MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。
    DNAT:目标地址转换,解决外网用户访问内网的问题。
    REDIRECT:在本机做端口映射。
    LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配。

    命令详解

    命令格式:
    iptables [选项] [参数]

    选项包括:

    -t:指定要操纵的表;
    -A:向规则链中添加条目;
    -D:从规则链中删除条目;
    -I:向规则链中插入条目;
    -R:替换规则链中的条目;
    -L:显示规则链中已有的条目;
    -F:清楚规则链中已有的条目;
    -Z:清空规则链中的数据包计算器和字节计数器;
    -N:创建新的用户自定义规则链;
    -P:定义规则链中的默认目标;
    -h:显示帮助信息;
    -p:指定要匹配的数据包协议类型;
    -s:指定要匹配的数据包源ip地址;
    -d:指定要匹配的数据包目标ip地址;
    -j:指定要跳转的目标;
    -i:指定数据包进入本机的网络接口(网卡);
    -o:指定数据包离开本机的网络接口(网卡);
    --sport:匹配来源端口号;
    --dport:匹配目标端口号。
    

    命令选项输入顺序:
    iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作

    实例

    1、清除已有iptables规则

    iptables -F
    iptables -X
    iptables -Z
    

    2、开放指定的端口

    iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT               #允许本地回环接口(即允许本机访问本机)
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT    #允许已建立的或相关连的通行
    iptables -A OUTPUT -j ACCEPT         #允许所有本机向外的访问
    iptables -A INPUT -p tcp --dport 22 -j ACCEPT    #允许访问22端口
    iptables -A INPUT -p tcp --dport 80 -j ACCEPT    #允许访问80端口
    iptables -A INPUT -p tcp --dport 21 -j ACCEPT    #允许ftp服务的21端口
    iptables -A INPUT -p tcp --dport 20 -j ACCEPT    #允许FTP服务的20端口
    iptables -A INPUT -j REJECT       #禁止其他未允许的规则访问
    iptables -A FORWARD -j REJECT     #禁止其他未允许的规则访问
    

    3、屏蔽IP

    iptables -I INPUT -s 123.45.6.7 -j DROP       #屏蔽单个IP的命令
    iptables -I INPUT -s 123.0.0.0/8 -j DROP      #封整个段即从123.0.0.1到123.255.255.254的命令
    iptables -I INPUT -s 124.45.0.0/16 -j DROP    #封IP段即从123.45.0.1到123.45.255.254的命令
    iptables -I INPUT -s 123.45.6.0/24 -j DROP    #封IP段即从123.45.6.1到123.45.6.254的命令是
    

    4、查看已添加的iptables规则
    iptables -L -n -v

    5、删除已添加的iptables规则
    将所有iptables以序号标记显示,执行:
    iptables -L -n --line-numbers

    比如要删除INPUT里序号为8的规则,执行:
    iptables -D INPUT 8

    snat具体配置

    主机A

    接收数据包

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

    或者
    sudo iptables -P INPUT ACCEPT

    开启路由功能

    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。

    伪装数据包

    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

    查看与删除

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

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

    重启后依旧生效

    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之前添加:

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

    主机B

    centos

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

    DEVICE=eth0
    BOOTPROTO=static
    ONBOOT=yes
    IPADDR=192.168.56.102
    NETMASK=255.255.255.0
    GATEWAY=192.168.56.101
    

    然后service network restart

    ubuntu

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

    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”。

    DNS配置

    方法一

    1、编辑resolv.conf
    sudo vim /etc/resolv.conf

    2、添加nameserver的配置

    nameserver 180.76.76.76
    nameserver 223.6.6.6
    

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

    3、测试
    ping www.baidu.com

    方法二

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

    2、添加nameserver的配置

    dns-nameserver 180.76.76.76 223.5.5.5
    

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

    4、测试
    ping www.baidu.com

    结语

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

    书签

    Linux下配置SNAT上网

    利用iptables的SNAT功能实现局域网共享上网

    linux 路由表设置之 route 指令详解

    ubuntu配置静态路由及重启生效

    相关文章

      网友评论

        本文标题:Linux配置SNAT上网

        本文链接:https://www.haomeiwen.com/subject/mxuwrftx.html