[linux] 根据日志文件ban掉ip地址
搬家之后就没有公网ip地址了,所以在阿里云买了一个服务器,带上优惠160买了三年,流量计费的服务器。并且配置nps用来实现内网穿透。
某天发现阿里云的流量计费每隔一段时间扣0.01元,很小的费用,但是我想追究一下为什么会有流量费
于是发现,Nps的日志中不停的有新的tcp连接,去看了内网的ssh发现有人爆破我的ssh
其实现有的项目有能实现类似功能,比如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
这就像是蜘蛛通过蛛网捕食一样,莫名的好玩