一、防火墙、iptables和netfilter简介

防火墙(Firewall)是由软件和硬件设备组合而成的一种隔离技术,它工作于网络或主机的边缘(通信报文的进出口),对于进出本网络或主机的数据包根据事先定义的检测规则进行匹配检测,允许或是限制传输的数据包通过。


netfilter:是内核的一部分,由一些数据包过滤表组成,这些表包含内核用来控制数据包过滤处理的规则集。


iptables:是用来插入、修改和删除数据包过滤表中的规则的管理工具。


二、iptables详解

报文流向:

    流入本机:prerouting --> input ==> 用户空间进程; 

    流出本机:用户空间进程==> output --> postrouting; 
    转发:prerouting --> forward --> postrouting;


内置链:共有5个,每个对应于一个勾子函数; 

        PREROUTING 
        INPUT 
        FORWARD 
        OUTPUT 
        POSTROUTING


自定义链:用于对内置链进行补充或扩展,可实现更灵活的规则组织管理机制;需要使用时需要自己手动关联在勾子函数上。


表(table)的功能:

wKiom1ckqi3QfTL7AAAkWVLY8YI459.png


表和链的对应关系:

wKioL1ckq1XAkCIhAAAdiV7jSAs599.png


同一链上的不同的表的规则的应用优先级(高-->低):

                wKioL1ckq3TQhYjIAAAer96ExQk370.png

路由功能发生的时刻:

    (1)报文进入本机后:

        判断目标主机是否为本机? 
        是:INPUT 
        否:FORWARD

    (2)报文离开本机之前:

        判断经由哪一个接口送往下一跳?


规则:

    组成部分:根据规则的匹配条件尝试匹配报文,对匹配成功的报文根据规则定义的处理动作做出处理;

        (1)匹配条件:

            基本匹配 
            扩展匹配

        (2)处理动作(target):

            基本处理动作 
            扩展处理动作 
            自定义处理动作


添加规则时的考量点:

    (1)要实现何种功能:判断添加规则至哪个表上; 

    (2)报文流经的位置:判断添加规则至哪个链上;


