之前整过在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 jengelh@medozas.de
author: Patrick McHardy kaber@trash.net
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可以这样设计:
- 允许RELATED,ESTABLISHED
- 允许受信任的源
- 拦截坏东西的ip地址
- 拦截未知访问的ip地址
- 标记扫描端口的坏东西的ip地址
- 放通正常的服务
- 标记其他未知访问的ip地址
- 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 #清空整个列表