[linux] 根据日志文件ban掉ip地址

搬家之后就没有公网ip地址了,所以在阿里云买了一个服务器,带上优惠160买了三年,流量计费的服务器。并且配置nps用来实现内网穿透。

某天发现阿里云的流量计费每隔一段时间扣0.01元,很小的费用,但是我想追究一下为什么会有流量费

于是发现,Nps的日志中不停的有新的tcp连接,去看了内网的ssh发现有人爆破我的ssh
image

其实现有的项目有能实现类似功能,比如Fail2ban项目,但是我这个ssh是通过内网穿透出去的,内网的机器没办法知道访问者的实际ip地址,所以这个事情就只能在服务器上实现。

原先的思路就是通过判断tcp连接频率实现过滤,但是发现防火墙配置这个非常麻烦,所以让ai写了个脚本帮我分析nps的日志文件提取出现频次比较高的ip地址,然后屏蔽掉。

import re
from datetime import datetime, timedelta
from collections import defaultdict
import sys
import logging

# 配置日志
logging.basicConfig(filename='/var/log/ufw_ban.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def parse_log_line(line):
    """解析日志行,提取日期时间和 IP 地址"""
    pattern = r'(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}\.\d{3}) \[D\] \[tcp\.go:42\]  new tcp connection,local port \d+,client \d+,remote address ([\d\.]+):\d+'
    match = re.search(pattern, line)
    if match:
        return match.group(1), match.group(2)
    return None, None

def block_ip_with_ufw(ip):
    """使用ufw阻止IP地址"""
    command = f"ufw deny from {ip}"
    try:
        import subprocess
        subprocess.run(command, check=True, shell=True)
        logging.info(f"Blocked IP {ip} with ufw")  # 记录日志
        print(f"Blocked IP {ip} with ufw")
    except subprocess.CalledProcessError as e:
        logging.error(f"Failed to block IP {ip} with ufw: {e}")  # 记录错误日志
        print(f"Failed to block IP {ip} with ufw: {e}")

def analyze_log(file_path):
    """分析日志文件,统计最近一小时内每小时内每10分钟的连接次数,并阻止超过10次的IP地址"""
    one_hour_ago = datetime.now() - timedelta(hours=1)
    ip_count = defaultdict(int)

    # 打开文件并按行倒序处理
    with open(file_path, 'r') as file:
        lines = file.readlines()  # 读取所有行
        for line in reversed(lines):  # 倒序处理
            date_str, remote_ip = parse_log_line(line)
            if date_str and remote_ip:
                current_time = datetime.strptime(date_str, '%Y/%m/%d %H:%M:%S.%f')
                if current_time > one_hour_ago:  # 只考虑最近一小时内的数据
                    ip_count[remote_ip] += 1
                else:
                    break  # 超出时间范围,停止处理

    # 阻止超过10次连接的IP地址
    for ip, count in ip_count.items():
        if count > 10:
            block_ip_with_ufw(ip)

def main():
    if len(sys.argv) != 2:
        print("Usage: python script.py <log_file_path>")
        sys.exit(1)

    log_file_path = sys.argv[1]  # 从命令行参数获取日志文件路径
    analyze_log(log_file_path)

if __name__ == "__main__":
    main()

然后通过cron实现每小时运行0 * * * * /usr/bin/python3 /var/log/main.py /var/log/nps.log,上面的脚本会每小时运行一次,分析一小时内,连接超过十次的ip地址

运行一个晚上的结果如下

2024-11-19 17:00:01,628 - INFO - Blocked IP 219.232.6.42 with ufw
2024-11-19 19:00:02,305 - INFO - Blocked IP 185.182.185.226 with ufw
2024-11-20 02:00:02,192 - INFO - Blocked IP 117.156.229.133 with ufw
2024-11-20 06:00:01,380 - INFO - Blocked IP 121.17.100.14 with ufw
2024-11-20 07:00:02,116 - INFO - Blocked IP 172.236.192.229 with ufw
2024-11-20 09:00:02,030 - INFO - Blocked IP 38.242.154.175 with ufw

这就像是蜘蛛通过蛛网捕食一样,莫名的好玩

posted @ 2024-11-20 15:12  Startu  阅读(1)  评论(0编辑  收藏  举报