iptables命令用法详解:

    命令格式:iptables [-t table] SUBCOMMAND chain [matches...] [target]

        iptables [-t table] {-A|-C|-D} chain rule-specification 
        iptables [-t table] -I chain [rulenum] rule-specification 
        iptables [-t table] -R chain rulenum rule-specification 
        iptables [-t table] -D chain rulenum 
        iptables [-t table] -S [chain [rulenum]] 
        iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...] 
        iptables [-t table] -N chain 
        iptables [-t table] -X [chain] 
        iptables [-t table] -P chain target 
        iptables [-t table] -E old-chain-name new-chain-name 
        rule-specification = [matches...] [target] 
        match = -m matchname [per-match-options] 
        target = -j targetname [per-target-options]


    -t table:可省略,省略后默认为filter

        raw, mangle, nat, filter


    SUBCOMMAND:

        链管理:

            -N: new,新增一条自定义链; 
            例:

            ~]# iptables -N newchain

            -P:policy,设置链的默认策略(共有3种策略); 

                ACCEPT:接受 
                DROP:丢弃 
                REJECT:拒绝 
            例:

            ~]# iptables -P FORWARD DROP

            -E:rename,重命名自定义的未被引用(引用计数为0)的链; 

            例:

            ~]# iptables -E newchain testchain

            -X:delete,删除自定义的空链; 

            例:

            ~]# iptables -X testchain


        规则管理:

            -A:append,追加,默认为最后一个; 
            -I:insert,插入,默认为第一个; 
            -D:delete,删除 
                (1) rule specification 
                (2) rule number 
            -R:replace,替换 
            -F:flush,清洗 
            -S:selected,以iptables-save命令的格式显示链上的规则; 
            -Z:zero,置0; 
        注:iptables的每条规则都有两个计数器:由本规则匹配到的所有的packets;由本规则匹配到的所有的bytes。


        查看:

            -L: list,列出规则 
            -n:numeric,以数字格式显示地址和端口; 
            -v:verbose,详细信息;-vv, -vvv 
            -x:exactly,显示计数器的精确值而非单位换算后的结果; 
            --line-numbers:显示链上的规则的编号; 
            组合:-nvL


    匹配条件:

        基本匹配:netfilter自带的匹配机制

            [!] -s, --source address[/mask][,...]:原地址匹配 

            [!] -d, --destination address[/mask][,...]:目标地址匹配 
            [!] -i, --in-interface name:限制报文流入的接口,只能用于PREROUTING,INPUT及FORWARD; 
            [!] -o, --out-interface name:限制报文流出的接口,只能用于OUTPUT,FORWARD及POSTROUTING;


        扩展匹配:经由扩展模块引入的匹配机制,-m matchname

            隐式扩展:可以不用使用-m选项专门加载相应模块;前提是要使用-p选项可匹配何种协议; 
            显式扩展:必须由-m选项专门加载相应模块;


            隐式扩展:

                [!] -p, --protocol PROTOCOL PROTOCOL: 
                协议:tcp, udp, icmp, icmpv6, esp, ah, sctp, mh or "all"

                    

                tcp: 隐含指明了“-m tcp”,有专用选项:

                [!] --source-port,--sport port[:port]:匹配报文中的tcp首部的源端口;可以是端口范围;

                [!] --destination-port,--dport port[:port]:匹配报文中的tcp首部的目标端口;可以是端口范围; 

                例:允许对IP为172.18.0.13的主机进行web访问

                ~]# iptables -A INPUT -d 172.18.0.13 -p tcp --dport 80 -j ACCEPT
                ~]# iptables -A OUTPUT -s 172.18.0.13 -p tcp --sport 80 -j ACCEPT

                [!] --tcp-flags mask comp:检查报文中mask指明的tcp标志位,而要这些标志位comp中必须为1; 

                --tcp-flags syn,fin,ack,rst syn 
                --tcp-flags syn,fin,ack,rst ack,fin;四次挥手的第一次 
                [!] --syn: 
                --syn相当于“--tcp-flags syn,fin,ack,rst syn”;tcp三次握手的第一次;


                udp:隐含指明了“-m udp”,有专用选项:

                [!] --source-port,--sport port[:port]:匹配报文中的udp首部的源端口;可以是端口范围; 
                [!] --destination-port,--dport port[:port]:匹配报文中的udp首部的目标端口;可以是端口范围; 
                例:允许IP地址为172.18.0.13的主机对其它主机进行tftp访问

                ~]# iptables -A OUTPUT -s 172.18.0.13 -p udp -sport 69 -j ACCEPT
                ~]# iptables -A INPUT -d 172.18.0.13 -pa udp -dport 69 -j ACCEPT


                icmp:隐含指明了“-m icmp”,有专用选项:

                [!] --icmp-type {type[/code]|typename} 
                type/code: 
                    0/0:echo reply,ping应答 
                    8/0:echo request,ping请求 
                例:允许IP为172.18.0.13的主机对其它主机进行ping操作

                ~]# iptables -A OUTPUT -s 172.18.0.13 -p icmp --icmp-type 8 -j ACCEPT
                ~]# iptables -A INPUT -d 172.18.0.13 -p icmp --icmp-type 0 -j ACCEPT

                    允许IP为172.18.0.13的主机被其它主机进行ping操作

                ~]# iptables -A INPUT -d 172.18.0.13 -p icmp --icmp-type 8 -j ACCEPT
                ~]# iptables -A OUTPUT -s 172.18.0.13 -p icmp --icmp-type 0 -j ACCEPT


            显式扩展:

                multiport:多端口匹配

                注:以离散方式定义多端口匹配,最多可以指定15个端口;

                    [!] --source-ports,--sports port[,port|,port:port]... 
                    [!] --destination-ports,--dports port[,port|,port:port]... 
                    [!] --ports port[,port|,port:port]... 
                    例:允许IP为172.18.0.13的主机可以被其它主机web访问和ssh连接

                    ~]# iptables -I INPUT -s 0/0 -d 172.18.0.13 -p tcp  -m multiport --dports 22,80 -j ACCEPT
                    ~]# iptables -I OUTPUT -d 0/0 -s 172.18.0.13 -p tcp  -m multiport --sports 22,80 -j ACCEP


                iprange:连续ip地址匹配

                注:指明一段连续的ip地址范围做为源地址或目标地址匹配;

                    [!] --src-range from[-to]:源地址范围 
                    [!] --dst-range from[-to]:目标地址范围 
                    例:允许IP为172.18.0.13的主机可以被IP地址在172.18.0.0-172.18.255.255范围内的主机进行web访问

                    ~]#iptables -I INPUT -d 172.18.0.13 -p tcp --dport 80 -m iprange --src-range 172.18.0.0-172.18.255.255 -j ACCEPT
                    ~]#iptables -I OUTPUT -s 172.18.0.13 -p tcp --sport 80 -m iprange --dst-range 172.18.0.0-172.18.255.255 -j ACCEP


                string:对报文中的应用层数据做字符串匹配检测;

                    --algo {bm|kmp}: 
                    (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris)两种算法在性能上无太大差别 
                    [!] --string pattern:给定要检查的字符串模式; 
                    [!] --hex-string pattern:给定要检查的字符串模式(十六进制); 
                    例:对IP为172.18.0.13的主机进行web访问时,如果返回内容中包含"hello"字符串,则拒绝访问。

                    ~]# iptables -I OUTPUT -s 172.18.0.13 -p tcp --sport 80 -m string --algo bm --string "hello" -j REJECT


                time:根据收到报文的时间/日期与指定的时间/日期范围进行匹配;

                    --datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]:起始日期时间; 
                    --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]:结束日期时间;

                    --timestart hh:mm[:ss]:起始时间; 
                    --timestop hh:mm[:ss]:结束时间;

                    [!] --monthdays day[,day...]:匹配一个月中的哪些天; 
                    [!] --weekdays day[,day...]:匹配一个周中的哪些天; 
                    例:允许IP地址在172.18.100.1-172.18.100.100范围内的主机,在每周的星期一到星期五的9点到16点的时间段内对IP为172.18.0.13的主机进行web访问。

                    ~]# iptables -R INPUT 4 -d 172.18.0.13 -p tcp --dport 80 -m iprange --src-range 172.18.100.1-172.18.100.100 -m time --timestart 09:00:00 --timestop 16:00:00 --weekdays 1,2,3,4,5 -j ACCEPT


                connlimit:根据每客户端主机做并发连接数限制,即每客户端最多可同时发起的连接数量;

                    --connlimit-upto n:连接数量小于等于n则匹配; 

                    --connlimit-above n:连接数量大于n则匹配; 
                    例:每个客户端主机对IP地址为172.18.0.13的主机进行web访问时,并发连接数最多为2个。

                    ~]# iptables -A INPUT -d 172.18.0.13 -p tcp --dport 80 -m connlimit --connlimit-upto 2 -j ACCEPT


                limit:基于令牌桶算法对报文的速率做匹配;

                    --limit rate[/second|/minute|/hour|/day] 
                    --limit-burst number 
                    例:每个客户端主机对IP地址为172.18.0.13的主机进行ping操作时,前3次请求速度不受限制,第4次请求开始以每分钟20次请求的速度发起请求。

                    ~]# iptables -R INPUT 3 -d 172.18.0.13 -p icmp --icmp-type 8 -m limit --limit 20/minute --limit-burst 3 -j ACCEPT


                state:是conntrack的子集,用于对报文的状态做连接追踪;

                    [!] --state state

                    INVALID:无法识别的连接; 
                    ESTABLISHED:连接追踪模板当中存在记录的连接; 
                    NEW:连接追踪模板当中不存的连接请求; 
                    RELATED:相关联的连接; 
                    UNTRACKED:未追踪的连接;


                    已经追踪到的并记录下来的连接: 
                    /proc/net/nf_conntrack


                    连接追踪功能所能够记录的最大连接数量(可调整): 
                    /proc/sys/net/nf_conntrack_max 

                    例:调整最大连接数可用2种如下方式

                    ~]#sysctl -w net.nf_conntrack_max=200000
                    ~]#echo  200000 > /proc/sys/net/nf_conntrack_max


                    总结:conntrack所能够追踪的连接数量的最大值取决于/proc/sys/net/nf_conntrack_max的值的设定;已经追踪到的并记录下来的连接位于/proc/net/nf_conntrack文件中,超时的连接将会被删除;当模板满载时,后续的新连接有可能会超时;解决方法: 
                        (1) 加大nf_conntrack_max的值; 
                        (2) 缩小nf_conntrack条目的超时时限; 
                        不同协议的连接追踪超时时限文件所在位置:/proc/sys/net/netfilter/


                    例:如何放行IP地址为172.18.0.13主机的被动模式的ftp服务? 
                        (1) 内核加载nf_conntrack_ftp模块; 
                            modprobe nf_conntrack_ftp 
                        (2) 放行命令连接

                        ~]#iptables  -A INPUT  -d  172.18.0.13 -p tcp --dport 21  -m state --state NEW,ESTABLISHED -j  ACCEPT
                        ~]#iptables  -A  OUTPUT  -s  172.18.0.13  -p tcp --sport  21  -m state --state  ESTABLISHED -j ACCEPT

                        (3) 放行数据连接

                        ~]#iptables  -A INPUT  -d  172.18.0.13 -p tcp  -m state --state RELATED,ESTABLISHED -j  ACCEPT
                        ~]#iptables  -A  OUTPUT  -s  172.18.0.13  -p tcp  -m state --state  ESTABLISHED -j ACCEPT


    规则的检查次序:规则在链接上的次序即为其检查时的生效次序;因此,其优化使用有一定法则;

        (1)同类规则(访问同一应用),匹配范围小的放前面;用于特殊处理; 

        (2)不同类的规则(访问不同应用),匹配频率高的放前面; 
        (3)应该将那些可由一条规则描述的多个规则合并为一; 
        (4)设置默认策略;


    规则的有效期限:

        iptables命令添加的规则:手动删除之前,其生效期限为kernel的生命周期。

    

        保存规则:

            CentOS 6:共有2种保存方法

            ~]# service  iptables  save 
            ~]# iptables-save  > /etc/sysconfig/iptables

            也可以保存在其他位置,但系统启动时不会自动加载 

            ~]# iptables-save > /PATH/TO/SOME_RULE_FILE


            CentOS 7:

            ~]# iptables-save  >  /PATH/TO/SOME_RULE_FILE


        重载预存的规则:

        ~]# iptables-restore  <  /PATH/FROM/SOME_RULE_FILE

            CentOS 6也可以使用命令

            ~]#service  iptables  restart

                系统会自动从/etc/sysconfig/iptables文件中重载规则;


        自动生效规则文件中的规则:

            (1) 把iptables命令放在脚本文件中,让脚本文件开机自动运行; 
                /etc/rc.d/rc.local 
                /usr/bin/iptables.sh

            (2) 用规则文件保存规则,开机自动重载命令; 
                /etc/rc.d/rc.local 

            ~]#iptables-restore < /PATH/FROM/SOME_RULE_FILE


    处理动作:

        -j targetname [per-target-options]

