1.iptables介绍


iptables是一个配置linux内核防火墙的命令行工具,是netfilter项目的一部分。iptables也经常代指内核级防火墙。iptables用于ipv4,ip6tables用于ipv6。nfttables已经包含在linux kernel 3.13中,以后回取代iptables成为主要的linux防火墙工具。


2.iptables基本概念


iptables是位于用户空间的命令行程序,用于生成规则送往内核中的netfilter之上。netfilter是位于内核中tcp/ip协议栈上的一个framework,有5个钩子函数。

在内核空间中选择了5个位置来检查流经的数据包:

    (1)内核空间中:从一个网络接口进来,到另一个网络接口去的

    (2)数据包从内核流入用户空间的

    (3)数据包从用户空间流出的

    (4)进入/离开本机的外网接口

    (5)进入/离开本机的内网接口

     这5个位置被称为5个钩子函数(hook functions),对应iptables的5个规则链


iptables 5个内置的规则链

    (1)PREROUTING(路由前):对数据包做路由选择前应用此链中的规则。所有数据包进来的时候都先

         由这条链处理。

    (2)INPUT(数据包流入口):进来的数据包应用此规则链中的策略

    (3)FORWARD(转发):转发数据包时应用此规则链中的策略

    (4)OUTPUT(数据包出口):外出的数据包应用此规则链中的策略

    (5)POSTROUTING(路由后):对数据包作路由选择后应用此规则链中的规则。所有数据包出来的时

         候都要经由这个链处理。

     任何一个数据包,只要经过本机,必将经过这5个链中的其中一个链。

     

     自定义链:

         除了内置的链外,我们还可以自定义链,自定义链用于对内置链进行补充或扩展,可实现更灵

         活的规则组织管理机制。 

    

iptables的表(tables)

    (1)filter:用于存放所有与防火墙相关操作的默认表

    (2)net:用于网络地址换,修改报文的源地址或者目标地址,甚至是端口

    (3)mangle:用于对特定的数据包修改。拆解报文,做出修改,并重新封装报文

    (4)raw:用于配置数据包,raw中的数据包不会被系统跟踪

     大部分情况下仅需要使用filter和nat。

     优先级次序(由高到低):

        raw-->mangle-->nat-->filter


3.iptables 数据包过滤匹配流程


wKiom1eUIIOzT6C2AADxj3RvrUU861.png-wh_50

 功能(表)<-->钩子(链):

 同一条链上的不同的表的规则的应用优先级(从高到低)

 raw:PREROUTING,OUTPUT

 mangel:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING

 nat:PREROUTING,INPUT(之前没有),OUTPUT,POSTROUTING

 filter:INPUT,FORWARD,OUTPUT

 

 报文流向:   

    流入:到达本机某进程的报文:PREROUTING --> INPUT ==> 用户空间进程;

    流出:本机某进程发出的报文:用户空间进程==> OUTPUT --> POSTROUTING; 

    转发:由本机转发的报文:PREROUTING --> FORWARD --> POSTROUTING;

 

 路由功能发生的时刻

    报文进入本机后:

        判断目标主机是否为本机?

            是:INPUT

            否:FORWARD

    报文离开本机之前:

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


 规则的组成部分:

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

        匹配条件:

            基本匹配条件:简单检查ip,tcp,udp等报文的某属性进行匹配的机制

            扩展匹配条件:需要借助于扩展模块进行的匹配条件指定,即为扩展匹配

                隐式扩展:

                显示扩展

        处理动作(target):
            基本处理动作 ACCEPT,DROP,REJECT

            扩展处理动作

            自定义处理动作


4.iptables基本使用


4.1 iptables基本语法

    iptables命令格式:iptables [-t table] COMMAND chain [-m matchname [per-match-options]]

    [-j targetname [per- target-options]]

    -t tables:默认为[filter],raw,mangle,raw

COMMAND:

    链管理:      

-N
new,新增一条自定义链
-Xdrop,删除自定义的引用计数为0的空链
-P

policy,设置链的默认策略

ACCEPT:接受

DROP:丢弃

