标签归档:ip_recent

Linux上iptables端口触发拦截

之前整过在RouterOS上异常的访问触发防火墙拦截ip地址访问,就一直想給VPS套上这种拦截策略,以提高安全性,拦截那些奇奇怪怪的扫描,最近偶然看到了iptables里面的一个模块——ip_recent。

这个模块现在已经改名了,叫做xt_recent,可以达到我所想要的目的,这里记录一下用法:

xt_recent

首先,检查一下模块的情况,用modinfo来看看模块的情况

root@ferrets:/proc/net/xt_recent# modinfo xt_recent
filename: /lib/modules/5.10.0-9-amd64/kernel/net/netfilter/xt_recent.ko
alias: ip6t_recent
alias: ipt_recent
license: GPL
description: Xtables: "recently-seen" host matching
author: Jan Engelhardt [email protected]
author: Patrick McHardy [email protected]
depends: x_tables
retpoline: Y
intree: Y
name: xt_recent
vermagic: 5.10.0-9-amd64 SMP mod_unload modversions
sig_id: PKCS#7
signer: Debian Secure Boot CA
sig_key: 4B:6E:F5:AB:CA:66:98:25:17:8E:05:2C:84:66:7C:CB:C0:53:1F:8C
sig_hashalgo: sha256
signature: 54:BB:49:31:44:96:65:97:63:67:BA:20:96:4A:85:29:C6:F2:0C:19:
69:FC:31:34:C7:1E:82:9C:13:90:80:E2:7C:9B:2E:46:1F:32:46:A3:
E0:29:55:01:E4:0E:24:5A:EE:67:C2:6D:45:16:ED:0A:51:AC:CE:A7:
66:F4:CE:3D:2E:F4:13:32:23:87:0C:A2:77:3D:72:99:96:CB:36:6E:
3C:43:15:52:8E:F5:59:31:1B:A1:4F:2D:B2:08:81:AC:F7:B3:0D:80:
D7:0E:DD:78:94:50:F9:8A:CA:3F:5C:6D:AB:4A:B9:E3:94:87:64:7F:
97:08:4F:4A:D3:7E:44:54:8F:F3:03:B8:A8:48:8E:5D:7C:5C:9F:FE:
4E:49:60:63:57:EC:62:57:0C:5C:9F:1F:36:FE:D3:E6:EF:F3:AB:C5:
D2:A4:0E:9C:B2:89:52:55:8A:1F:BF:92:DE:30:19:61:75:A6:22:BC:
A4:DD:2D:B7:8B:74:65:61:A6:4D:75:0E:9B:05:EB:33:79:46:88:13:
71:A3:3F:5C:4B:3C:11:85:EF:B0:F9:CD:45:DE:28:12:84:EB:D1:79:
32:38:19:D3:9F:55:7D:01:27:6C:A2:FB:96:18:7D:30:4E:F7:B4:4F:
33:DA:B6:5D:A2:F9:5E:B0:D2:17:4D:14:12:39:D7:00
parm: ip_list_tot:number of IPs to remember per list (uint)
parm: ip_list_hash_size:size of hash table used to look up IPs (uint)
parm: ip_list_perms:permissions on /proc/net/xt_recent/* files (uint)
parm: ip_list_uid:default owner of /proc/net/xt_recent/* files (uint)
parm: ip_list_gid:default owning group of /proc/net/xt_recent/* files (uint)
parm: ip_pkt_list_tot:number of packets per IP address to remember (max. 255) (uint)

xt_recent上记录ip地址和RouterOS的addresslist设定稍微有点不一样。xt_recent有个参数ip_list_tot,这里会指定单个列表中,能够记录的ip地址的最大的数量,只要列表没满,就会一直留在列表里面;而RouterOS的addresslist会有个timeout的设定,如果超时了就会自动从列表里面移除。这样就导致两者的记录和调用逻辑稍微有点不一样:

  • xt_recent是匹配策略就记录下ip,然后在拦截策略读取ip列表的时候再指定时间区间。
  • RouterOS是匹配的时候就定义一个timeout,然后拦截策略不需要考虑老旧数据的问题。

具体孰优孰劣这个不同人有不同看法,这里就不作太多比较。

要注意的是ip_list_tot默认大小是100,我个人感觉是不是非常够的,于是打算修改一下这个限制。

具体当前的值可以在/sys/module/xt_recent/parameters/ip_list_tot看到,直接用cat来读出来就行。

如果你也觉得默认的列表只有100的容量不是很够,可以参考下面的部分来修改ip_list_tot的值

首先把xt_recent这个mod卸载掉,如果出现提示说这个mod在用导致无法卸载的话,就先检查一下是不是iptables或者ip6tables已经存在调用,可以先把策略删掉,完了再加回来。

首先,把xt_recent停掉。

modprobe -r xt_recent

然后,在/etc/modprobe.d/下面新增一个xt_recent.conf,内容如下:

options xt_recent ip_list_tot=8192

新增完毕之后,再重新加载xt_recent

modprobe xt_recent

最后,检查一下是否已经生效

cat /sys/module/xt_recent/parameters/ip_list_tot

完毕之后,就可以着手开始调整iptables了。

iptables

设计思路可以参考之前RouterOS的部分,但是要作一些修改,因为拦截两种坏东西的时长是不一样的,在Linux上要拆分成两个list,所以,iptables里面INPUT chain可以这样设计:

  1. 允许RELATED,ESTABLISHED
  2. 允许受信任的源
  3. 拦截坏东西的ip地址
  4. 拦截未知访问的ip地址
  5. 标记扫描端口的坏东西的ip地址
  6. 放通正常的服务
  7. 标记其他未知访问的ip地址
  8. INPUT chain默认行为是DROP

这里拿未知访问的来做例子:

# 4.拦截未知访问的ip地址
iptables -A INPUT -m recent --update --seconds 86400 --name UnknownConnection --rsource -j DROP
……
……
……
# 7.标记其他未知访问的ip地址
iptables -A INPUT -m recent --set --name UnknownConnection --rsource -j DROP

这里简单介绍一下几个参数:

-A INPUT :这个策略添加在INPUT chain中
-j DROP :跳转至DROP,即直接丢弃包,不做任何回应
-m recent :调用xt_recent模块
--update :更新最后一次见到的时间
--seconds 86400:指定只检查86400秒就是24小时内的部分,这里的单位是秒
--name UnknownConnection :指定检查名称为UnknownConnection列表
--rsource :指定为源地址匹配
--set :将地址添加到列表中

其他用法的话,这里有篇文章,讲述的比较详细,可以作为参考。

配上之后,可以在/proc/net/xt_recent/文件夹里面看到所有的列表,可以直接用cat或者less等工具来读取。

列表里面的内容

结束

从此,服务器的安全性得到了一定的提升,至少能挡一下扫描什么的了。至于说WAF什么的……先靠Cloudflare吧。

哦,对了,ip6tables可以用一样的方法来加强抗扫描的能力。

追加1

上了这个拦截之后,发现邮箱被jetpack提醒网站下线的邮件填满了。花了一段时间检查之后,终于发现之前放通的部分是使用了ctstate NEW+limit这种,导致无法匹配到tcp reset的包,最后发来reset包的cloudflare服务器就被当作是坏家伙而屏蔽了。加上允许reset包的策略就可以解决这个问题。

iptables -A INPUT -p tcp -m tcp --tcp-flags RST,PSH,ACK RST -m limit --limit 64/sec -j ACCEPT

追加2

如果需要手动操作清单里面的ip地址,可以直接用echo来添加和删除:例如

echo +10.10.10.10 > UnknownConnection #将10.10.10.10添加到列表中
echo -10.10.10.10 > UnknownConnection #将10.10.10.10从列表中移除
echo / > UnknownConnection #清空整个列表