iptables详解:常用模块的基本使用

目录

tcp扩展模块

multiport扩展模块

iprange扩展模块

connlimit模块

limit扩展模块

udp扩展模块

icmp扩展模块

state扩展模块

限制每分钟接收10个ICMP数据报文

允许10个数据报文快速通过,然后限制每分钟接收1个个ICMP数据报文

限制网络传输的带宽不可以超过500k/s


tcp扩展模块

-p tcp -m tcp --sport用于匹配tcp协议报文的源端口,可以使用冒号指定一个连续的端口范围

  • -p protocol,
  • -m:match,指匹配的模块,很多人可能以为是module的缩写,其实是match的缩写,
  • --sport: source port);-p tcp -m tcp
  • --dport用于匹配tcp协议报文的目标端口,可以使用冒号指定一个连续的端口范围(--dport 80:88

这里是我们正常访问80端口的页面

iptables详解:常用模块的基本使用_第1张图片

这面的规则是拒绝了来自192.168.159.1无法使用tcp访问本机(192.168.159.200)的80:88端口

iptables -t filter -I INPUT -s 192.168.159.1 -m tcp -p tcp --dport 80:88 -j REJECT

我们可以尝试使用22端口ssh来测试一下:

iptables详解:常用模块的基本使用_第2张图片

可以看到我们还是访问成功了,这是为什么呢,就是因为我们设置的规则它是开区间的,80:88,但是并不包括80,所以我们应该设置为79:88。

修改完成后再测试:

iptables详解:常用模块的基本使用_第3张图片

查看iptables表我们也可以发现这条拒绝规则收到了数据

此外,tcp扩展模块还有-tcp-flags选项,它可以根据TCP头部的“标识位”来匹配。

注:这里只能封连续的端口,无法封分散的端口,下面的multiport就可以解决这个问题

multiport扩展模块

-p tcp -m multiport --sports用于匹配报文的源端口,可以指定离散的多个端口号,端口之间用”逗号”隔开;

-p udp -m multiport --dports用于匹配报文的目标端口,可以指定离散的多个端口号,端口之间用”逗号”隔开:

iptables -t filter -I INPUT -s 192.168.159.1 -m multiport -p tcp --dport 80,22 -j REJECT
这里拒绝了来自192.168.159.1 目标80 和 22 端口的流量

我们刚敲完这条命令就会发现由于拒绝了22端口,我们的远程连接直接断开了

那么再测试一下80端口:

 iptables详解:常用模块的基本使用_第4张图片

这里很明显也拒绝成功了!

iprange扩展模块

使用iprange扩展模块可以指定”一段连续的IP地址范围”,用于匹配报文的源地址或者目标地址。iprange扩展模块中有两个扩展匹配条件可以使用:

--src-range(匹配源地址范围)

– --dst-range(匹配目标地址范围)

iptables -t filter -I INPUT -m iprange --src-range 192.168.159.201-192.168.159.222  -j DROP

上面这条规则的意思就是封堵了192.168.159.201-222ip

那么我们可以尝试使用192,168,159.201尝试ping一下本机

可以看到一直卡在这里,说明规则确实生效了,DROP掉了我们的icmp包 

connlimit模块

使用connlimit扩展模块,可以限制每个IP地址同时链接到server端的链接数量

注意:我们不用指定IP,其默认就是针对”每个客户端IP”,即对单IP的并发连接数限制。(可以限制并发连接,即最多只能有两个进程)

限制22端口(ssh默认端口)连接数量上限不能超过2个;

iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT

表示连接数量只要不超过两个就允许连接,至于超过两个并不一定不允许连接,这得看默认策略是ACCEPT还是DROP或REJECT,又或者有其它规则对它进行限制。

可以配合--connlimit-mask来限制网段:

iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 --connlimit-mask 24 -j REJECT

网址由32位二进制组成,最大可写成:255.255.255.255,而mask就是掩码(网络知识,请自行了解),24表示24个1,即255.255.255.0。

我们在192.168.159.200上面配置了限制只能连接两个的规则

连接测试一下:

iptables详解:常用模块的基本使用_第5张图片

limit扩展模块

limit模块是限速用的,用于限制“单位时间内流入的数据包的数量”。

每6位秒放行一下ping包(因为1分钟是60秒,所以1分钟10个包,就相当于每6秒1个包):

iptables -t filter -I INPUT -p icmp -m limit --limit 10/minite -j ACCEPT
//默认规则需要修改为DROP

然后需要将默认规则修改为DROP,否则会走默认的ACCEPT规则

iptables -P INPUT DROP

注:修改万模默认规则远程连接可能会断开,不过没有关系,用别的主机测试即可 

--limit后面的单位除了minite,还可以是second、hour、day

--limit-burst: burst是爆发、迸发的意思,在这里是指最多允许一次性有几个包通过,要理解burst,先看以下的“令牌桶算法”。

注:可以防御DDos攻击

令牌桶算法: 有一个木桶,木桶里面放了5块令牌,而且这个木桶最多也只能放下5块令牌,所有报文如果想要出关入关,都必须要持有木桶中的令牌才行,这个木桶有一个神奇的功能,就是每隔6秒钟会生成一块新的令牌,如果此时,木桶中的令牌不足5块,那么新生成的令牌就存放在木桶中,如果木桶中已经存在5块令牌,新生成的令牌就无处安放了,只能溢出木桶(令牌被丢弃),如果此时有5个报文想要入关,那么这5个报文就去木桶里找令牌,正好一人一个,于是他们5个手持令牌,快乐的入关了,此时木桶空了,再有报文想要入关,已经没有对应的令牌可以使用了,但是,过了6秒钟,新的令牌生成了,此刻,正好来了一个报文想要入关,于是,这个报文拿起这个令牌,就入关了,在这个报文之后,如果很长一段时间内没有新的报文想要入关,木桶中的令牌又会慢慢的积攒了起来,直到达到5个令牌,并且一直保持着5个令牌,直到有人需要使用这些令牌,这就是令牌桶算法的大致逻辑。

看完了“令牌桶算法”,其实--limit就相当于指定“多长时间生成一个新令牌”,而--limit-burst则用于指定木桶中最多存放多少块令牌。

我们在192.168.159.200上面配置了上面的那一条规则,然后尝试使用192.168.159.201ping200看看效果:

iptables详解:常用模块的基本使用_第6张图片

 可以看到从第六个包开始下面的每一个包都是间隔了6秒发送的

udp扩展模块

udp扩展模块中能用的匹配条件比较少,只有两个,就是--sport--dport,即匹配报文的源端口与目标端口。

例如放行samba服务的137和138端口:

iptables -t filter -I INPUT -p udp -m udp --dport 137 -j ACCEPT
iptables -t filter -I INPUT -p udp -m udp --dport 138 -j ACCEPT

udp扩展中的--sport--dport与tcp一样,同样支持指定一个连续的端口范围:

iptables -t filter -I INPUT -p udp --dport 137:157 -j ACCEPT

另外与tcp一样,udp也能使用--multiport指定多个不连续的端口。

icmp扩展模块

ping是使用icmp协议的,假设要禁止所有icmp协议的报文进入本机(根据前面所说,我们可以省略用-m icmp来指定使用icmp模块,因为不指定它会默认使用-p指定的协议对应的模块):

iptables -t filter -I INPUT -p icmp -j REJECT

上述命令能产生两个效果:

– 1、别人ping本机时,无法ping通,因为数据报文无法进入

– 2、本机ping别人时,虽然数据包可以出去,但别人的响应包也是icmp协议,无法进来(即“有去无回”)。

所以这样设置会导致,不止别人ping不通本机,本机也ping不通别人。


很明显上边的规则不是我们想要的,我们想要的一般都是允许本机ping别人,不允许别人ping本机:

iptables -t filter -I INPUT -p icmp --icmp-type 8/0(type为8,code为0) -j REJECT

--icmp-type 8/0用于匹配报文type为8,code为0时才会被匹配到,至于会是type和code,这是icmp协议的知识。

其实上边的命令还可以省略code(即把“8/0”写成“8”即可,省略掉“/0”,原因是type=8的报文中只有code=0一种,所以我们不写默认就是code=0,不会有其它值):

iptables -t filter -I INPUT -p icmp --icmp-type 8 -j REJECT

除了能用type/code来匹配icmp报文,还可以使用icmp的描述名称来匹配:

iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT

--icmp-type "echo-request"的效果与icmp --icmp-type 8/0icmp --icmp-type 8的效果完全一样(你可能发现了,icmp协议的描述“echo-request”其实是“echo request”,只不过我们用于作为匹配条件时,要把空格换成横杠)。

例如:

在192.168.159.200上进行配置
iptables -t filter -I INPUT -p icmp --icmp-type 8/0(type为8,code为0) -j REJECT
这里拒绝了给本机里面走的8/0,所以别人无法ping你

配置完成后

本主机ping别人:

iptables详解:常用模块的基本使用_第7张图片

别人ping本主机:

iptables详解:常用模块的基本使用_第8张图片

注:这里可以使用Wireshark抓包查看

200->201的icmp包:

iptables详解:常用模块的基本使用_第9张图片

后面就正常的ping

201->200的icmp包

iptables详解:常用模块的基本使用_第10张图片

这里就会拒绝这个包

state扩展模块

在TCP/IP协议簇中,UDP和ICMP是没有所谓的连接的,但是对于state模块来说,tcp报文、udp报文、icmp报文都是有连接状态的,我们可以这样认为,对于state模块而言,只要两台机器在”你来我往”的通信,就算建立起了连接。

而”连接”中的报文可以分为5种状态,报文状态可以为NEW(连接的第一个包)、ESTABLISHED(表示连接已经建立)、RELATED(相关联的连接,当前连接是一个新请求,但是附属于某个已经存在的连接)、INVALID(没有办法识别的包的状态)、UNTRACKED(报文未追踪)。

放行RELATED和ESTABLISHED状态的报文:

iptables -t filter -I INPUT -m state --state RELATED, ESTABLISHED -j ACCEPT
iptables -t filter -A INPUT -j REJECT
//这两条命令也可以防止nmap的端口扫描

当我们通过http的url访问某个网站的网页时,客户端向服务端的80端口发起请求,服务端再通过80端口响应我们的请求,于是,作为客户端,我们似乎应该理所应当的放行80端口,以便服务端回应我们的报文可以进入客户端主机,于是,我们在客户端放行了80端口,同理,当我们通过ssh工具远程连接到某台服务器时,客户端向服务端的22号端口发起请求,服务端再通过22号端口响应我们的请求,于是我们理所应当的放行了所有22号端口,以便远程主机的响应请求能够通过防火墙,但是,作为客户端,如果我们并没有主动向80端口发起请求,也没有主动向22号端口发起请求,那么其他主机通过80端口或者22号端口向我们发送数据时,我们可以接收到吗?应该是可以的,因为我们为了收到http与ssh的响应报文,已经放行了80端口与22号端口,所以,不管是”响应”我们的报文,还是”主动发送”给我们的报文,应该都是可以通过这两个端口的,那么仔细想想,这样是不是不太安全呢?如果某些与你敌对的人,利用这些端口”主动”连接到你的主机,你肯定会不爽的吧,一般都是我们主动请求80端口,80端口回应我们,但是一般不会出现80端口主动请求我们的情况吧。

你心里可能会这样想:我知道哪些主机是安全的,我只要针对这些安全的主机放行对应的端口就行了,其他IP一律拒绝,比如,我知道IP为123的主机是安全的,所以,我对123主机开放了22号端口,以便123主机能够通过22号端口响应我们的ssh请求,

那么,如果你需要管理的主机越来越多呢?你是不是每次都要为新的主机配置这些规则呢?如果有30台主机呢?如果有300台主机呢?80端口就更别提了,难道你每次访问一个新的网址,都要对这个网址添加信任吗?这显然不太合理。

你心里可能又会想:针对对应的端口,我用–tcp-flags去匹配tcp报文的标志位,把外来的”第一次握手”的请求拒绝,是不是也可以呢?那么如果对方使用的是UDP协议或者ICMP协议呢?似乎总是有一些不完美的地方。

那么我们仔细的思考一下,造成上述问题的”根源”在哪里,我们为了让”提供服务方”能够正常的”响应”我们的请求,于是在主机上开放了对应的端口,开放这些端口的同时,也出现了问题,别人利用这些开放的端口,”主动”的攻击我们,他们发送过来的报文并不是为了响应我们,而是为了主动攻击我们,好了,我们似乎找到了问题所在?

问题就是:怎样判断这些报文是为了回应我们之前发出的报文,还是主动向我们发送的报文呢?

我们可以通过iptables的state扩展模块解决上述问题,但是我们需要先了解一些state模块的相关概念,然后再回过头来解决上述问题。

从字面上理解,state可以译为状态,但是我们也可以用一个高大上的词去解释它,state模块可以让iptables实现”连接追踪”机制。

那么,既然是”连接追踪”,则必然要有”连接”。

咱们就来聊聊什么是连接吧,一说到连接,你可能会下意识的想到tcp连接,但是,对于state模块而言的”连接”并不能与tcp的”连接”画等号,在TCP/IP协议簇中,UDP和ICMP是没有所谓的连接的,

但是对于state模块来说,tcp报文、udp报文、icmp报文都是有连接状态的,我们可以这样认为,对于state模块而言,只要两台机器在”你来我往”的通信,就算建立起了连接,如下图所示

iptables详解:常用模块的基本使用_第11张图片

而报文在这个所谓的链接中是什么状态的呢?这是我们后面讨论的话题。

对于state模块的连接而言,”连接”其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED

那么上述报文的状态都代表什么含义呢?我们先来大概的了解一下概念,然后再结合示例说明。

注意:如下报文状态都是对于state模块来说的。

  • NEW:连接中的第一个包,状态就是NEW,我们可以理解为新连接的第一个包的状态为NEW。

  • ESTABLISHED:我们可以把NEW状态包后面的包的状态理解为ESTABLISHED,表示连接已建立。

或许用图说话更容易被人理解

iptables详解:常用模块的基本使用_第12张图片

  • RELATED:从字面上理解RELATED译为关系,但是这样仍然不容易理解,我们举个例子。

比如FTP服务,FTP服务端会建立两个进程,一个命令进程(20),一个数据进程(21)。

命令进程负责服务端与客户端之间的命令传输(我们可以把这个传输过程理解成state中所谓的一个”连接”,暂称为”命令连接”)。

数据进程负责服务端与客户端之间的数据传输 ( 我们把这个过程暂称为”数据连接” )。

但是具体传输哪些数据,是由命令去控制的,所以,”数据连接”中的报文与”命令连接”是有”关系”的。

那么,”数据连接”中的报文可能就是RELATED状态,因为这些报文与”命令连接”中的报文有关系。

(注:如果想要对ftp进行连接追踪,需要单独加载对应的内核模块nf_conntrack_ftp,如果想要自动加载,可以配置/etc/sysconfig/iptables-config文件)

INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是INVALID,我们可以主动屏蔽状态为INVALID的报文。

UNTRACKED:报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接。

好了,我们已经大致了解了state模块中所定义的5种状态,那么现在,我们回过头想想刚才的问题。

刚才问题的根源就是:怎样判断报文是否是为了回应之前发出的报文。

刚才举例中的问题即可使用state扩展模块解决,我们只要放行状态为ESTABLISHED的报文即可,因为如果报文的状态为ESTABLISHED,那么报文肯定是之前发出的报文的回应,如果你还不放心,可以将状态为RELATED或ESTABLISHED的报文都放行,这样,就表示只有回应我们的报文能够通过防火墙,如果是别人主动发送过来的新的报文,则无法通过防火墙,示例如下。

iptables -F
iptables -t filter -I INPUT -m state  --state RELATED,ESTABLISHED -j ACCEPT 
//接受回复的ESTABLISHED的连接
iptables  -t filter -A INPUT -j REJECT 
//直接连接的NEW会被拒绝掉

实验验证:

(1)在192.168.159.200上进行配置

[root@centos111 ~]# iptables -F
[root@centos111 ~]# iptables -t filter -I INPUT -m state  --state RELATED,ESTABLISHED -j ACCEPT
[root@centos111 ~]# iptables -t filter -A INPUT  -j REJECT 

(2)在200上尝试远程登录192.168.159.201

[root@centos111 ~]# ssh [email protected]
[email protected]'s password: 
Last failed login: Sun Nov 19 09:55:47 CST 2023 from 192.168.159.200 on ssh:notty
There was 1 failed login attempt since the last successful login.
Last login: Sun Nov 19 09:02:50 2023 from 192.168.159.1
[root@centos222 ~]# 

//这里成功的连接了

(3)在201上尝试远程连接200

[root@centos222 ~]# ssh [email protected]
ssh: connect to host 192.168.159.200 port 22: Connection refused

验证成功!

下面介绍几个实用的案例:

限制每分钟接收10个ICMP数据报文

1.先添加一条规则,限制1分钟内只收10个icmp协议的请求报文。
iptables -t filter -I INPUT -p icmp -m limit --limit 10/minute -j ACCEPT
2.然后添加第二条规则,超出10个报文后,其余的报文全部丢弃。
iptables -t filter -A INPUT -p icmp -j DROP
3.查看添加的防火墙规则
[root@centos222 ~]# iptables -t filter -nvxL INPUT --line-numbers 
Chain INPUT (policy ACCEPT 171 packets, 10464 bytes)
num      pkts      bytes target     prot opt in     out     source               destination         
1           0        0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0            limit: avg 10/min burst 5
2           0        0 DROP       icmp --  *      *       0.0.0.0/0            0.0.0.0/0 

查看效果,可以看到前5个数据包都可以正常接收,那是因为limit默认初始包就是5个,因此没有任何问题,从第六个数据包开始后,每隔6秒才会正常处理一个数据包,因为1分钟限制10次数据包的接收,那就表示6秒收一个,效果如下图所示。

也可以理解为是一开始可以快速通过5个数据报文,后面的数据报文是每分钟通过10个。

iptables详解:常用模块的基本使用_第13张图片

允许10个数据报文快速通过,然后限制每分钟接收1个个ICMP数据报文

实现思路和1)中一模一样,只不过就是调整一下初始包的数量。