REJECT:拒绝

-Fflush,清空指定的链
-E
rename,重命名自定义的未被引用(引用计数为0)的链

    

    规则管理:

-A
append,追加,在指定链的尾部追加一条规则,默认为最后一个
-Iinsert,插入,在指定的位置(省略位置时表示链首)默认为第一个
-D

delete,删除,删除指定的规则

(1)rule specification

(2)rule number

-Rreplace,替换,将指定的规则替换为新规则;不能仅修改规则中的部分,而是整条规则完全替换
-Z

zero,置0

iptables的每条规则都有2个计数器

(1)由本规则匹配到的所有packets

(2)由本规则匹配到的所有的bytes

-S
selected,以iptables-save命令的格式显示链上的规则

        

    查看:    

-L

list,列出表中的链上的规则

-n:number,以数字格式显示地址和端口

-v:verbose,显示详细格式

-x:exactly,显示计数器的精确值而非单位换算后的结果

--line-numbers:显示链中的规则的编号


组合:-vnL

    chain:

        (1)内键链

        (2)自定义链


4.2 匹配条件说明

多重条件:逻辑关系为“与”

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

[!] -s,--source address[/mash][,...]源地址匹配
[!] -d,--destination address[/mask][,...]目标地址匹配
[!] -p,--protocol protocolprotocol:{tcp|udp|icmp}
[!] -i,--in-interface name限制报文流入的接口,只能用于PREROUTING,INPUT及FORWARD
[!] -o,--out-interface name限制报文流出的接口,只能用于FORWARD,OUTPUT,及POSTROUTING

   示例:

iptables -t filter -A input -s 172.16.0.0/16 -d 172.16.100.67 -j ACCEPT
iptables -t filter -A output -s 172.16.100.67 -d 172.16.0.0/16 -j ACCEPT
iptables -vnL
iptablrs -vnl --line-numbers
iptables -R INPUT 1 -s 172.16.100.68 -d 172.16.100.67 -j DROP
iptables -A OUTPUT -s 172.16.100.67 -d 172.16.0.0/16 -o eno16777736 -j ACCEPT
iptables -F (在清空规则之前要确保policy为ACCEPT)

 

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

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

显示扩展:必须由-m选项专门加载相应模块

    

隐式扩展

    -p {tcp|udp|icmp}:限制协议

        -p tcp           

            [!] --source-port,--sport port[:port]:匹配报文中传输层的源端口;

            [!] --destination-port,--dport port[:port]:匹配报文中传输层的目标端口;

            [!] --tcp-flags mask comp: 匹配tcp报文中的状态

                可以设置的状态值有: SYN,ACK,FIN,RST,URG,PSH

                ALL表示所有的状态,NONE表示所有没有设定  

                mask:要检查的标志位列表,以逗号分隔

comp:必须为1的标志位,余下的出现在mask列表中的标志位则必须为0;

                如:--tcp-flags ALL ALL 检查所有状态都为1

                    --tcp-flags ALL NONE 检查所有状态都为0

                    --tcp-flags SYN,ACK,FIN,RST  SYN 表示第一次握手

                

            [!] --syn:相当于--tcp-flags  SYN,ACK,FIN,RST  SYN 

          

        -p dup:          

            [!] --source-port,--sport port[:port]:匹配报文中传输层的源端口;

    [!] --destination-port,--dport port[:port]:匹配报文中传输层的目标端口;


        -p icmp

            [!] --icmp-type {type[/code]|typename}

8:echo-request

0:echo-reply


 示例:      

iptables -A INPUT  -s 172.16.0.0/16 -d 172.16.100.67 -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT  -s 172.16.0.0/16 -s 172.16.100.67 -p tcp --sport 22 -j ACCEPT

        允许自己ping别人,但别人不能ping自己

iptables -A OUTPUT -s 172.16.100.67  -p icmp --icmp-type 8 -j ACCEPT
iptables -A INPUT -d 172.16.100.67 -p icmp --icmp-type 0 -j ACCEPT


显示扩展:

    获取帮助:

    centos 7:man iptables-extensions

    centos 6:man iptables

