3、iptables扩展及使用

iptables/netfilter

netfilter: kernel framework,位于内核中的协议框架

iptables  是规则管理命令行工具

 

四表:filter, nat, mangle, raw

五链:PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING

 

iptables

子命令:

链:-F, -X, -N, -E, -Z, -P, -L

规则:-A, -I, -D, -R

 

-j TARGET:

    ACCEPT, DROP, REJECT, RETURN, LOG, MARK, DNAT, SNAT, MASQUEARDE, ...

 

匹配标准:

  • 通用匹配:-s, -d, -p, -i, -o
  • 扩展匹配
  • 隐含扩展:
  • -p tcp: --dport, --sport, --tcp-flags, --syn (--tcp-flags SYN,ACK,FIN,RST SYN)
  • -p udp: --dport, --sport
  • -p icmp: --icmp-type
  • 显式扩展: -m

 

iptables:

显式扩展

multiport扩展、iprange扩展、string扩展、time扩展、connlimit扩展、limit扩展、state扩展

 

必须显式指明使用的扩展模块(rpm -ql iptables | grep "\.so"或rpm -ql iptables | grep "[[:lower:]]\+\.so$")

CentOS 6: man iptables

CentOS 7: man iptables-extensions

 

1、multiport扩展   (--dport/--sport指明端口时必须是单个的或连续的)

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

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

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

[!] --ports port[,port|,port:port]...:既能匹配源端口,也能匹配目标端口

-m multiport 示例

# iptables -A INPUT -d 192.168.184.142 -p tcp --dport 22 -j ACCEPT  //放行22号端口

# iptables -A OUTPUT -s 192.168.184.142 -p tcp --sport 22 -j ACCEPT

# iptables -P INPUT DROP     //修改表的默认策略
# iptables -P FORWARD DROP
# iptables -P OUTPUT DROP

此时web服务是无法响应的,下面演示一次性定义开放22和80端口

# iptables -I INPUT -s 192.168.184.0/24 -d 192.168.184.142 -p tcp -m multiport --dports 22,80 -j ACCEPT   入栈

       // -s 指定源IP,这里指的是一个网段,-m 指是使用显式扩展,--dports指定多个离散端口

# iptables -I OUTPUT -d 192.168.184.0/24 -s 192.168.184.142 -p tcp -m multiport --sports 22,80 -j ACCEPT

# iptables -D INPUT 2    
# iptables -D OUTPUT 2

此时的80端口也可以访问了

2、iprange扩展     ip范围

指明连续的(但一般是不能扩展为整个网络)ip地址范围时使用;

[!] --src-range from[-to]:指明连续的源IP地址范围;

[!] --dst-range from[-to]:指明连续的目标IP地址范围;

iprange示例

# iptables -I INPUT  -d 192.168.184.142 -p tcp -m multiport --dports 22:23,80 -m iprange --src-range 192.168.184.1-192.168.184.150 -j ACCEPT
# iptables -I OUTPUT -s 192.168.184.142 -p tcp -m multiport --sports 22:23,80 -m iprange --dst-range 192.168.184.1-192.168.184.150 -j ACCEPT
                                                  //连续端口之间用冒号隔开:22:23,不连续的用80隔开
# iptables -D INPUT 2   
# iptables -D OUTPUT 2

3、string扩展

功能:基于字符串匹配去检查协议传输单元中的内容

1、任何通过网络传输的数据都必定是可以被流式化的数据,

2、数据通过网络传输时,会被封装上各种首部,

string可以检查在网络上发送的每一个报文,报文虽然编码,却可以匹配编码中是否出现了string指定的字符串的。

iptables工作在网络层和传输层,却可以通过string扩展去检查所传输的内容中是否有要匹配的字符串的

 

检查报文中出现的字符串;

--algo {bm|kmp}  指明字符串比对算法,必须给定算法

bm = Boyer-Moore

kmp = Knuth-Pratt-Morris

[!] --string pattern  指明字符串是什么

string示例

在web服务器的web页面文件中定义一个bad.html

# vim /var/www/html/bad.html

  This is a movie page.   //网页内容,如果用户请求的网页中包含movie,那么就拒绝

一般来说当用户请求一个网页,他请求的报文中一般不包含非法内容,因为只有网页响应的时候,网页上的内容有可能包含非法内容,所以应该在output规则上添加规则,同时应该放在output定义的80规则上面,因为如果放在80下面,那么响应报文被80规则匹配到以后直接就发送出去了

未定义之前是可以被访问的

# iptables -I OUTPUT -m string --algo bm --string 'movie' -j REJECT  //下图未做修改

142的默认网页可以查看

但是带有movie的网页无法查看

请求可以进来,但由于含有movie字符串,所以web服务器并不响应

4、time扩展

根据报文到达的时间与指定的时间范围进行匹配;

#man  iptables-extensions 即可查看下面的用法

  • --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...]

从0点到23点之间不允许访问,因为Linux系统用的是CST时间,这里既然拒绝就直接在请求上即INPUT上拒绝,同时同类规则匹配范围小的放前面,所以放在INPUT第一条规则

