Linux自动banip脚本(2)

Linux自动banip脚本(2)

上一篇文章讲解了
re模块
subprocess模块

接下来我们正式开始我们的项目脚本代码的编写

首先我们来回顾一下

Linux的日志分析需要查看的日志文件(属于应急响应必须掌握的部分)
/var/log/cron 记录系统的定时任务
/var/log/cups 打印信息的日志
/var/log/message 记录系统重要信息的日志
/var/log/btmp 登录失败
/var/log/lastlog 最后一次登录
/var/log/wtmp 成功登录记录
/var/log/secure 登录日志(包括登录成功以及失败)(我们的项目脚本就是围绕着这个日志展开)
/var/log/utmp 目前登录用户的信息

我们来查看一下/var/log/secure 里的内容

Jul  8 00:07:38 centos7 sshd[2498]: Failed password for root from 192.168.3.100 port 60154 ssh2
Jul  8 00:07:38 centos7 sshd[2499]: Failed password for root from 192.168.3.100 port 60174 ssh2
Jul  8 00:07:38 centos7 sshd[2498]: Connection closed by 192.168.3.100 port 60154 [preauth]
Jul  8 00:07:38 centos7 sshd[2499]: Connection closed by 192.168.3.100 port 60174 [preauth]
Jul  8 00:07:38 centos7 sshd[2501]: Failed password for root from 192.168.3.100 port 60194 ssh2
Jul  8 00:07:38 centos7 sshd[2497]: Failed password for root from 192.168.3.100 port 60162 ssh2
Jul  8 00:07:38 centos7 sshd[2501]: Connection closed by 192.168.3.100 port 60194 [preauth]
Jul  8 00:07:38 centos7 sshd[2497]: Connection closed by 192.168.3.100 port 60162 [preauth]
Jul  8 00:28:05 centos7 sshd[2752]: Invalid user r from 192.168.3.100 port 40946
Jul  8 00:28:05 centos7 sshd[2752]: input_userauth_request: invalid user r [preauth]
Jul  8 00:28:05 centos7 sshd[2752]: Received disconnect from 192.168.3.100 port 40946:11: Bye Bye [preauth]
Jul  8 00:28:05 centos7 sshd[2752]: Disconnected from 192.168.3.100 port 40946 [preauth]
Jul  8 00:28:05 centos7 sshd[2755]: Invalid user r from 192.168.3.100 port 40954
Jul  8 00:28:05 centos7 sshd[2755]: input_userauth_request: invalid user r [preauth]
Jul  8 00:28:05 centos7 sshd[2754]: Invalid user r from 192.168.3.100 port 40952
Jul  8 00:28:05 centos7 sshd[2754]: input_userauth_request: invalid user r [preauth]
Jul  8 00:28:05 centos7 sshd[2755]: pam_unix(sshd:auth): check pass; user unknown
Jul  8 00:28:05 centos7 sshd[2755]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.3.100
Jul  8 00:28:05 centos7 sshd[2758]: Invalid user r from 192.168.3.100 port 41004
Jul  8 00:28:05 centos7 sshd[2758]: input_userauth_request: invalid user r [preauth]
Jul  8 00:28:05 centos7 sshd[2754]: pam_unix(sshd:auth): check pass; user unknown
Jul  8 00:28:05 centos7 sshd[2754]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.3.100
Jul  8 00:28:05 centos7 sshd[2758]: pam_unix(sshd:auth): check pass; user unknown
Jul  8 00:28:05 centos7 sshd[2758]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.3.100
Jul  8 00:28:05 centos7 sshd[2757]: Invalid user r from 192.168.3.100 port 40990
Jul  8 00:28:05 centos7 sshd[2757]: input_userauth_request: invalid user r [preauth]
Jul  8 00:28:05 centos7 sshd[2757]: pam_unix(sshd:auth): check pass; user unknown
Jul  8 00:28:05 centos7 sshd[2757]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.3.100
Jul  8 00:28:05 centos7 sshd[2756]: Invalid user r from 192.168.3.100 port 40980
Jul  8 00:28:05 centos7 sshd[2756]: input_userauth_request: invalid user r [preauth]
Jul  8 00:28:05 centos7 sshd[2756]: pam_unix(sshd:auth): check pass; user unknown
Jul  8 00:28:05 centos7 sshd[2756]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.3.100
Jul  8 00:28:07 centos7 sshd[2755]: Failed password for invalid user r from 192.168.3.100 port 40954 ssh2
Jul  8 00:28:07 centos7 sshd[2754]: Failed password for invalid user r from 192.168.3.100 port 40952 ssh2
Jul  8 00:28:07 centos7 sshd[2758]: Failed password for invalid user r from 192.168.3.100 port 41004 ssh2
Jul  8 00:28:07 centos7 sshd[2757]: Failed password for invalid user r from 192.168.3.100 port 40990 ssh2
Jul  8 00:28:07 centos7 sshd[2754]: Connection closed by 192.168.3.100 port 40952 [preauth]
Jul  8 00:28:07 centos7 sshd[2755]: Connection closed by 192.168.3.100 port 40954 [preauth]
Jul  8 00:28:07 centos7 sshd[2756]: Failed password for invalid user r from 192.168.3.100 port 40980 ssh2
Jul  8 00:28:07 centos7 sshd[2758]: Connection closed by 192.168.3.100 port 41004 [preauth]
Jul  8 00:28:07 centos7 sshd[2757]: Connection closed by 192.168.3.100 port 40990 [preauth]
Jul  8 00:28:07 centos7 sshd[2756]: Connection closed by 192.168.3.100 port 40980 [preauth]

