树莓派 NGINX 流控和 fail2ban 防止 CC 攻击

博客一直定时会遭受小量的cc攻击 总是导致我的树莓派会很卡

CC 攻击

攻击者通过创建大量请求导致服务器资源耗尽,主要针对特定服务接口,属于实现 DoS 攻击的一种方式(DoS 攻击更多是针对网络端口,而不是具体服务接口)。

NGINX 流控

  • limit_req_zone:通过“漏桶”算法限制每个 IP 发起的请求频率。
  • limit_conn_zone:限制每个 IP 发起的连接数。

fail2ban

通过匹配服务器日志操作 iptables 来限制客户端网络连接。

实践配置

NGINX 部分

在 http 部分中配置:

<span class="hljs-attribute">limit_req_zone</span> <span class="hljs-variable">$binary_remote_addr</span> zone=sym:<span class="hljs-number">10m</span> rate=5r/s;
<span class="hljs-attribute">limit_conn_zone</span> <span class="hljs-variable">$binary_remote_addr</span> zone=conn_sym:<span class="hljs-number">10m</span>;

然后在需要流控的 location 部分配置:

<span class="hljs-attribute">limit_req</span> zone=sym burst=<span class="hljs-number">5</span>;
<span class="hljs-attribute">limit_conn</span> conn_sym <span class="hljs-number">10</span>;

重启 NGINX 后当有超流客户端请求时将在 NGINX error.log(默认在 /var/log/nginx/error.log) 中看到类似记录:

<span class="hljs-number">2017</span>/<span class="hljs-number">02</span>/<span class="hljs-number">12</span> <span class="hljs-number">18</span>:<span class="hljs-number">03</span>:<span class="hljs-number">57</span> <span class="hljs-string">[error]</span><span class="hljs-number">15965</span>#<span class="hljs-number">15965</span>: *<span class="hljs-number">61240</span> limiting requests, excess: <span class="hljs-number">6</span>.<span class="hljs-number">000</span> by zone <span class="hljs-string">"sym"</span>, client: <span class="hljs-number">121.41.106.121</span>, server: hacpai.com, request: <span class="hljs-string">"<span class="hljs-keyword">GET</span> / HTTP/1.0"</span>, host: <span class="hljs-string">"hacpai.com"</span>

此时请求已经被 NGINX 限流,但是客户端仍然能够继续发送请求,占用服务器资源。

fail2ban 部分

新建 /etc/fail2ban/jail.d/sym.conf 文件,加入如下内容:

[sym-cc]
enabled  = true
port     = https,http
filter   = sym
logpath  = /var/log/nginx/*error.log
maxretry = 120
findtime = 60
bantime  = 120
action   = iptables-multiport[name=Sym, port="https,http", protocol=tcp]
           sendmail-whois-lines[name=Sym, dest=youremail@gmail.com]

findtime 60 秒内如果有超过 maxretry 120 次匹配到则禁止连接 bantime 120 秒。禁止连接通过操作 iptables 实现 。(要发送邮件,需要安装配置好 sendmail)

重启 fail2ban 后当发生超流时可以在 /var/log/fail2ban.log 中看到类似记录:

2017<span class="hljs-selector-tag">-02-12</span> 18<span class="hljs-selector-pseudo">:01</span><span class="hljs-selector-pseudo">:26</span>,968 <span class="hljs-selector-tag">fail2ban</span><span class="hljs-selector-class">.actions</span>: <span class="hljs-selector-tag">WARNING</span> <span class="hljs-selector-attr">[sym-cc]</span> <span class="hljs-selector-tag">Ban</span> 121<span class="hljs-selector-class">.41</span><span class="hljs-selector-class">.106</span><span class="hljs-selector-class">.121</span>

另外:

  • fail2ban-client statusfail2ban-client status sym-cc 可以查看当前禁止信息
  • fail2ban-regex /var/log/nginx/error.log /etc/fail2ban/filter.d/sym.conf 可以查看配置匹配情况。

注意事项

fail2ban

  • 服务重启可能较慢,耐心等待
  • findtime 不要小于 60 秒
  • action 用 iptables-multiport 同时设置 HTTPS 和 HTTP
  • 可能需要自己手动加入操作系统启动项

如果 NGINX 开了 access_log,其实也可以简单粗暴一点直接将 fail2ban 配置到访问日志上,这样就不用配置 NGINX 流控模块了,不过缺点是失去了“弹性”。

NGINX

上面提到的 NGINX 流控模块的“弹性”主要指的是 limit_req_zone 模块中 burstnodelay 两个参数的组合使用。

  • rate:按照固定速率“漏请求”给后端服务器
  • burst:可理解为桶大小,能装多少个请求
  • nodelay:带了这个参数的话在桶装不下时将请求“全部倒给”后端服务器;如果不带的话请求还是按照速率慢慢漏

日志清理

需要定时清理 NGINX、fail2ban 日志,防止磁盘空间占用过大。

 

Momostudent
Momostudent
因为喜欢所以折腾。。。