任务:扫描apache2服务器的access.log,找出恶意访问的ip,将其加入黑名单,禁止访问。
工具:python ;ipset;crontab
1、设置ipset
ipset 是可以存储一个地址集合
安装:
$ sudo apt-get install ipset
让我通过简单的示例告诉你该如何使用ipset命令。
首先,让我们创建一条新的IP集,名为banthis(名字任意):
$ sudo ipset create banthis hash:net
第二个参数(hash:net)是必须的,代表的是集合的类型。IP集有多个类型。hash:net类型的IP集使用哈希来存储多个CIDR块。如果你想要在一个集合中存储单独的IP地址,你可以使用hash:ip类型。
一旦创建了一个IP集之后,你可以用下面的命令来检查:
$ sudo ipset list
image
这显示了一个可用的IP集合列表,并有包含了集合成员的详细信息。默认上,每个IP集合可以包含65536个元素(这里是CIDR块)。你可以通过追加"maxelem N"选项来增加限制。
$ sudo ipset create banthis hash:net maxelem 1000000
现在让我们来增加IP块到这个集合中:
$ sudo ipset add banthis 1.1.1.1/32
$ sudo ipset add banthis 1.1.2.0/24
$ sudo ipset add banthis 1.1.3.0/24
$ sudo ipset add banthis 1.1.4.10/24
你会看到集合成员已经改变了。
$ sudo ipset list
image
现在是时候去创建一个使用IP集的iptables规则了。这里的关键是使用"-m set --match-set "选项。
现在让我们创建一条让之前那些IP块不能通过80端口访问web服务的iptable规则。可以通过下面的命令:
屏蔽80端口
$ sudo iptables -I INPUT -m set --match-set banthis src -p tcp --destination-port 80 -j DROP
屏蔽443端口
$ sudo iptables -I INPUT -m set --match-set banthis src -p tcp --destination-port 443 -j DROP
ipset 设置完毕!
2、编写扫描脚本
扫描日志,取出日志里面的访问IP地址
import re
import gzip
import os
badrequest=[' *******'] #恶意访问请求的特征文本
def scan_apache_gzip_log(filename): #扫描压缩日志
iplist=set()
f=gzip.open(filename,'r')
for eachline in f:
eachline=eachline.decode('utf-8')
s=re.finditer('^\d+\.\d+\.\d+\.\d+',eachline)#找出ip
for s in s:
ip=s.group()
for item in badrequest: #匹配恶意请求文本
if(eachline.find(item)>0):
iplist.add(ip)
f.close()
return iplist
def scan_apache_log(filename): #扫描当天日志
iplist=set()
f=open(filename,'r')
for eachline in f:
s=re.finditer('^\d+\.\d+\.\d+\.\d+',eachline)
for s in s:
ip=s.group()
for item in badrequest:
if(eachline.find(item)>0):
iplist.add(ip)
f.close()
return iplist
def insert_into_ipset(iplist):
if(len(iplist)>0):
for item in iplist:
os.system('/sbin/ipset add banthis '+item)
if __name__=='__main__':
apachelog="**/apache2/access.log" #log文件地址
iplist=scan_apache_log(apachelog)
insert_into_ipset(iplist)
3、定时执行脚本
$sudo crontab -u root -e
进入 crontab 编辑界面。会打开Vim编辑你的任务
- 执行的任务
这个文件中是通过 5 个“”来确定命令或任务的执行时间的,这 5 个“”的具体含义下所示。
crontab 时间表示
项目含义范围
第一个"*"一小时当中的第几分钟(minute)0~59
第二个"*"一天当中的第几小时(hour)0~23
第三个"*"一个月当中的第几天(day)1~31
第四个"*"一年当中的第几个月(month)1~12
第五个"*"一周当中的星期几(week)0~7(0和7都代表星期日)
在时间表示中,还有一些特殊符号需要学习,如下所示。
时间特殊符号
特殊符号含义
(星号)代表任何时间。比如第一个""就代表一小时种每分钟都执行一次的意思。
,(逗号)代表不连续的时间。比如"0 8,12,16***命令"就代表在每天的 8 点 0 分、12 点 0 分、16 点 0 分都执行一次命令。
-(中杠)代表连续的时间范围。比如"0 5 ** 1-6命令",代表在周一到周六的凌晨 5 点 0 分执行命令。
/(正斜线)代表每隔多久执行一次。比如"*/10****命令",代表每隔 10 分钟就执行一次命令。
当“crontab -e”编辑完成之后,一旦保存退出,那么这个定时任务实际就会写入 /var/spool/cron/ 目录中,每个用户的定时任务用自己的用户名进行区分。而且 crontab 命令只要保存就会生效,只要 crond 服务是启动的。知道了这 5 个时间字段的含义,我们多举几个时间的例子来熟悉一下时间字段,如下所示。
crontab举例时间
含义45 22 ***命令在 22 点 45 分执行命令
0 17 ** 1命令在每周一的 17 点 0 分执行命令
0 5 1,15**命令在每月 1 日和 15 日的凌晨 5 点 0 分执行命令
40 4 ** 1-5命令在每周一到周五的凌晨 4 点 40 分执行命令
*/10 4 ***命令在每天的凌晨 4 点,每隔 10 分钟执行一次命令
0 0 1,15 * 1命令在每月 1 日和 15 日,每周一个 0 点 0 分都会执行命令,
注意:星期几和几日最好不要同时出现,因为它们定义的都是天,非常容易让管理员混淆
我们设置为:
*/1 * * * * /etc/python36/python /XXXX我们的脚本地址
含义是每分钟执行一次脚本,扫描出恶意的IP,加入黑名单中。
使用crontab时要注意path(环境)设置,否则脚本不能完整执行。下面就是我碰到的问题:
在python脚本中用到了os.system("ipset add blacklist 12.2.2.X") 命令,该脚本手动执行时运行成功,但使用crontab定时任务来运行脚本,os.system()里面的命令无法执行。
os.system()里的命令需要写成绝对路径,否则crontab找不到该命令,就不会执行。用 $ whereis ipset 查找ipset 的绝对路径,是”/sbin/ipset“,改成os.system("/sbin/ipset add blacklist 12.2.2.X") ,命令成功执行。
网友评论