(1) multiport:以离散或者连续的方式定义多端口匹配条件

    [!] --source-ports,--sports port[,port|,port:port]...:指定多个源端口;

    [!] --destination-ports,--dports port[,port|,port:port]...:指定多个目标端口;

    [!] --ports port[,port|,port:port]...:指定多个端口;

    示例:    

iptables -A INPUT -d 172.16.100.67 -p tcp -m multiport --dports 22:23,80 -j ACCEPT
iptables -A OUTPUT -s 172.16.100.67 -p tcp -m multiport --sports 22:23,80 -j ACCEPT
设置默认规则:(不是我放行的都DROP)
iptables -A INPUT -d 172.16.100.67 -j DROP
iptables -A OUTPUT -s 172.16.100.67 -j DROP

(2) iprange扩展:以连续的IP地址范围指明连续的多地址匹配条件

    [!] --src-range from[-to]:源IP地址;

    [!] --dst-range from[-to]:目标IP地址;

    示例:

iptables -I INPUT -2 -d 172.16.100.67 -p tcp --dport 3306 -m iprange --src-range 172.16.100.61-172.16.100.70 -j ACCEPT
iptables -I OUTPUT -2 -s 172.16.100.67 -p tcp --sport 3306 -m iprange --dst-range 172.16.100.61-172.16.100.70 -j ACCEPT


(3) string扩展:对报文中应用层数据做字符串匹配检测

    [!] --string "pattern":要检测字符串模式;

    [!] --hex-string "pattern":要检测的字符串模式,16进制编码;

    --alog {bm|kmp}

    示例:

    web服务器172.16.100.67,测试页为:

    cat test.html

    <h1>admin area</h1>

    现在该页面在响应时,只响应给172.16.100.61-172.16.100.70的客户端,怎么实现?

iptables -I OUTPUT -s 172.16.100.67 -p tcp --sport 80 -m iprange ! --dst-range 172.16.100.61-172.16.100.70 -m string --string "admin" --algo kmp -j REJECT

(4) 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...]:匹配一个周中的哪些天

    示例:

~]# iptables -I INPUT -d 172.16.100.67 -p tcp --dport 23 -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays Tue,Thu,Sat -j ACCEPT
~]# iptables -R INPUT 4 -d 172.18.100.6 -p tcp --dport 23 -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


(5) connlimit 扩展:根据没客户端IP做并发连接数匹配

    --connlimit-upto n:连接数数量小于等于n,此时应该允许;

    --connlimit-above n:连接数数量大于n,此时应该拒绝;

    示例:

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

 

(6) limit扩展:基于令牌桶算法对收发报文的速率进行匹配

    --limit rate[/second|/minute|/hour|/day]:平均速率

    --limit-burst number:峰值速率

    示例:

 iptables -I INPUT -d 172.16.100.67 -p icmp --icmp-type 8 -m limit --limit-burst 5 --limit 20/minute -j ACCEPT

    

(7) state 扩展:状态检测,指明连接状态

    状态检测是靠连接追踪机制实现的(state conntrack)

    连接追踪原理:在内核的内存空间中有一段位置用来存储之前访问的用户请求,这段位置就是

    /proc/net/nf_conntrack(连接追踪模版)

    说明:一旦启用连接追踪功能,就要消耗大量的内存记录连接

          一旦有更大的连接数量进来,超出记录的连接数量,所有连接就会被断掉,超时。


    nf_conntrack内核模块:

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

        连接追踪功能所能记录的的最大连接数量定义在:/proc/sys/net/nf_conntrack_max

            此值可自行定义,建议必要时调整到足够大:

                sysctl -w net.nf_conntrack_max=300000,系统默认为65535

        不同协议的连接追踪时长:/proc/sys/net/netfilter/

      

    [!] --state STATE

    STATE:   

        INVALID:无法识别的状态; 

ESTABLISHED:已建立的连接;

NEW:新连接; 

RELATED:相关联的连接;

UNTRACKED:未追踪的连接;


    示例:

iptables -A INPUT -d 172.16.100.67 -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -s 172.16.100.67 -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -d 172.16.100.67 -p tcp -m multiport --dports 22,23,80,3306 -m state --state NEW -j ACCEPT
iptables -A INPUT -d 172.16.100.67 -j DROP
iptables -A OUTPUT -s 172.16.100.76 -j DROP

    上面规则没有允许icmp协议,现在让外部能ping进来怎么实现?

iptables -I INPUT 3 -d 172.16.100.67 -p icmp --icmp-type 8 -m state --state NEW -j ACCEPT

    

    开放被动模式的ftp服务:

    (1)装载追踪ftp协议的模块

   # lsmod |grep conntrack
   # modprobe nf_conntrack_ftp

    (2)放行命令连接

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

    (3)放行数据连接

~]# iptables -A INPUT -d 172.16.100.67 -p tcp -m state --state RELATED -j ACCEPT


4.3 处理动作(目标)


-j targetname [per-target-options]

targetname常见的有:DROP,ACCEPT,REJECT,RETRUN,REDIRECT,SNAT,DNAT,MASQUERADE,MARK,LOG

DROP,ACCEPT,REJECT 常用于过滤数据包

RETRUN:是返回调用者,通常用在自定义的链上,在自义链中无法匹配报文时,将其返回主链

     示例:添加自定义链

     添加:       

        iptables -N icmp_rules
        iptables -I FORWARD 2 -p icmp -j icmp_rules
        iptables -A icmp_rules -p icmp --icmp-type 8 -m state --state NEW -j ACCEPT

     返回主链:  

        iptables -A icmp_rules -j RETURN
        自定义链跟内核中的钩子是没有任何关系的,只要不被引用就不会被生效。

     删除自定义链:     

        iptables -D FORWARD 2
        iptables -F icmp_rules
        iptables -X icmp_rule

   

REDIRECT:端口重定向

    REDIRECT只能用于nat表的PREROUTING和OUTPUT链

    --to-ports port[-port]:映射至哪个目标端口; 

    示例:

    ~]# iptables -t nat -A PREROUTING -d 172.16.52.53 -p tcp --dport 80 -j REDIRECT --to-port 8088


SNAT:源地址转换

    SNAT只能用于nat表的POSTROUTING和INPUT

    --to-source  [ipaddr[-ipaddr]][:port[-port]]

    示例:如果我们希望内网主机与外网主机通讯使用的源地址都是网关主机的外网接口的地址,怎么

          实现?假设网关主机外网接口为172.16.52.52

  iptables -t nat -A POSTROUTING -s 192.168.11.0/24 -j SNAT --to-source 172.16.52.52


MASQUERADE:只有外网地址是动态获取时才能使用该选项

    外网地址是动态获取时,就要借助于MASQUERADE来动态指明要转换的地址


DNAT:目标地址转换

    DNAT只能用于nat表的PREROUTING和OUTPUT链

    作用:让本地网络中服务器使用统一的地址向外提供服务(发布服务),但隐藏了自己的真实地

          址;用于公开本来是隐藏在网关服务器之后的某台或某些主机的某些服务。

    示例:假如网关主机中ip地址172.16.52.50,是专门用来发布内网主机的。

          现在要求只要外网用户访问52.50,就转发到后端主机

iptables -t NAT -A PREROUTING -d 172.16.52.50 -j DNAT -to-destination 192.168.11.2

          只要访问52.50的80端口,我就转发到后端主机 

 iptables -t NAT -A PREROUTING -d 172.16.52.50 -p tcp --dport 80 -j DNAT -to-destination 192.168.11.2

          只要访问52.50的80端口,就映射到后端主机的8089端口

iptables -t NAT -A PREROUTING -d 172.16.52.50 -p tcp --dport 80 -j DNAT -to-destination 192.168.11.2:8089

    

LOG:用于记录日志。(注意:要先记录日志,然后再拒绝访问)     

    --log-level level

        emerg, alert, crit, error, warning, notice, info or debug.

    --log-prefix prefix

    --log-prefix

    --log-ip-options

    示例:

iptables -A INPUT -d 172.16.52.53 -p tcp --dport 8088 -j LOG --log-prefix "(to 8088)" --log-ip-options


4.4 规则的保存和重载


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

保存规则:iptables-save > /PATH/TO/SOME_RULE_FILE 

    CentOS 6:

        # service iptables save 自动保存规则至/etc/sysconfig/iptables文件中;

# iptables-save  > /etc/sysconfig/iptables

# iptables-save  >  /PATH/TO/SOME_RULE_FILE

    CentOS 7:

# iptables  -S  > /PATH/TO/SOME_RULE_FILE

        # iptables-save  >  /PATH/TO/SOME_RULE_FILE

    

重载规则:iptables-restore < /PATH/FROM/SOME_RULE_FILE

    CentOS 6:

        # server iptables restore 从/etc/sysconfig/iptables文件中重载规则; 

    CentOS 7:

        # iptables-restore < /PATH/FROM/SOME_RULE_FILE

        

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

    (1) 把iptables命令放在脚本文件中,让脚本文件开机自动运行;

/etc/rc.d/rc.local

/usr/bin/iptables.sh

    (2) 用规则文件保存规则,开机自动重载命令;

/etc/rc.d/rc.local

iptables-restore  <  /PATH/FROM/SOME_RULE_FILE

          
4.5 iptables规则优化


(1) 可安全放行所有入站及出站,且状态为ESTABLISHED的连接;

(2) 服务于同一类功能的规则,匹配条件严格的放前面,宽松放后面;

(3) 服务于不同类功能的规则,匹配报文可能性较大扩前面,较小放后面;

(4) 设置默认策略;

(a) 最后一条规则设定;

(b) 默认策略设定; 


4.6 练习题


假设本地主机为172.16.52.51

1、限制本地主机的web服务器在周一不允许访问;新请求的速率不能超过100个每秒;web服务器包含了admin字符串的页面不允许访问;web服务器仅允许响应报文离开本机;

iptables  -A INPUT -d 172.16.52.51 -p tcp --dport 80 -m time ! --weekdays Mon -m  limit --limit 100/second -m state --state NEW --j ACCEPT
iptables -I OUTPUT -s 172.16.52.51 -p tcp --sport 80 -m string --string "admin" -algo kmp -j REJECT

iptables -A OUTPUT -s 172.16.52.61 -p tcp --sport 80 -m state --state ESTABLISHED -J ACCEPT

2、在工作时间,即周一到周五的8:30-18:00,开放本机的ftp服务给172.16.0.0网络中的主机访问;数据下载请求的次数每分钟不得超过5个;

iptables -A INPUT  -d 172.16.52.51 -s 172.16.0.0/24 -p tcp --dport 21  -m time --timestart 08:30:00 --timestop 18:00:00 --weekdays 1,2,3,4,5 -m limit --limit 5/minute -j ACCEPT

3、开放本机的ssh服务给172.16.52.1-172.16.52.100中的主机,新请求建立的速率一分钟不得超过2个;仅允许响应报文通过其服务端口离开本机;

iptables -A INPUT -d 172.16.52.51 -p tcp --dport 22 -m -iprange --src-range 172.16.52.1-172.16.52.100 -m state --state NEW -m limit --limint 2/minute -j ACCEPT
iptables -A OUTPUT -s 172.16.52.51 -p tcp --sport 22 -m iprange --dst-range 172.16.52.1-172.16.52.100 -m state --state ESTABLISHED -j ACCEPT

4、拒绝TCP标志位全部为1及全部为0的报文访问本机;

iptables -A INPUT -d 172.16.52.51 -p --tcp-flags ALL ALL -j DROP
iptables -A INPUT -d 172.16.52.51 -p --tcp-flags ALL NONE -j DROP

5、允许本机ping别的主机;但不开放别的主机ping本机;

iptables -A OUTPUT -s 172.16.52.51 -p icmp --icmp-type 8 -j ACCEPT
iptables -A INIPUT -d 172.16.52.51 -p icmp --icmp-type 0 -j ACCEPT


感谢:MageEdu