wKiom1ckxjighi1FAAA4d_yE6-g819.png


        LOG:

            --log-level level:指定日志级别 
            emerg,alert, crit, error, warning, notice, info debug 
            注:默认的日志级别为level 4,当指定级别后,符合该级别和比此级别高的日志都会被记录。


            --log-prefix prefix:对日志加前缀,用来说明对应的日志信息是由谁产生的,最大长度为29个字符。

            例:对IP地址为172.18.0.13的主机进行web和ssh访问时做日志记录。

            ~]# iptables -I INPUT -d 172.18.0.13 -p tcp -m multiport --dports 80,22 -m state --state NEW,ESTABLISHED -j LOG --log-prefix "(web or ssh )"

        注:在使用LOG时,要把规则放在使用了DROP和REJECT的规则之前。



        RETURN:

            返回调用者;

        注:自定义链被调用时,默认规则匹配完最后一条后会返回调用者。


        REDIRECT:

            当普通用户对于某些端口没有使用权限时,管理员可以通过REDIRECT来解决此问题。

            --to-ports port[-port]

            例:对IP地址为172.18.0.13的主机进行web访问时以8080端口监听。

            ~]# iptables -t nat -A PREROUTING -d 172.18.0.13 -p tcp --dport 80 -j REDIRECT --to-ports 8080

            注:只能用于nat表的PREROUTING链和OUTPUT链,只有在入栈报文请求刚刚到达时才能用。


        NAT:Network Address Translation(网络地址转换)

            SNAT:

                source NAT,修改IP报文中的源IP地址,只能作用于nat表的POSTROUTING链和INPUT链(CentOS 7才可使用在INPUT链)。

                让本地网络中的主机可使用统一地址与外部主机通信,从而实现地址伪装。 
                请求:由内网主机发起,修改源IP,如果修改则由管理员定义; 
                响应:修改目标IP,由nat自动根据会话表中追踪机制实现相应修改;


                --to-source [ipaddr[-ipaddr]] 
                例:将本地网络中IP地址为10.0.1.22的主机的网络地址随机转换为172.18.0.13-172.18.0.16中的一个地址,以此地址与外部主机通信。

                ~]#iptables -t nat -A POSTROUTING -s 10.0.1.22 -j SNAT --to-source 172.18.0.13-172.18.0.16


            DNAT:

                destination NAT,修改IP报文中的目标IP地址,只能作用于nat表的RPEROUTING链和OUTPUT链。

                让本地网络中服务器使用统一的地址向外提供服务(发布服务),但隐藏了自己的真实地址。 
                请求:由外网主机发起,修改其目标地址,由管理员定义; 
                响应:修改源地址,但由nat自动根据会话表中的追踪机制实现对应修改;

                --to-destination [ipaddr[-ipaddr]][:port[-port]] 
                例:将本地网络中IP地址为10.0.1.22的主机的网络地址转换为172.18.0.13,以此dizhi。

                ~]# iptables -t nat -A PREROUTING -d 172.18.0.13 -p tcp --dport 80 -j DNAT --to-destination 10.0.1.22


            MASQUERADE:

                自动获取外网地址,将源地址转换为外网地址,只能作用于nat表的POSTROUTING。由于使用时会额外消耗很多资源,建议外网地址为动态获取时使用,外网地址为静态地址时,建议使用SNAT.

                例:将本地网络中IP地址为10.0.1.22的主机的网络地址转换为动态外网地址,以此地址与外部主机通信。

                ~]# iptables -t nat -A POSTROUTING -s 10.0.1.22 -j MASQUERADE