Решил поделиться скриптом, который является мини аналогом известного fail2ban. Использую его на маленьких проектах. Логика простая 1) Скрипт читает логи (/var/log/auth.log). 2) Если у IP слишком много неудачных попыток входа — блокирует его через iptables или ufw 3) White-list (список IP, которые никогда не банятся). 4) Авторазбан через заданное время (например, 1 час). Всё это будет работать на Python 3.9 и под управлением Debian 12
#!/usr/bin/env python3
import re
import subprocess
import json
from datetime import datetime, timedelta
# -------------------
# Настройки
# -------------------
LOG_FILE = "/var/log/auth.log" # путь к логам SSH
STATE_FILE = "banned_state.json" # база забаненных IP с временем
MAX_ATTEMPTS = 5 # сколько неудачных попыток до блокировки
BAN_TIME = 60 * 60 # время бана (в секундах) - 1 час
USE_UFW = True # True - ufw, False - iptables
# Белый список IP
WHITE_LIST = {"127.0.0.1", "192.168.0.1"}
# -------------------
# Работа с состоянием
# -------------------
def load_state():
try:
with open(STATE_FILE, "r") as f:
return json.load(f)
except FileNotFoundError:
return {}
def save_state(state):
with open(STATE_FILE, "w") as f:
json.dump(state, f)
# -------------------
# Поиск атакующих IP
# -------------------
def parse_failed_attempts():
failed_ips = {}
pattern = re.compile(r"Failed password.*from (\d+\.\d+\.\d+\.\d+)")
with open(LOG_FILE, "r") as f:
for line in f:
match = pattern.search(line)
if match:
ip = match.group(1)
failed_ips[ip] = failed_ips.get(ip, 0) + 1
return failed_ips
# -------------------
# Бан / Разбан IP
# -------------------
def ban_ip(ip):
print(f"Блокирую IP: {ip}")
if USE_UFW:
subprocess.run(["ufw", "deny", "from", ip], check=False)
else:
subprocess.run(["iptables", "-A", "INPUT", "-s", ip, "-j", "DROP"], check=False)
def unban_ip(ip):
print(f"Разбан IP: {ip}")
if USE_UFW:
subprocess.run(["ufw", "delete", "deny", "from", ip], check=False)
else:
subprocess.run(["iptables", "-D", "INPUT", "-s", ip, "-j", "DROP"], check=False)
# -------------------
# Основная логика
# -------------------
def main():
state = load_state()
failed_ips = parse_failed_attempts()
now = datetime.now()
changed = False
# Проверяем новые атаки
for ip, count in failed_ips.items():
if ip in WHITE_LIST:
continue # никогда не баним белые IP
if count >= MAX_ATTEMPTS and ip not in state:
ban_ip(ip)
state[ip] = (now + timedelta(seconds=BAN_TIME)).isoformat()
print(f"[{now}] IP {ip} заблокирован (попыток: {count})")
changed = True
# Проверяем срок действия бана
to_unban = []
for ip, until_str in state.items():
until = datetime.fromisoformat(until_str)
if now >= until:
unban_ip(ip)
to_unban.append(ip)
changed = True
for ip in to_unban:
del state[ip]
if changed:
save_state(state)
if __name__ == "__main__":
main()
Белый список (WHITE_LIST): туда можно добавить свои IP. Авторазбан через BAN_TIME (по умолчанию 1 час). Состояние хранится в banned_state.json. Работает как с ufw, так и с iptables (выбирается через USE_UFW). Обычно на Deb ставят ufw, поэтому оставляем как есть
Осталось добавить в crontab -e, лучше проверять каждые 10 минут
*/10 * * * * /usr/bin/python3 /path/to/firewall_autoblocker.py
Комментарии (0)
Оставить комментарий
Пока нет комментариев. Будьте первым!