6.9.3 利用recent模块限制同一IP的连接数

6.9.2节向大家演示了自动区别黑名单和白名单的iptables脚本,发现将其应用于Web服务器的效果并不是很好,如果想限制瞬间连接数过大的恶意IP地址,可以考虑使用iptables的模块recent。

新版的iptables有个实用、简单又高效的功能,可以用它阻止瞬间连接数过多的源IP。这种阻挡功能在某些地方很受欢迎,比如说某大型讨论区网站,每个网页都有可能遭到无聊人士的连接,一瞬间太多的连接访问将导致服务器呈现呆滞状态。

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

这时,就需要用到下列三行指令,代码内容如下:

iptables -I INPUT -p tcp --dport 80 -m state --state NEW -m recent --name web --set

iptables -A INPUT -m recent --update --name web --seconds 60 --hitcount 20 -j LOG --log-prefix 'HTTP attack: '

iptables -A INPUT -m recent --update --name web --seconds 60 --hitcount 20 -j DROP

其中,要将SERVER_IP换成被攻击的服务器IP。

第一行:-I表示将本规则插入到INPUT链的最上头。什么样的规则呢?iptables判断只要是TCP性质的联机,目标端口是80并且目标IP是我们机器IP的联机,就可以将这个联机列入这份Web清单中。

第二行:-A表示将本规则附在INPUT链的最尾端。如果在60秒内,同一个来源连续产生了多个联机,则在到达第20个联机时,就对此联机留下Log记录,记录行将以HTTP attack开头。

第三行:-A表示将本规则附在INPUT链的最尾端。在与第二行条件相同的情况下,本次的动作则是将此连接给断掉,即将每60秒内有20个联机的数据包给DROP掉。

所以,这三行规则表示,我们允许一个客户端,每一分钟内可以接上服务器的20个新连接,具体数值可以由具体的生产环境来决定。这些规则也可以用在对Internet开放的其他应用服务上,例如Mail邮件服务器和DNS解析服务器。

为什么新版的iptables在阻挡上很有效率呢?因为在旧版的iptables中,并没有这些新模块功能,导致我们需要使用操作系统的Shell(比如netstat)接口,周期性地执行网络检查与拦阻动作。前者只动用到网络层的资源,而后者已经是应用层的大量(相对而言)运算。试想一下,服务器资源都已经被非法客户端给消耗殆尽了,哪还有余力周期性地呼叫软件层级的计算,来阻挡非法客户端呢?新版的iptables增加了此模块后就可以直接禁止掉恶意的IP,而不需要调用操作系统的Shell接口,所以更有效率。

接下来我们测试一下这个脚本的效果,步骤如下。

1)将这三句话写成脚本形式,方便执行操作(此测试机器的系统为CentOS 6.4 x86_64,IP为192.168.1.204),代码如下:

#!/bin/bash

iptables -I INPUT -p tcp --dport 80 -m state --state NEW -m recent --name web --set

iptables -A INPUT -m recent --update --name web --seconds 60 --hitcount 20 -j LOG --log-prefix 'HTTP attack: '

iptables -A INPUT -m recent --update --name web --seconds 60 --hitcount 20 -j DROP

执行后查看结果,显示如下:

Chain INPUT (policy DROP 1 packets, 284 bytes)

pkts bytes target prot opt in out source destination

0 0 tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 state NEW recent: SET name: web side: source

0 0 ACCEPT all -f * * 0.0.0.0/0 0.0.0.0/0 limit: avg 100/sec burst 100

999 43956 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x16/0x02 limit: avg 20/sec burst 200

0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0

204 14068 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED

1 44 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443,25,465,110,995,143,993,587,465,22

0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 recent: UPDATE seconds: 60 hit_count: 20 name: web side: source LOG flags 0 level 4 prefix `HTTP attack: '

0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 recent: UPDATE seconds: 60 hit_count: 20 name: web side: source

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)

pkts bytes target prot opt in out source destination

0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmp type 8 limit: avg 1/sec burst 10

Chain OUTPUT (policy ACCEPT 17 packets, 1596 bytes)

pkts bytes target prot opt in out source destination

0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0

2)在这台机器上开启Nginx或Apache服务,即开启80端口;在另一台IP为192.168.1.211的机器上运行Webbench压力测试工具,来模拟非法攻击,命令如下:

webbench -t 1000 –

c 500 http://192.168.1.204

Webbench - Simple Web Benchmark 1.5

Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.

Benchmarking: GET http://192.168.1.204/

500 clients, running 1000 sec.

3)观察结果可以得知,在相当长的时间内(即时间间隔为1000s的时间段内),IP地址为192.168.1.211的机器是访问不了192.168.1.204的Web服务的,只有过了这段压力测试的时间后,192.168.1.211的机器才能正常访问192.168.1.204的Web服务,证明脚本生效;还可以查看服务器的iptables日志,输入以下命令即可查看系统的最后100条日志(iptables日志默认是放在/var/log/messages里的):

tail –

n100 /var/log/messages

结果显示如下:

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=56870 DF PROTO=TCP SPT=40874 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=48892 DF PROTO=TCP SPT=40875 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=201 DF PROTO=TCP SPT=40876 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=6778 DF PROTO=TCP SPT=40877 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=42 DF PROTO=TCP SPT=40878 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=19679 DF PROTO=TCP SPT=40879 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=4841 DF PROTO=TCP SPT=40880 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=49662 DF PROTO=TCP SPT=40881 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=50257 DF PROTO=TCP SPT=40882 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

[root@fabric ~]# tail /var/log/messages

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=3805 DF PROTO=TCP SPT=40873 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=56870 DF PROTO=TCP SPT=40874 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=48892 DF PROTO=TCP SPT=40875 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=201 DF PROTO=TCP SPT=40876 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=6778 DF PROTO=TCP SPT=40877 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=42 DF PROTO=TCP SPT=40878 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=19679 DF PROTO=TCP SPT=40879 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=4841 DF PROTO=TCP SPT=40880 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=49662 DF PROTO=TCP SPT=40881 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

Oct 28 07:00:07 fabric kernel: HTTP attack: IN=eth0 OUT= MAC=00:16:3e:05:23:85:00:16:3e:0a:10:7a:08:00 SRC=192.168.1.211 DST=192.168.1.204 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=50257 DF PROTO=TCP SPT=40882 DPT=80 WINDOW=14480 RES=0x00 SYN URGP=0

我们监测到大量带有HTTP attack日志头的iptables日志,如果发现此IP重复数量非常之多,则直接用iptables-I命令将其禁止掉,省得它下次又重新发包攻击。

这里需要注意的是,iptables的recent模块功能虽然强大,但它并不适用于一些基于LVS+Keepalived的Linux集群环境,这是因为后端的Web都是通过前端的LVS负载均衡器来连接的,有时会遇到并发数比较大的情况,比如单位时间内的并发数超过2000,这时候用recent模块肯定是不行的,另外为了保证数据包转包的高效,在采用了LVS+Keepalived集群架构的机器上往往要关掉iptables防火墙。大家都知道,LVS/DR模式是基于公网地址的,现在SSH暴力破解工具比比皆是,我们又应该如何防止SSH暴力破解呢?