FRP内网穿透场景下的SSH异常连接识别与自动化封禁
1. FRP内网穿透与SSH安全挑战
FRP作为轻量级内网穿透工具,已经成为许多开发者和运维人员的首选方案。我自己在管理实验室服务器时,就经常用它来暴露内网服务。但最近发现一个棘手问题:FRP服务器开放SSH端口后,每天都会收到大量来自全球各地的异常连接请求。这些请求不仅占用宝贵的隧道资源,更严重的是可能引发安全风险。
传统防护方案在内网服务器上部署Fail2ban确实有效,但在FRP场景下却遇到了瓶颈。因为所有流量经过FRP转发后,源IP都会变成127.0.0.1,这让基于IP的防护工具完全失效。我实验室的两台服务器就曾因此每天承受数万次暴力破解尝试,导致正常SSH连接都变得异常缓慢。
经过抓包分析,发现恶意流量有明显特征:单个IP会在短时间内建立大量TCP连接,且连接状态多为TIME-WAIT。相比之下,正常用户的连接通常保持ESTABLISHED状态。这个发现让我意识到,通过分析TCP连接状态和IP并发特征,或许能在FRP层面实现主动防御。
2. 异常连接的特征识别技术
2.1 TCP状态深度解析
要识别异常连接,首先得理解TCP连接的各种状态。通过ss -anp命令可以看到,合法SSH连接通常显示为ESTABLISHED状态,表示连接正在活跃通信。而恶意扫描产生的连接往往呈现TIME-WAIT状态,这是TCP协议中连接关闭后的等待状态。
在我的测试环境中,正常用户连接后,TCP状态变化是这样的:
# 正常连接状态示例 ESTAB 0 0 192.168.1.100:22 203.0.113.45:54321而恶意扫描的连接状态则是:
# 异常连接状态示例 TIME-WAIT 0 0 192.168.1.100:22 198.51.100.33:12345 TIME-WAIT 0 0 192.168.1.100:22 198.51.100.33:12346 TIME-WAIT 0 0 192.168.1.100:22 198.51.100.33:123472.2 并发连接特征分析
恶意扫描最明显的特征是单个IP的高并发连接。通过统计发现,正常用户通常只会建立1-2个SSH连接,而扫描工具往往会同时发起数十个连接。在我的日志里就抓到过一个IP在5秒内建立了87个连接,这种异常行为很容易识别。
这里有个实用技巧:使用ss命令配合awk可以快速统计各IP的连接数:
ss -anp | grep ":22" | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr输出结果类似:
87 198.51.100.33 2 203.0.113.45 1 192.0.2.893. 自动化防御系统搭建
3.1 Python监控脚本开发
基于上述特征,我开发了一个Python监控脚本,主要实现三个功能:
- 解析
ss命令输出的连接信息 - 统计各IP的TIME-WAIT连接数
- 对超过阈值的IP自动封禁
核心代码如下:
#!/usr/bin/env python3 import re from collections import defaultdict from datetime import datetime import subprocess THRESHOLD = 3 # 并发连接阈值 LOG_FILE = '/var/log/frp_ssh_monitor.log' def analyze_connections(): ip_counts = defaultdict(int) output = subprocess.check_output(['ss', '-anp']) for line in output.decode().split('\n'): if ':22' not in line: # 替换为你的FRP端口 continue parts = line.split() if len(parts) < 6: continue status = parts[1] ip_port = parts[5] ip = re.sub(r':\d+$', '', ip_port.split(']')[-1]) if status == 'TIME-WAIT': ip_counts[ip] += 1 return ip_counts3.2 iptables自动封禁机制
当检测到异常IP时,脚本会自动调用iptables添加封禁规则。为了避免误封,我设置了白名单机制,确保管理员IP不会被错误拦截:
def block_malicious_ips(ip_counts): whitelist = {'192.168.1.100', '203.0.113.45'} # 替换为你的可信IP for ip, count in ip_counts.items(): if count > THRESHOLD and ip not in whitelist: subprocess.run([ 'iptables', '-A', 'INPUT', '-s', ip, '-p', 'tcp', '--dport', '22', '-j', 'DROP' ]) log_block_event(ip, count)4. 生产环境部署方案
4.1 系统架构设计
完整的防御系统包含以下组件:
- 监控模块:每分钟执行
ss命令采集连接数据 - 分析模块:Python脚本处理原始数据,识别异常IP
- 执行模块:调用iptables实施封禁
- 日志模块:记录所有封禁事件和成功连接
建议的目录结构:
/etc/frp_defense/ ├── config.json # 配置文件 ├── monitor.py # 主程序 ├── whitelist.txt # IP白名单 └── logs/ # 日志目录4.2 Crontab定时任务配置
为了让系统持续运行,需要设置定时任务。建议每分钟执行一次监控:
# 编辑crontab crontab -e # 添加以下内容 * * * * * /usr/bin/python3 /etc/frp_defense/monitor.py >> /var/log/frp_defense.log 2>&14.3 性能优化技巧
在大流量环境下,原始方案可能产生性能问题。经过实测,我总结了几个优化点:
- 使用
ss -n避免DNS反向解析 - 将Python脚本编译为字节码加速执行
- 设置iptables规则过期时间,避免规则集膨胀:
iptables -A INPUT -s 198.51.100.33 -m recent --set --name SSH_BAN iptables -A INPUT -s 198.51.100.33 -m recent --update --seconds 3600 --name SSH_BAN -j DROP5. 进阶防护策略
5.1 多维度威胁检测
除了TCP状态,还可以结合其他特征提升检测准确率:
- 地理信息:突然出现的境外IP
- 时间规律:非工作时间的密集连接
- 行为模式:固定间隔的连接尝试
5.2 智能阈值调整
固定阈值可能不适合所有场景。我改进了算法,使其能自动学习正常流量模式:
class AdaptiveThreshold: def __init__(self, window_size=24): self.history = [] self.window_size = window_size def update(self, current_count): self.history.append(current_count) if len(self.history) > self.window_size: self.history.pop(0) def get_threshold(self): if not self.history: return 3 avg = sum(self.history) / len(self.history) return max(3, avg * 1.5) # 保证最小阈值为35.3 防御绕过应对方案
最近发现攻击者开始使用以下手段绕过检测:
- IP轮换:每个IP只发起少量请求
- 慢速扫描:降低请求频率
- 模拟ESTABLISHED状态
针对这些情况,我增加了以下防御措施:
- 24小时累计计数
- 请求间隔时间分析
- 数据包特征检测
6. 监控与日志分析
完善的日志系统对后期分析至关重要。我的日志格式包含以下字段:
[2023-08-20 14:30:45] BLOCKED 198.51.100.33 COUNT=87 REASON="TIME-WAIT overflow" [2023-08-20 14:31:02] ALLOWED 203.0.113.45 ESTABLISHED使用GoAccess可以生成直观的报表:
cat /var/log/frp_defense.log | grep BLOCKED | awk '{print $3}' | sort | uniq -c | sort -nr7. 系统维护与更新
任何安全系统都需要持续维护。我建立了以下机制:
- 每周自动备份iptables规则
- 每月审查白名单
- 每季度更新检测算法
备份iptables规则的命令:
iptables-save > /etc/iptables.rules恢复规则:
iptables-restore < /etc/iptables.rules在实际运营中,这套系统成功将SSH攻击流量降低了98%,服务器资源占用回归正常水平。不过安全是持续的过程,我现在正研究如何将这套机制扩展应用到其他服务端口,形成完整的FRP层安全防护体系。