抛砖引玉,来说下我的fail2ban配置

起因是看到使用iptables限制区域访问 - 配置调优 - LINUX DO这篇帖子,我就想起我当时天天被爆破ssh时的解决方案

安装

Fail2Ban的安装和配置过程非常直接,相关信息可以在其GitHub仓库以及官方Wiki中找到:

配置

wiki里是这么说的:

If not configured manually, Fail2ban will load configuration files from the directory /etc/fail2ban. You can find many files called *.conf there.
Before you start the fail2ban service for the first time, you should do some configuration appropriate to your system. The least would be to enable jails for the services that you want to protect with fail2ban.

[Q] Should I make my configuration directly in jail.conf and fail2ban.conf?
[A] No. You should avoid to change .conf files, created by fail2ban installation. Instead, you should create new files with a .local extension.

官方推荐在配置 fail2ban 的时候应该避免直接更改由 fail2ban 安装创建的.conf 文件(例如 fail2ban.confjail.conf),应该创建扩展名为.local 的新文件(例如 jail.local)来进行自定义配置。

.local 文件将覆盖.conf 文件相同部分的参数。

我拿sshd爆破来举个例子:

  • 首先创建.local文件: vim /etc/fail2ban/jail.local

  • 然后添加规则(可根据需要修改):

[DEFAULT]
# 配置忽略检测的 IP (段),添加多个需要用空格隔开
ignoreip = 127.0.0.1/8
[sshd]
enabled = true
# ssh的端口,如果使用非默认端口 22,要修改为实际使用端口
port = 22
# 配置使用的匹配规则文件(位于 /etc/fail2ban/filter.d 目录中)
filter = sshd
# 日志文件路径
logpath = /var/log/ban_sshd.log
# 配置 IP 封禁的持续时间(years/months/weeks/days/hours/minutes/seconds)
bantime  = 1h
# 是否开启增量禁止,可选
bantime.increment = true
# 如果上面为false则不生效,增量禁止的指数因子,这里设置为168的意思就是每次增加 168*(2^ban次数) (封禁时长类似这样 - 1小时 -> 7天 -> 14天 ...):
bantime.factor = 168
# 最大封禁时间,8w 表示8周,可选
bantime.maxtime = 8w
# 配置计算封禁 IP 的具体滑动窗口大小
findtime  = 5m
# 配置在 findtime 时间内发生多少次失败登录然后将 IP 封禁
maxretry = 3
# 配置封禁 IP 的手段(位于 /etc/fail2ban/action.d 目录中),可通过 iptables、firewalld 或者 TCP Wrapper 等,此处设置为 hostsdeny 代表使用 TCP Wrapper
action = hostsdeny

以上配置就是针对于 22 端口的ssh服务,在 5分钟 内,连续超过 3 次登录失败,就使用TCP Wrapper封禁尝试登录的ip 1小时 , 1小时 解封后继续登录失败,那就增量封禁到 7天->14天 ... ,最长封禁时间为 8周

:wq保存退出,然后重启服务生效

systemctl restart fail2ban
systemctl status fail2ban

内存节省选项(可选)

详见: maxmatches: memory saving options by sebres · Pull Request #2402 · fail2ban/fail2ban

在网站或服务器被DDoS时,由于findtimebantime很长,可能导致 fail2ban 在访问量较大的网站上产生大量内存消耗,解决方式就是配置中添加类似这样:
fail2ban.local:

[DEFAULT]
dbmaxmatches = 0
dbpurgeage = 20d

jail.local:

[DEFAULT]
maxmatches = 0

验证配置是否生效

tail -f /var/log/ban_sshd.log或者fail2ban-client status sshd

就能看到目前正在爆破你和ban掉爆破ssh的ip日志,和目前已经封禁的ip了

# fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 4
|  |- Total failed:     2435
|  `- File list:        /var/log/ban_sshd.log
`- Actions
   |- Currently banned: 95
   |- Total banned:     97
   `- Banned IP list:   188.166.250.214 61.177.172.140 180.101.88.205 218.92.0.29 61.177.172.179 211.224.34.90 218.92.0.107 218.92.0.118 210.204.192.235 86.60.174.21 180.101.88.197 61.177.172.160 61.177.172.136 218.92.0.76 180.101.88.196 125.124.113.133 111.2.113.237 218.92.0.112 179.43.180.106 165.232.159.232 185.148.253.22 59.5.15.143 64.225.30.41 183.81.169.238 188.192.178.230 210.231.184.92 221.226.39.202 170.106.183.204 165.227.85.21 143.244.177.125 92.205.108.83 43.156.35.214 78.135.85.201 195.72.145.14 64.225.54.6 170.106.199.89 43.143.164.246 120.53.220.179 94.179.133.22 139.196.253.42 165.232.180.16 45.164.39.253 201.226.239.98 27.254.149.199 114.132.157.247 113.31.119.15 81.71.88.224 101.126.64.240 124.223.2.75 104.250.50.192 170.64.163.179 117.184.199.39 118.195.163.59 220.82.219.197 81.192.46.48 46.25.44.227 49.51.231.176 43.153.162.117 170.106.65.25 190.145.192.106 111.67.195.91 221.145.121.27 210.222.106.148 217.76.48.9 185.224.128.34 185.219.127.19 112.196.74.82 43.156.17.233 106.240.228.244 124.156.192.109 43.153.220.28 103.240.205.212 43.139.139.189 106.13.223.14 124.223.6.90 103.226.248.146 103.79.152.202 42.194.226.27 181.94.223.41 113.142.54.163 27.254.235.4 220.123.110.183 87.255.193.50 161.35.71.130 89.185.85.151 35.227.114.241 159.65.224.161 43.134.63.206 128.199.39.25 205.185.113.140 119.246.42.139 211.225.58.80 161.35.221.197 43.133.34.99 43.153.75.181

可以看到我阿里云香港的vps,就这刚刚一会已经被ssh爆破了2435次,ban掉97个ip了

通过正则来ban特定日志记录的ip

如果需要,还可以根据失败日志中的特定模式来封禁IP。例如,对于如下Speed-Test类型的日志:

Feb 28 23:45:30 host kernel: [5140091.073466] Speed-Test IN=eno1 OUT= MAC=... SRC=192.0.2.1 DST=127.0.0.1 ...

可以在.local文件中添加相应的failregex规则来匹配这种模式。

.local文件里添加一行

failregex = ^\s*\S+\s+kernel:(?: +\[[^\]]+\])? Speed-Test (?:\b(?:IN=\w+|OUT=|(?:(?!OUT=|IN=)[A-Z]+=[^ \[]*)+) )*SRC=<ADDR> DST=\S+

这样所有触发特定失败日志的ip都会根据规则来封禁。

基于此,可以用来保护WordPress,WP登录地址为/wp-login.php

所以可以新增配置文件:

[wordpress]
enabled = true
# HTTP(80端口)和HTTPS(443端口)
port = http,https
# fail2ban 自带动作,意思是封禁,记录日志,发送邮件给管理员
action = %(action_mwl)s
maxretry = 5
findtime = 60s
bantime = 12h
logpath = /var/log/wp_access.log
failregex = ^ -.* /wp-login.php.* HTTP/1\.."

解封

# 解封所有IP
fail2ban-client unban --all
# 解封指定IP
# fail2ban-client unban <IP> ... <IP>
fail2ban-client unban 1.1.1.1
#删除特定服务的(如sshd)被ban IP
fail2ban-client set sshd delignoreip 1.1.1.1
45 个赞

针对sshd爆破有效果

常规话题配置调优

1 个赞

很不错,我以前写过一个网站的自动限制IP访问,定时搜索访问日志,当访问次数超过设定值的时候,自动把IP放入黑名单。

我markdown排版有点问题,凑合看吧 :cold_sweat:

不错,之前也是发现小鸡有那么多的IP在持续的爆破扫描,后来直接改为非标端口,禁用了密码登录了

学习了

自用

#!/bin/bash

# 查找登录失败次数超过2次的IP
list=$(sudo lastb | awk '{if ($3 ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) print $3}' | sort | uniq -c | awk '{if ($1 > 2) print $2}')

# 将这些IP加入到 /etc/hosts.deny 文件中,以禁止这些IP访问该机器
if [ ${#list[@]} -gt 0 ]; then
    for ip in ${list}
    do
        if ! grep -q "${ip}" /etc/hosts.deny; then
            echo "ALL: ${ip}" >> /etc/hosts.deny
        fi
        iptables -A INPUT -s ${ip} -j DROP
    done
    
    # 重启iptables服务使防火墙规则生效
    systemctl restart iptables
fi

# 清空系统记录登录失败次数的日志文件 /var/log/btmp
echo > /var/log/btmp
2 个赞

感谢分享,看来我设置的findtime还是太保守了

你们的都太专业了,看都看不懂,我琢磨着自己弄了一个,把所有nginx非200的都给掐了

然而我发现竟然有大量的CF的IP请求是404,有人在用大善人做坏事吧?这就很蛋疼,如果把大善人的IP拉黑了,我可能也会遇到server is down之类的错误。不知各位佬有什么好办法

172.70.135.106 - - [07/Apr/2024:04:29:37 +0800] "GET /heartcombo/has_scope/issues HTTP/2.0" 404 123 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"
172.70.175.223 - - [07/Apr/2024:04:29:41 +0800] "GET /heartcombo/responders/pulls HTTP/2.0" 404 123 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"
172.70.34.34 - - [07/Apr/2024:04:29:46 +0800] "GET /heartcombo/mail_form/issues HTTP/2.0" 404 123 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"
172.71.223.7 - - [07/Apr/2024:04:29:49 +0800] "GET /aiekick/NoodlesPlate/pulls HTTP/2.0" 404 123 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"
172.71.222.61 - - [07/Apr/2024:04:29:53 +0800] "GET /titusjan/objbrowser/issues HTTP/2.0" 404 123 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"
172.70.174.171 - - [07/Apr/2024:04:29:57 +0800] "GET /cam-inc/k6-operator/issues HTTP/2.0" 404 123 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"
172.70.42.115 - - [07/Apr/2024:04:30:01 +0800] "GET /heartcombo/mail_form/pulls HTTP/2.0" 404 123 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"
172.70.174.117 - - [07/Apr/2024:04:30:05 +0800] "GET /heartcombo/has_scope/pulls HTTP/2.0" 404 123 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot)"

jail.local

[DEFAULT]
ignoreip = 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 ::1 xxx.xxx.xxx.xxx
bantime = 3600
findtime = 600
maxretry = 5

[sshd]
enabled = true
port = 54322
logpath = %(sshd_log)s
backend = %(sshd_backend)s

[nginx-http-auth]
enabled = true
port = http,https,10000:20000
logpath = %(nginx_error_log)s

[nginx-botsearch]
enabled = true
port = http,https,10000:20000
logpath = %(nginx_error_log)s

[nginx-non-200]
enabled = true
port = http,https,10000:20000
logpath  = /var/log/nginx/access.log
filter = nginx-non-200

nginx-non-200.conf

[Definition]
failregex = ^<HOST> -.*"(GET|POST|HEAD|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH) .*" 40[0-9].*$
ignoreregex = xxx\.com|yyy\.com
1 个赞

最后用这个工具,回想下已经差不多8年前了 :grinning:

F2b 好像對docker沒用。。。設好了docker 中照樣被暴力搞卻沒禁封

From 配置调优 to 开发调优

学习了,感谢。

感谢佬友分享