使用 Fail2Ban 保护 Gitea
Fail2Ban 是一个入侵检测系统框架,其工作原理是检查客户端登录日志,自动标记多次登录尝试失败的客户端 IP,并且在一段时间内阻止其访问。对与互联网上公开的服务器来说,这种防御手段可以在一定程度上缓解服务器压力。管理员在设置 Fail2Ban 时需谨慎处理,任何错误的配置将导致服务器无法访问。
准备工作
输出日志到文件
Gitea 日志中的一部分是 CLI、SSH 或 HTTP 客户端的登录授权结果,其中包含了远程客户端 IP 地址。这部分日志默认情况下只输出到控制台(配置为 MODE = console
),调整日志输出模式为 MODE = file
之后,日志将输出到文件,便于 Fail2Ban 扫描该内容。
[log]
MODE = file
LEVEL = info
#ROOT_PATH = /path/to/log
日志默认存放于 gitea
程序的相对路径 log/gitea.log
,如果设定了 ROOT_PATH
作为日志存放目录,那么日志位于 ${ROOT_PATH}/gitea.log
。要查找准确的日志存放路径,还可以通过“管理后台 - 应用配置 - 日志配置”,查找 filename
字符串。
当用户的身份验证失败时,Gitea 日志中会记录此类信息:
2018/04/26 18:15:54 [I] Failed authentication attempt for user from xxx.xxx.xxx.xxx
2020/10/15 16:08:44 [E] invalid credentials from xxx.xxx.xxx.xxx
安装 Fail2Ban
Debian / Ubuntu / Raspberry Pi OS
apt install fail2ban -y
Fedora / CentOS
# CentOS 7 需要安装 EPEL
sudo yum install epel-release
sudo yum install fail2ban -y
Synology DSM
给群晖配置 Fail2Ban 稍微有些麻烦。 已有的解决方案是采用 docker compose ,详情参考:
编辑规则
Filter
根据前面的日志,添加新的 filter 到 filter.d/gitea.conf
。
# /etc/fail2ban/filter.d/gitea.conf
[Definition]
failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>
ignoreregex =
这条规则使用正则表达式从日志中过滤出包含下列字符串的客户端 IP。
Failed authentication attempt
invalid credentials
Attempted access of unknown user
Jail
然后,添加 jail 规则到 jail.d/gitea.conf
,下面是示范:
# /etc/fail2ban/jail.d/gitea.conf
[gitea]
enabled = true # 功能开关
filter = gitea # 使用过滤器 gitea
logpath = /path/to/gitea.log # 日志路径
maxretry = 10 # 触发防御机制的最大尝试次数
findtime = 3600 # 发现同一目标的时间间隔(秒)
bantime = 900 # 封锁时间(秒)
action = iptables-allports # 采取行动,禁止对方访问所有端口
上述规则规定客户端在 1 小时内,如果登录失败的次数达到 10 次,则通过 iptables 锁定该客户端 IP 地址 15 分钟。
另外,如果你的 Gitea 服务器运行在 Docker 容器中,并且直接将容器端口暴露到外部网络,你还需要添加 chain="FORWARD"
到 jail 规则以适应转发后的数据包。如果你在容器的宿主机上使用 Nginx 反向代理连接到 Gitea 时,则无需这样配置。
# /etc/fail2ban/jail.d/gitea.conf
[gitea]
...
action = iptables-allports[chain="FORWARD"]
最后,运行 sudo systemctl reload fail2ban
重载配置文件。
使用 fail2ban-client status gitea
检查 Fail2Ban 运行状态。
$ sudo fail2ban-client status gitea
Status for the jail: gitea
|- Filter
| |- Currently failed: 24
| |- Total failed: 49
| `- File list: /home/ferris/docker/gitea/data/data/log/gitea.log
`- Actions
|- Currently banned: 0
|- Total banned: 1
`- Banned IP list:
测试 Fail2Ban
在浏览器中使用错误的用户名或密码反复登录 Gitea。如果浏览器报告无法访问目标地址,表示你的 IP 地址已被防火墙禁封。
解封 IP:
sudo fail2ban-client set gitea unbanip XX.XX.XX.XX
常见问题
反向代理
如果你使用 Nginx 反向代理到 Gitea 实例,你还需要设置 Nginx 的 HTTP 头部值 X-Real-IP
将真实的客户端 IP 地址传递给 Gitea。否则 Gitea 程序会将客户端地址错误解析为反向代理服务器的地址,例如回环地址 127.0.0.1
。
proxy_set_header X-Real-IP $remote_addr;
额外注意,在 Gitea 的配置文件 app.ini
中存在下列默认值:
REVERSE_PROXY_LIMIT = 1
REVERSE_PROXY_TRUSTED_PROXIES = 127.0.0.0/8,::1/128
REVERSE_PROXY_LIMIT
限制反向代理服务器的层数,设置为0
表示不使用这些标头。REVERSE_PROXY_TRUSTED_PROXIES
表示受信任的反向代理服务器网络地址。经过该网络地址转发来的流量,Gitea 会尝试扫描X-Real-IP
头部得到真实客户端地址。(参考 configuration cheat sheet)