# iptables -I INPUT -d 192.168.184.142 -p tcp --dport 80 -m time --timestart 00:00 --timestop 23:59 -j REJECT

此时在浏览器中输入192.168.184.142就不再提供web服务了 

5、connlimit扩展

根据每客户端IP(也可以是地址块)做并发连接数数量匹配;即对每个IP可以对服务器同时发送请求的数量的限制。

--connlimit-above n:连接的数量大于n     

--connlimit-upto n: 连接的数量小于等于n    

默认策略是拒绝, 使用--connlimit-upto来允许,默认是允许,使用--connlimit-above允许

限制ssh的并发链接数,放在INPUT链上ssh服务即22号端口的规则的上面

# iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j REJECT

6、limit扩展

基于收发报文的速率做检查;

令牌桶过滤器    令牌桶算法 https://jinnianshilongnian.iteye.com/blog/2305117      https://blog.csdn.net/SunnyYoona/article/details/51228456#commentBox

--limit rate[/second|/minute|/hour|/day]   //表示每秒钟/分钟/小时/天多少个          30/minute:表示每两秒响应一个请求

--limit-burst number  表示未响应前的峰值即第一次响应可以一次性响应多少个请求

示例

  • 0:echo-reply   回显应答
  • 8: echo-request 回显请求

# iptables -A OUTPUT -s 192.168.184.144 -p icmp --icmp-type 8 -j ACCEPT  ping别的主机,先从本主机出去,目标地址不知道,ping请求是8
# iptables -A INPUT -d 192.168.184.144 -p icmp --icmp-type 0 -j ACCEPT   ping别的主机,要接受ping后的报文,目标地址是本机,报文类型是回显应答

以上是只能本机ping别的主机,别的主机无法ping本主机,下面就定义规则为限制别的主机ping本主机的速率

# iptables -A INPUT -d 192.168.184.142 -p icmp --icmp-type 0 -m limit --limit-burst 5 --limit 30/minute -j ACCEPT  //响应请求的速率

//-s源地址省略,表示所有主机可以ping本主机;别的主机ping本主机,请求类型为8,表示回显请求;limit:表示做速率限制,--limit-burst 5:表示第一次可以一次性响应5个请求;--limit 30/minute:表示每两秒一个,
# iptables -A OUTPUT -s 192.168.184.142 -p icmp --icmp-type 8 -j ACCEPT   //响应请求后,从本机响应的报文不再做限制,只要ping进来就能响应

# ping -W 1 192.168.184.142    //使用-W表示ping每隔1秒钟向外发一个包

7、state扩展  状态扩展  (重要)

根据连接追踪机制检查连接的状态,对链接做出匹配检查;

连接追踪是iptables在内核内部找一段内核空间,并在这段内核空间中记录下来此前每一个源地址,和这个源地址访问的目标地址(目标地址一般是本机地址),然后给每一个源地址和目标地址的链接记录下来,并在后面记录一个倒计时的计时器(可以记录的非常详细,比如包括协议、源端口、目标端口等),这个内存空间是在内核中,所以这个内核比较小

链接与链接之间的状态,跟tcp、udp、icmp协议无关,是iptables自己在内核中的一个功能

 

调整连接追踪功能所能够容纳的最大连接数量:

/proc/sys/net/nf_conntrack_max

 

已经追踪到并记录下的连接:

/proc/net/nf_conntrack

 

不同协议或连接类型追的时长:

/proc/sys/net/netfilter/

 

可追踪的连接状态:

NEW:新发出的请求;连接追踪模板中不存此连接相关的信息条目,因此,将其识别为第一次发出的请求;

ESTABLISHED:NEW状态之后,连接追踪模板中为其建立的条目失效之前,这段期间内所进行的通信的状态;

RELATED:相关的连接;如ftp协议的命令连接与数据连接之间的关系;

INVALIED:无法识别的连接;

RELATED:一个新的链接请求发起时本来是NEW,但是对ftp这样的应用来讲,数据链接是与一个已存在的命令链接或控制链接是相互关联的,因此在这种场景中,数据链接新发起的链接状态可以识别为NEW,实际上更多在nf_conntrack_ftp打开以后被识别成RELATED请求,不过RELATED这个链接请求建立完成后,后续的传输过程中都是ESTABLISHED。

--state STATE1,STATE2,...            --state NEW,ESTABLISHED

示例

对22和80端口只能是响应,不能去请求。所以对NEW状态的应该放行,因为别的主机可能请求服务器,对于ESTABLISHED也应该放行,因为这是响应。但是对于响应的只能放行ESTABLISHED状态的

# iptables -I INPUT -d 192.168.184.142 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

       //--state NEW,ESTABLISHED   这里是入栈的链接,放行22端口的NEW和ESTABLISHED两种状态

# iptables -I OUTPUT -s 192.168.184.142 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT //出去的报文,只放行状态为ESTABLISHED

像放行22号端口一样放行80端口,就直接修改上面的规则

# iptables -I INPUT -d 192.168.184.142 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT

# iptables -I OUTPUT -s 192.168.184.142 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