可以看到里面有:

登录成功 Accepted password for root from 192.168.3.100 port 60186 ssh2
登录失败 Failed password for root from 192.168.3.100 port 60154 ssh2
没有这个用户 Invalid user r from 192.168.3.100 port 40990

我们可以设置一个阈值,超过这个阈值就对这些没有登录成功的ip进行封禁

封禁可以使用黑名单:
hosts黑名单 /etc/hosts.deny
hosts白名单 /etc/hosts.allow

配置格式
服务:地址:允许/封禁
服务:
ssh ftp smb telnet 关键字(all)禁止or运行所有服务
all:192.168.0.10:deny(全封)
all:192.168.0.10:allow(加白)

以上的deny以及allow的可以省略

地址:
192.168.0.10
192.168.0.10/24(整个C段封掉)
192.168.0.*(整个C段封掉)
192.168.0..(整个C段封掉)

Linux常用查询命令:
find
grep
awk
sed
cat
tail
head

小案例
从第10行开始,显示5行,也就是说显示10~14行
cat /etc/passwd | tail -n +10 | head -n 5

只显示/etc/passwd下的账户
cat /etc/passwd | awk -F ':' '{print $1}'

在/var/log/secure中定位有多少个ip在爆破主机的root账号(主要查看root账户)
grep "Failed password for root" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -nr
登录成功的ip有哪些
grep "Accepted" /var/log/secure | awk '{print $11}' | uniq -c | sort -nr

怎么实现暴力破解自动阻断的具体步骤:
1、打开安全日志( /var/log/secure)
2、对安全日志进行实时监控(tail -f)
3、解析日志每一行的内容,找出正在爆破的ip
4、设置一个阈值,超过阈值之后,直接封禁(把ip放入黑名单中)

出现Invalid 说明:这个用户都不存在

Invalid user r from 192.168.3.100 port 40946

出现Failed 说明:这个用户存在,但是密码错误

Failed password for root from 192.168.3.100 port 60154 ssh2

具体的代码示例如下:

#!/usr/bin/env python3

import re
import subprocess
import time

#要实时监控的安全日志文件
logFile = '/var/log/secure'
#要设置的黑名单
blackList = '/etc/hosts.deny'
#封禁的阈值
num = 3

#获取已经加入黑名单的ip,然后转换为字典
def getDenies():
    deniesDict = {}
    with open(blackList) as f:
        blacklist = f.readlines()
        for ip in blacklist:
            group = re.search(r'(\d+.\d+.\d+.\d+)',ip)
            if group:
                #给黑名单ip做一个标记
                deniesDict[group[1]] = '1'
        return deniesDict

#监控日志的方法
def monitorLog():
    #已经拉黑的ip
    deniesDict = getDenies()
    #ip错误次数字典
    tempIP = {}
    #开始监控
    while True:
        #读取安全日志信息
        log_infor = subprocess.Popen('tail -f {}'.format(logFile),stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
        #挂起1秒钟,避免速度过快
        time.sleep(0.1)
        #逐行分析
        log_line_info = log_infor.stdout.readline().strip()
        if log_line_info:
            group = re.search(r'Invalid user \w+ from (\d+.\d+.\d+.\d+)',str(log_line_info))
            #不存在的用户直接进行封禁
            if group and not deniesDict.get(group[1]):
                subprocess.getoutput('echo "sshd:{}" >> {}'.format(group[1],blackList))
                deniesDict[group[1]] = '1'
                time_str = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
                print('{} -- add ip:{} to hosts.deny for Invalid user'.format(time_str,group[1]))
                continue
        
        #用户存在但是密码错误
        group = re.search(r'Failed password for \w+ from (\d+.\d+.\d+.\d+)',str(log_line_info))
        if group and not deniesDict.get(group[1]):
            ip = group[1]
            #统计ip错误次数
            if not tempIP.get(ip):
                tempIP[ip] = 1
            else:
                tempIP[ip] = tempIP[ip] + 1
            #如果错误次数大于阈值直接封禁
            if tempIP[ip] > num:
                del tempIP[ip]
                subprocess.getoutput('echo "sshd:{}" >> {}'.format(group[1],blackList))
                deniesDict[group[1]] = '1'
                time_str = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
                print('{} -- add ip:{} to hosts.deny for wrong password'.format(time_str,group[1]))

if __name__ == '__main__':
    monitorLog()
posted on 2025-07-08 14:24  burgess0x  阅读(9)  评论(0)    收藏  举报