1.先添加一条规则,限制1分钟内只收10个icmp协议的请求报文。
iptables -t filter -I INPUT -p icmp -m limit --limit 1/m --limit-burst 10 -j ACCEPT
2.然后添加第二条规则,超出10个报文后,其余的报文全部丢弃。
iptables -t filter  -A INPUT -p icmp -j DROP

效果如下,首先发送了10个数据包正常接收,剩下的数据包每隔1分钟接收1个。 iptables详解:常用模块的基本使用_第14张图片

限制网络传输的带宽不可以超过500k/s

限速如何通过limit模块来实现呢?其实也很简单,我们可以计算出1个数据包的大小,然后用500k的大小除以数据包的大小,得出500k能换算出多少个数据包,例如是300个,那么最后设置1秒钟接收的数据包的数量为300个,就可以实现每秒的传输速率带宽在500k左右。

一个数据包的大小大概在1500字节。

公式:(限制的带宽速率*1000)/(单个数据包的大小)

500k的限速,每秒可限制的数据包数量大概为(500*1000/150 = 300个)300个。

[root@centos111 ~]# iptables -t filter -I INPUT -p  tcp -m limit --limit 300/s  -j ACCEPT
[root@centos111 ~]# iptables -t filter -A INPUT -p  tcp -j DROP

速率带宽多多少少是由落差的,如果就想限制在500k以内,可以根据测试的结果来调整每秒数据包的效果,如下图所示,拉取文件的速率为327k/s,此时数据包的数量我是设置的120个。

我们尝试在配置规则完成后的主机上测试传输一个东西:

首先可以使用find命令找一个比较大的文件:

find / -type f -size +100M

然后我使用scp 将这个文件传入到一个目录下,查看它的传输速度:

scp /usr/lib64/firefox/libxul.so [email protected]:/tmp

但是这里并没有生效,只是传输的很慢而已,大概两分钟传输完了

我们试着清理掉防火墙规则后再测试一下:

这里可以看到1秒中传输完了,这说明我们前面的限速还是有作用的,只是没有达到预期的那么慢

 到这里iptables的基础知识和一些常用的模块的基本使用就介绍完毕了

你可能感兴趣的:(安全,防火墙,linux,网络,linux,服务器,运维,web安全,安全,iptables)