error_log比access_log更早、更准地识别恶意代理,因其记录“为什么失败”而非“访问了什么”,能暴露ssl握手失败、连接拒绝、请求无效等代理行为引发的异常信号,并支持通过grep+awk筛选和fail2ban自动拦截。

error_log 在识别恶意代理请求时,不是看“访问了什么”,而是看“为什么失败”——它直接暴露代理行为在服务层引发的异常信号,比 access.log 更早、更准。
恶意代理常触发的 error_log 特征
真实代理探测或滥用行为,往往导致 Nginx 与上游或客户端通信异常,这类问题会明确写入 error.log:
- SSL handshake failed:大量来自不同 IP 的 TLS 握手失败(尤其伴随相同 SNI 或空 ClientHello),常见于扫描型代理池或中间人探测
- connect() failed (111: Connection refused):代理尝试连接已关闭或未监听的后端端口,高频出现即暗示端口扫描或代理链测试
- upstream timed out:单个 IP 持续触发超时,但 upstream 响应时间正常 → 很可能是代理故意慢速发包、维持长连接耗尽资源
- client sent invalid request:非标准 HTTP/1.0 请求头、畸形 Host 字段、重复或缺失关键头(如 Transfer-Encoding),多见于低质量匿名代理或自研爬虫
如何从 error.log 中快速定位可疑代理
不用逐行翻查,用几条命令就能筛出高风险线索:
- 提取所有 SSL 握手失败并按 IP 统计:grep "SSL_do_handshake() failed" /var/log/nginx/error.log | awk '{print $12}' | sort | uniq -c | sort -nr | head -10
- 找出反复连接拒绝的 IP:grep "Connection refused" /var/log/nginx/error.log | awk '{print $12}' | sort | uniq -c | sort -nr | head -10
- 匹配代理典型错误组合(含 IP + 时间 + 错误类型):awk '/SSL_do_handshake|Connection refused|invalid request/ {print $1,$2,$12,$4,$5}' /var/log/nginx/error.log | head -20
配合 Fail2ban 实现自动拦截
仅发现不够,要让防御闭环。关键在于把 error.log 中的代理特征转为 Fail2ban 可识别的规则:
- 在 /etc/fail2ban/filter.d/nginx-proxy-attack.conf 中定义 filter:
- failregex = ^.*SSL_do_handshake\(\) failed.*client:
|connect\(\) failed \(111: Connection refused\).*client: - 在 jail.local 中启用该 jail,设置 findtime=60(1分钟内触发3次即封)
- 确保 Nginx error_log 级别为 warn 或更高,避免 info 级日志淹没有效信号
为什么比 access.log 更适合代理检测
access.log 记录的是“它发了什么”,而 error.log 记录的是“它根本没按协议来”。一个伪装良好的代理可能返回 200,但它的握手、连接、请求格式早已在 error.log 留下破绽。比如:
- 合法用户极少在 1 分钟内触发 5 次 SSL 握手失败;但代理池轮询不同出口 IP 时,这个数字很常见
- 正常浏览器不会发送 “GET / HTTP/0.9” 这类废弃协议请求,但很多免费代理会,Nginx 直接记为 invalid request
- 代理转发时若未正确处理 Connection: close,可能导致 Nginx 频繁报 upstream reset,这类日志集中出现就是代理链不稳定或恶意复用的证据