下面把两个端口合二为一

# iptables -I INPUT -d 192.168.184.142 -p tcp -m multiport --dports 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT

# iptables -I OUTPUT -s 192.168.184.142 -p tcp -m multiport --sports 22,80 -m state --state ESTABLISHED -j ACCEPT

如果别的主机ping本主机?

# iptables -A INPUT -d 192.168.184.142 -p icmp --icmp-type 0 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -s 192.168.184.142 -p icmp --icmp-type 8 -m state --state ESTABLISHED -j ACCEPT

此时ping就可以建立链接了

从以上可以发现无论是tcp协议还是icmp协议,或者无论是22号端口或者80端口,只要允许进入INPUT,都要放行,所以可以在OUTPUT上定义一条规则,这条规则不定义端口、协议、源IP和目标IP,只定义链接状态ESTABLISHED。

# iptables -I OUTPUT -m state --state ESTABLISHED -j ACCEPT    //此时这里只定义链接状态

一条规则就可以直接对N条规则直接放行,这就是规则优化

可以假设入栈的只要是ESTABLISHED状态的,就说明此前访问过,那么所有ESTABLISHED状态就可以统统放行,只要对NEW状态不放行就可以。

# iptables -I INPUT -m state --state ESTABLISHED -j ACCEPT  //无论tcp、icmp协议的请求,只要是已经建立的链接,只要被第一条匹配到直接通过

# iptables -I INPUT 2 -d 192.168.184.142 -p tcp -m multiport --dports 22,80 -m state --state NEW -j ACCEPT

问题:如何开放被动模式的ftp服务?

对21号端口开放NEW和ESTABLISHED,因为命令链接一般是通过21号端口实现,由于数据链接工作在非固定的随机端口上,

所以只需要检查这个链接的状态是不是为RELATED就可以了,如果是RELATED,无论是入栈还是出栈直接放行就可以。

(1) 装载ftp追踪时的专用的模块:

/lib/modules/3.10.0-693.el7.x86_64/kernel/net

/lib/modules/3.10.0-693.el7.x86_64/kernel/net/netfilter

# modprobe nf_conntrack_ftp   //装载模块

# lsmod   //可以查看装载的模块

 

(2) 放行请求报文:

命令连接:NEW, ESTABLISHED

数据连接:RELATED, ESTABLISHED   

       (数据刚建立链接时的状态叫RELATED,这个只是第一次建立数据链接时,而且不叫新连接,而是RELATED链接,而不是NEW,命令链接才是NEW)

 

ftp专用放行规则

# iptables -A INPUT -d LocalIP -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT   //放行的命令链接

# iptables -A INPUT -d LocalIP -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT      //放行的数据链接,不再限制端口

 

(3) 放行响应报文:

ESTABLISEHD

# iptables -A OUTPUT -s LocalIP -p tcp -m state --state ESTABLISHED -j ACCEPT     //出栈放行

示例

1、安装vsftpd软件并启动

# yum install vsftpd -y

# cp /etc/issue /var/ftp/pub/   //cp文件到vsftp的默认下

# systemctl start vsftpd        //启动ftp服务

# ss -tunl                     //查看21号端口是否启动

2、关闭防火墙并清空规则,下图是已经配置的iptables规则链,可以先保存

# iptables-save > /root/iptables.1

修改成下图的样子

可以在浏览器中访问ftp服务

3、添加规则链

# iptables-restore < /root/iptables.1   //把之前保存的规则重新导入,这里换成了141服务器,在文件中修改IP即可

# modprobe nf_conntrack_ftp   //装载ftp模块
# lsmod | grep ftp

nf_conntrack_ftp   18638   0
nf_conntrack       133387  3  xt_conntrack,nf_conntrack_ftp,nf_conntrack_ipv4

# iptables -R INPUT 2 -d 192.168.184.141 -p tcp -m multiport --dport 21,22,80 -m state --state NEW -j ACCEPT  

    //这里直接修改了INPUT的第二条规则,即在--dport上添加了21号端口,这是放行(进栈)的命令链接,是NEW状态

# iptables -R INPUT 1 -m state --state ESTABLISHED,RELATED -j ACCEPT 

   //RELATED无法确定是tcp的哪个端口,而且只有用到RELATED功能的才会检查RELATED状态,所以很少用,所以直接把第一条规则改为ESTABLISHED和RELATED都放行

出栈的无论什么协议、什么IP、什么端口只要是ESTABLISHED状态全都放行,所以无需再改,所以ftp服务就可以访问了

 命令链接和数据链接的区别?

一个新的链接请求发起时本来是NEW,但是对ftp这样的应用来讲,数据链接是与一个已存在的命令链接或控制链接是相互关联的,因此在这种场景中,数据链接新发起的链接状态可以识别为NEW,实际上更多在nf_conntrack_ftp打开以后被识别成RELATED请求,不过RELATED这个链接请求建立完成后,后续的传输过程中都是ESTABLISHED。

 

posted @ 2018-10-15 13:59  Study~Column  阅读(1313)  评论(0编辑  收藏  举报