python学习之监控centos中的安全日志,配置黑名单

#! /usr/bin/env python3
import time
import re
import subprocess

Logfile = '/var/log/secure'  #安全日志
hostsDeny = '/etc/hosts.deny'  #黑名单

passwrod_wrong = 2


#读取hostsDeny
'''
读取每行的内容,从中把对应的IP地址放到字典openHostsDeny:key是IP,value是1,返回对应的字典
'''
def getDenies():
    openHostsDeny = {}
    list= open(hostsDeny).readlines()
    for ip in list:
        group = re.search(r'(\d+\.\d+\.\d+\.\d+)',ip)
        if group:
            openHostsDeny[group[1]] = '1'
    return openHostsDeny

#监控
def monitorLog(Logfile):
    tempIp ={}
    openHostsDeny = getDenies()
    '''
subprocess.Popen() 是 Python 中用於執行外部命令的函數。
'tail -f ' + Logfile 是要執行的外部命令。tail 是一個 Unix/Linux 命令,通常用於查看文件的末尾幾行,而 -f 參數表示追蹤(follow),會持續監聽文件的新增內容。Logfile 變量包含了指定的日誌文件路徑。
stdout=subprocess.PIPE 和 stderr=subprocess.PIPE 表示將子進程的標準輸出和標準錯誤輸出分別導向到管道中。這兩個參數確保了可以捕獲外部命令的輸出(stdout)和錯誤信息(stderr)。
shell=True 表示命令會在 shell 中執行,這樣就可以使用命令行中的特性(例如 tail -f)。
總體而言,這行程式碼的作用是通過 Python 執行一個 tail -f 命令,持續監聽指定的日誌文件 (Logfile),並通過管道捕獲該命令的輸出和錯誤,使程式可以實時讀取並處理日誌文件中的新內容。
    '''
    openFile = subprocess.Popen('tail -f ' +Logfile,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
    while True:
        time.sleep(0.3)
        # strip() 方法用於移除字符串中的開頭和末尾的空白字符(比如空格、換行符等)
        line = openFile.stdout.readline().strip()
        if line:
            # \w+ 表示匹配一個或多個字母、數字或底線字符。
            group = re.search('Invalid user \w+ from (\d+\.\d+\.\d+\.\d+)',str(line))
            # group:这是一个之前通过正则表达式搜索后得到的匹配对象。在 Python 中,如果 re.search() 找到了符合模式的文本,它会返回一个匹配对象;否则返回 None。这个条件 group 检查是否有匹配对象。
            # not openHostsDeny.get(group[1]):这部分包含了另一个条件。openHostsDeny 是一个字典对象。
            # openHostsDeny.get(group[1]) 表示尝试从字典 openHostsDeny 中获取一个键为 group[1] 的值。group[1] 包含了在正则表达式中匹配的 IP 地址。
            if group and not openHostsDeny.get(group[1]):
                # subprocess.getoutput() 是 Python 中用于执行外部命令并获取输出结果的函数。
                # 'echo \'sshd:{}\' >> {}'.format(group[1], hostsDeny) 是一个命令字符串。它使用 format() 方法将两个参数 group[1] 和 hostsDeny 的值插入到字符串中。
                # group[1] 是之前正则表达式匹配得到的 IP 地址,而 hostsDeny 是一个文件路径,用于指定要追加内容的文件。
                # 在这个命令中,echo 是一个常见的命令,用于在终端输出指定的文本内容。\'sshd:{}\' 是要输出的文本,其中 {} 会被 group[1] 的值替换,>> 表示将输出内容追加到文件末尾。
                # 这行代码的作用是将 sshd:IP地址 的文本内容(其中 IP地址 是之前匹配得到的特定 IP 地址)追加到名为 hostsDeny 的文件中。通常情况下,
                # 此类操作会将特定的 IP 地址加入到一个文件中,例如将 IP 地址加入到阻止访问的黑名单中。
                subprocess.getoutput('echo \'sshd:{}\' >> {}'.format(group[1],hostsDeny))
                openHostsDeny[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('Failed password for \w+ from (\d+\.\d+\.\d+\.\d+)',str(line))
            if group:
                ip = group[1]
                # 统计id出现的次数
                if not tempIp.get(ip):
                    tempIp[ip]=1
                else:
                    tempIp[ip] = tempIp[ip]+1
                
                if tempIp [ip]>passwrod_wrong and not openHostsDeny.get(ip):
                    del tempIp[ip]
                    subprocess.getoutput('echo \'sshd:{}\' >> {}'.format(ip,hostsDeny))
                    openHostsDeny[ip] = '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]))

if __name__ == '__main__':
    monitorLog(Logfile)

你可能感兴趣的:(python,linux,python,centos,linux黑名单)