是的,可以通过脚本自动封禁SSH攻击IP,以下是几种常见的实现方法:

基于日志分析的Shell脚本
#!/bin/bash
# 分析SSH日志,封禁多次失败的IP
# 阈值设置
MAX_ATTEMPTS=5
LOG_FILE="/var/log/auth.log"
# 或使用 /var/log/secure (CentOS/RHEL)
# 获取失败次数超过阈值的IP
FAILED_IPS=$(grep "Failed password" $LOG_FILE | \
awk '{print $(NF-3)}' | \
sort | uniq -c | \
awk -v limit=$MAX_ATTEMPTS '$1 > limit {print $2}')
# 封禁IP
for IP in $FAILED_IPS; do
# 检查是否已封禁
if ! iptables -L INPUT -n | grep -q "$IP"; then
iptables -A INPUT -s $IP -j DROP
echo "[$(date)] 封禁IP: $IP" >> /var/log/autoblock.log
fi
done
使用fail2ban(推荐)
# fail2ban配置文件 /etc/fail2ban/jail.local [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 5 bantime = 3600 findtime = 600
实时监控脚本(含解封机制)
#!/bin/bash
# 实时监控并自动封禁/解封
while true; do
# 封禁逻辑
tail -n0 -F /var/log/auth.log | while read line; do
if echo "$line" | grep -q "Failed password"; then
IP=$(echo "$line" | grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
COUNT=$(grep "Failed password.*$IP" /var/log/auth.log | wc -l)
if [ $COUNT -ge 5 ]; then
iptables -C INPUT -s $IP -j DROP 2>/dev/null || \
iptables -A INPUT -s $IP -j DROP
echo "[$(date)] 自动封禁IP: $IP (失败$COUNT次)"
fi
fi
done
sleep 1
done
高级功能脚本
#!/usr/bin/env python3
"""
高级SSH攻击防护脚本
功能:自动封禁、解封、发送告警
"""
import re
import subprocess
import time
from collections import defaultdict
from datetime import datetime, timedelta
class SSHBlocker:
def __init__(self, max_attempts=5, ban_time=3600):
self.max_attempts = max_attempts
self.ban_time = ban_time
self.failed_attempts = defaultdict(list)
def parse_logs(self):
"""解析SSH日志"""
try:
with open('/var/log/auth.log', 'r') as f:
for line in f.readlines()[-1000:]: # 只读取最后1000行
if 'Failed password' in line:
ip_match = re.search(r'\d+\.\d+\.\d+\.\d+', line)
if ip_match:
ip = ip_match.group()
self.failed_attempts[ip].append(datetime.now())
except FileNotFoundError:
# 尝试其他日志路径
pass
def block_ip(self, ip):
"""封禁IP"""
try:
subprocess.run(['iptables', '-A', 'INPUT', '-s', ip, '-j', 'DROP'],
check=True)
print(f"[{datetime.now()}] 封禁IP: {ip}")
self.send_alert(f"SSH攻击防护: 已封禁IP {ip}")
except Exception as e:
print(f"封禁失败 {ip}: {e}")
def unblock_ip(self, ip):
"""解封IP"""
try:
subprocess.run(['iptables', '-D', 'INPUT', '-s', ip, '-j', 'DROP'],
check=True)
print(f"[{datetime.now()}] 解封IP: {ip}")
except:
pass
def send_alert(self, message):
"""发送告警(可替换为邮件、钉钉等)"""
# 这里可以集成告警系统
print(f"告警: {message}")
def run_check(self):
"""执行安全检查"""
self.parse_logs()
now = datetime.now()
for ip, attempts in list(self.failed_attempts.items()):
# 清理过期记录
valid_attempts = [t for t in attempts if now - t < timedelta(hours=1)]
self.failed_attempts[ip] = valid_attempts
if len(valid_attempts) >= self.max_attempts:
self.block_ip(ip)
if __name__ == "__main__":
blocker = SSHBlocker()
# 每60秒检查一次
while True:
blocker.run_check()
time.sleep(60)
使用方法
- 基本脚本:
chmod +x autoblock.sh ./autoblock.sh
添加到crontab定期执行
crontab -e /5 * /path/to/autoblock.sh
2. **fail2ban**(最推荐):
```bash
# Ubuntu/Debian
apt install fail2ban
systemctl enable fail2ban
systemctl start fail2ban
# CentOS/RHEL
yum install fail2ban
systemctl enable fail2ban
systemctl start fail2ban
- 高级脚本:
chmod +x ssh_blocker.py nohup python3 ssh_blocker.py &
注意事项
- 白名单设置:避免误封自己的IP
- 日志轮转:注意日志文件可能被切割
- 权限问题:需要root权限运行封禁命令
- 持久化:iptables规则重启后会丢失,建议保存规则
- 性能影响:避免频繁读取大日志文件
最佳实践
- 优先使用fail2ban:成熟稳定,配置灵活
- 设置合理阈值:5次失败/10分钟内比较合理
- 永久封禁+自动解封:根据IP reputation动态调整
- 多维度防护:结合geoiploc、黑名单库等
这些脚本可以有效防止SSH暴力破解攻击,建议在生产环境下使用fail2ban方案。