1.配置多源ip或者网段限制
# 丢弃掉来自192.168.1.111,192.168.1.112的所有报文
iptables -t filter -I INPUT -s 192.168.1.111,192.168.1.112 -j DROP
# DROP掉某个网段的报文
iptables -t filter -I INPUT -s 10.6.0.0/16 -j DROP
# 对来源地址取反,只要发往本机的报文的源地址不是192.168.1.146,就接受报文
iptables -t filter -I INPUT ! -s 192.168.1.146 -j DROP
2.配置对目标ip的限制
是用-d
参数对目的地址进行限制。注意,如果是对源和目标地址都有限制,需要同时满足才会执行对应规则。
# 禁止报文从192.168.1.146发到192.168.1.156
iptables -t filter INPUT -s 192.168.1.146 -d 192.168.1.156 -j DROP
# 禁止报文发到192.168.1.156的所有报文
iptables -t filter INPUT -d 192.168.1.156 -j DROP
3.协议类型匹配
使用 -p
参数对报文协议进行匹配,协议内容包含: tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh。
# REJECT掉发往192.168.1.156的tcp协议报文
iptables -t filter -I INPUT -d 192.168.1.156 -p tcp -j REJECT
4.匹配网卡
使用-i
对车机报文通过某一网卡流入进行限制,使用-o
对车机报文通过某一网卡流出进行限制。
-i
选项只能用于PREROUTING链、INPUT链、FORWARD链,那么-o
选项只能用于FORWARD链、OUTPUT链、POSTROUTING链
# DROP掉经过wlan0口的ping报文
iptables -t filter -I INPUT -i wlan0 -p icmp -j DROP
5.限制端口
5.1 限制目标端口
使用 --dport
限制目标端口。在使用--dport
选项时,必须事先指定了使用哪种协议,即必须先使用-p
选项。
使用-–dport
之前,我们使用-m
选项,指定了对应的扩展模块为tcp,也就是说,如果想要使用-–dport
这个扩展匹配条件,则必须依靠某个扩展模块完成。
# REJECT 外来报文的目标端口为本机的22号端口(ssh默认端口)
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 22 -j REJECT
# -m tcp表示使用tcp扩展模块,–dport表示tcp扩展模块中的一个扩展匹配条件,可用于匹配报文的目标端口。
# 注意,-p tcp与 -m tcp并不冲突,-p用于匹配报文的协议,-m 用于指定扩展模块的名称,正好,这个扩展模块也叫tcp。
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp --dport 22 -j REJECT
5.2 限制源端口
使用--sport
可以判断报文是否从指定的端口发出,即匹配报文的源端口是否与指定的端口一致
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp --sport 22 -j REJECT
5.3 限制端口范围
# REJECT目标端口为22到25之间的所有端口
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp --dport 22:25 -j REJECT
# 表示匹配0号到22号之间的所有端口
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp --dport :22 -j REJECT
# 表示匹配80号端口以及其以后的所有端口(直到65535)
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp --dport :22 -j REJECT
# 管理多个离散的源端口
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dport 22,36,88 -j REJECT
6. iprange扩展模块
-s
选项与-d
选项并不能一次性的指定一段连续的IP地址范围,如果我们需要指定一段连续的IP地址范围,可以使用iprange扩展模块。
iprange扩展模块中有两个扩展匹配条件可以使用: --src-range 和 --dst-range
# 如果报文的源IP地址如果在192.168.1.127到192.168.1.146之间,则丢弃报文
iptables -t filter -I INPUT -m iprange --src-rang 192.168.1.127-192.168.1.146 -j DROP
7.String扩展模块
使用string扩展模块,可以指定要匹配的字符串,如果报文中包含对应的字符串,则符合匹配条件。
iptables -t filter -I INPUT -m string --algo bm --string "xxxx" -j REJECT
-m string
表示使用string模块,--algo bm
表示使用bm算法去匹配指定的字符串,--string "xxxx"
则表示我们想要匹配的字符串为”xxxx”.
- --algo:用于指定匹配算法,可选的算法有bm与kmp,此选项为必须选项,我们不用纠结于选择哪个算法,但是我们必须指定一个。
- --string:用于指定需要匹配的字符串。
8.time扩展模块
可以通过time扩展模块,根据时间段区匹配报文,如果报文到达的时间在指定的时间范围以内,则符合匹配条件。
8.1 约束在晚上12点-早上7点不能上网,保证充足睡眠。
# 限制http端口
iptables -t filter -I INPUT -p tcp --dport 80 -m time --timestart 00:00:00 --timestop 07:00:00 -j REJECT
# 限制https端口
iptables -t filter -I INPUT -p tcp --dport 443 -m time --timestart 00:00:00 --timestop 07:00:00 -j REJECT
8.2 约束周末不能上网
--weekdays
可以取反
iptables -t filter -I INPUT -p tcp --dport 80 -m time --weekdays 6,7 -j REJECT
iptables -t filter -I INPUT -p tcp --dport 443 -m time --weekdays 6,7 -j REJECT
8.3 约束每月某些天不能上网
--monthdays
可以取反
iptables -t filter -I INPUT -p tcp --dport 80 -m time --monthdays 10,11 -j REJECT
iptables -t filter -I INPUT -p tcp --dport 443 -m time --monthdays 10,11 -j REJECT
8.4 限制时间段
iptables -t filter -I INPUT -p tcp --dport 80 -m time --datestart 2021-05-24 --datestop 2021-05-30 -j REJECT
iptables -t filter -I INPUT -p tcp --dport 443 -m time --datestart 2021-05-24 --datestop 2021-05-30 -j REJECT
9.connlimit扩展模块
使用connlimit扩展模块,可以限制每个IP地址同时链接到server端的链接数量,注意:我们不用指定IP,其默认就是针对”每个客户端IP”,即对单IP的并发连接数限制。
9.1 限制每个IP地址最多只能占用两个ssh链接远程到server端
使用–connlimit-above 2
表示限制每个IP的链接数量上限为2,再配合-p tcp
, –dport 22
,即表示限制每个客户端IP的ssh并发链接数量不能高于2。
iptables -t filter -I INPUT -p tcp --dport 22 -m connlimt --connlimit-above 2 -j ACCEPT
9.2 限制某个网段,最多多少个链接
使用--connlimit-mask
限制某个网段,–connlimit-mask 27
表示某个C类网段,这个网段中最多只能有30台机器(30个IP),这30个IP地址最多只能有10个ssh连接同时连接到服务器端。
iptables -t filter -I INPUT -p tcp --dport 22 -m connlimt --connlimit-above 10 --connlimit-mask 27 -j ACCEPT
mask是子网掩码的意思,通过子网掩码来限制ip段。
10.limit扩展模块
使用limit模块是对”报文到达速率”进行限制,可以以秒为单位进行限制,也可以以分钟、小时、天作为单位进行限制。
10.1 限制,外部主机对本机进行ping操作时,本机最多每6秒中放行一个ping。
iptables -t filter -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT
如果单是以上规则,是无法限制每6秒到来的报文的。因为当1-5秒到来的报文,会走默认规则,默认是ACCEPT。
因此,还需要添加默认的匹配规则。
iptables -t filter -I INPUT -p icmp -j REJECT
需要注意的是,需要先配置接受规则,再配置拒绝规则。
如上配置之后,我们看看现象如下
可以看到1-5的报文没有被过滤到,后面的报文每6秒接受到一次,以满足拦截需求的。
出现这个现象的原因是:limit模块使用了令牌桶算法。
令牌桶算法:我们可以这样想象,有一个木桶,木桶里面放了5块令牌,而且这个木桶最多也只能放下5块令牌,所有报文如果想要出关入关,都必须要持有木桶中的令牌才行,这个木桶有一个神奇的功能,就是每隔6秒钟会生成一块新的令牌,如果此时,木桶中的令牌不足5块,那么新生成的令牌就存放在木桶中,如果木桶中已经存在5块令牌,新生成的令牌就无处安放了,只能溢出木桶(令牌被丢弃),如果此时有5个报文想要入关,那么这5个报文就去木桶里找令牌,正好一人一个,于是他们5个手持令牌,快乐的入关了,此时木桶空了,再有报文想要入关,已经没有对应的令牌可以使用了,但是,过了6秒钟,新的令牌生成了,此刻,正好来了一个报文想要入关,于是,这个报文拿起这个令牌,就入关了,在这个报文之后,如果很长一段时间内没有新的报文想要入关,木桶中的令牌又会慢慢的积攒了起来,直到达到5个令牌,并且一直保持着5个令牌,直到有人需要使用这些令牌,这就是令牌桶算法的大致逻辑。
因此,我们可以–limit-burst
来限制桶的令牌数目。
iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT
11.匹配TCP报文头标志位
可以使用--tcp-flags
匹配报文tcp头部的标志位。
# 匹配第一次握手
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
”SYN,ACK,FIN,RST,URG,PSH SYN”, 这串字符就是用于配置我们要匹配的标志位的,我们可以把这串字符拆成两部分去理解,第一部分为”SYN,ACK,FIN,RST,URG,PSH”,第二部分为”SYN”。
第一部分表示:我们需要匹配报文tcp头中的哪些标志位,那么上例的配置表示,我们需要匹配报文tcp头中的6个标志位,这6个标志位分别为为”SYN、ACK、FIN、RST、URG、PSH”,我们可以把这一部分理解成需要匹配的标志位列表。
第二部分表示:第一部分的标志位列表中,哪些标志位必须为1,上例中,第二部分为SYN,则表示,第一部分需要匹配的标志位列表中,SYN标志位的值必须为1,其他标志位必须为0。
所以,上例中的”SYN,ACK,FIN,RST,URG,PSH SYN”表示,需要匹配报文tcp头中的”SYN、ACK、FIN、RST、URG、PSH”这些标志位,其中SYN标志位必须为1,其他的5个标志位必须为0 .
# 匹配第二次握手
iptables -t filter -I INPUT -p tcp -m tcp --sport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN,ACK -j REJECT
以上两条可以简写为:
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN -j REJECT
iptables -t filter -I INPUT -p tcp -m tcp --sport 22 --tcp-flags ALL SYN,ACK -j REJECT
12.icmp扩展
我们平常使用ping命令ping某主机时,如果主机可达,对应主机会对我们的ping请求做出回应(此处不考虑禁ping等情况),也就是说,我们发出ping请求,对方回应ping请求,虽然ping请求报文与ping回应报文都属于ICMP类型的报文,但是如果在概念上细分的话,它们所属的类型还是不同的,我们发出的ping请求属于类型8的icmp报文,而对方主机的ping回应报文则属于类型0的icmp报文,根据应用场景的不同,icmp报文被细分为如下各种类型。
从上图可以看出,所有表示”目标不可达”的icmp报文的type码为3,而”目标不可达”又可以细分为多种情况,是网络不可达呢?还是主机不可达呢?再或者是端口不可达呢?所以,为了更加细化的区分它们,icmp对每种type又细分了对应的code,用不同的code对应具体的场景, 所以,我们可以使用type/code去匹配具体类型的ICMP报文,比如可以使用”3/1″表示主机不可达的icmp报文。
上图中的第一行就表示ping回应报文,它的type为0,code也为0,从上图可以看出,ping回应报文属于查询类(query)的ICMP报文,从大类上分,ICMP报文还能分为查询类与错误类两大类,目标不可达类的icmp报文则属于错误类报文。
而我们发出的ping请求报文对应的type为8,code为0。
12.1 此时我们只想要ping通别人,但是不想让别人ping通我们
iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8/0 -j REJECT
iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8 -j REJECT
// echo-request是协议名,中间空格用‘-’代替
iptables -t filter -I INPUT -p icmp -m icmp --icmp-type "echo-request" -j REJECT
使用”-m icmp”表示使用icmp扩展,因为上例中使用了”-p icmp”,所以”-m icmp”可以省略,使用”–icmp-type”选项表示根据具体的type与code去匹配对应的icmp报文,而上图中的”–icmp-type 8/0″表示icmp报文的type为8,code为0才会被匹配到,也就是只有ping请求类型的报文才能被匹配到,所以,别人对我们发起的ping请求将会被拒绝通过防火墙,而我们之所以能够ping通别人,是因为别人回应我们的报文的icmp type为0,code也为0,所以无法被上述规则匹配到,所以我们可以看到别人回应我们的信息。
13.判断报文是来自回应还是请求
我们可以使用state模块的--state
来追踪链接的状态。
对于state模块的连接而言,”连接”其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED。(详细定义参考文档)
NEW:连接中的第一个包,状态就是NEW,我们可以理解为新连接的第一个包的状态为NEW。
ESTABLISHED:我们可以把NEW状态包后面的包的状态理解为ESTABLISHED,表示连接已建立。
RELATED:从字面上理解RELATED译为关系,但是这样仍然不容易理解,我们举个例子。
比如FTP服务,FTP服务端会建立两个进程,一个命令进程,一个数据进程。
命令进程负责服务端与客户端之间的命令传输(我们可以把这个传输过程理解成state中所谓的一个”连接”,暂称为”命令连接”)。
数据进程负责服务端与客户端之间的数据传输 ( 我们把这个过程暂称为”数据连接” )。
但是具体传输哪些数据,是由命令去控制的,所以,”数据连接”中的报文与”命令连接”是有”关系”的。
那么,”数据连接”中的报文可能就是RELATED状态,因为这些报文与”命令连接”中的报文有关系。
(注:如果想要对ftp进行连接追踪,需要单独加载对应的内核模块nf_conntrack_ftp,如果想要自动加载,可以配置/etc/sysconfig/iptables-config文件)
INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是INVALID,我们可以主动屏蔽状态为INVALID的报文。
UNTRACKED:报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接。
iptables -t filter -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A INPUT -j REJECT