1578 字
8 分钟
关于 Docker Gitea 非 rootless 版无法获取SSH log信息解决办法
本文主要内容非rootless版本(也就是默认的
gitea/gitea:latest无法获取到SSH登录日志信息,哪怕设置ENABLE_SSH_LOG为true也无济于事。本文介绍一种解决办法,通过获取Docker容器的日志文件来实现SSH log的记录,从而可以进行fail2ban的配置
Gitea在部署标准版的情况下,无论你如何配置app.ini都无法获取到SSH登录日志信息,主要原因是Gitea容器内并没有sshd服务,所以无法获取到相关日志信息。官网的描述很简单的,只需要改下 app.ini 中 log 部分下的 MODE为file,并开启 ENABLE_SSH_LOG,但是请放心做无用功,哪怕如此修改后,gitea.log 依旧不会有 SSH 相关的log,因为ENABLE_SSH_LOG 仅对 Gitea 内建 SSH 有效,抱歉的是,标准版中的 OpenSSH 不可与内建 SSH 调和。同时在其 github 存在一个 issue ,回复是“如果你没用它自带的 SSH,凭什么指望 Gitea 的日志会提供那些信息?直接设置 fail2ban 去用 sshd 的日志就行了”。
但是,天不绝人之路,通过docker compose logs -f gitea查看可以发现,docker logs内是有SSH相关的爆破信息的,因此解决方法就很简单了,定时将docker logs内的SSH信息提取出来,写入到一个单独的log文件中,然后让fail2ban去监控这个log文件即可。
部署流程
定时提取SSH log
- 创建脚本文件
Terminal window nano ~/docker_data/gitea/gitea_docker_log.sh && chmod +x ~/docker_data/gitea/gitea_docker_log.shgite_docker_log.sh #!/bin/bash# --- 配置 ---# Gitea 容器的名称CONTAINER_NAME="gitea"# 日志文件在宿主机上的完整路径LOG_FILE="/root/docker_data/gitea/gitea.log"# --- 脚本主体 ---LOG_DIR=$(dirname "$LOG_FILE")# 确保日志目录存在mkdir -p "$LOG_DIR"echo "脚本已启动,将监控容器 '$CONTAINER_NAME' 并将日志写入 '$LOG_FILE'"# 无限循环,确保在容器重启后能自动重新连接while true; do# 使用 docker inspect 检查容器是否存在且在运行,这比解析 ps 输出更可靠if docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME" 2>/dev/null | grep -q "true"; thenecho "[$(date '+%Y-%m-%d %H:%M:%S')] 已连接到 '$CONTAINER_NAME' 容器日志流..."# 使用 docker logs 持续跟踪日志(只取过去15秒的日志),并将标准错误(2)也重定向到标准输出(1)# 然后通过 sed 高效地格式化时间戳,最后追加到日志文件# sed -u: 使用无缓冲模式,确保日志实时写入# s/T/ /: 将日期和时间之间的 'T' 替换为空格# s/\..*Z$//: 删除小数点及其后面的所有内容,即毫秒和'Z'docker logs --timestamps --follow "$CONTAINER_NAME" 2>&1 | \sed -u 's/T/ /;s/\..*Z$//' >> "$LOG_FILE"# 如果 docker logs 命令退出 (通常是因为容器停止了),会执行到这里echo "[$(date '+%Y-%m-%d %H:%M:%S')] 与 '$CONTAINER_NAME' 的日志流断开。正在重试..."elseecho "[$(date '+%Y-%m-%d %H:%M:%S')] 容器 '$CONTAINER_NAME' 未运行或不存在,等待 10 秒..."fi# 短暂休眠,避免在容器不存在时消耗过多 CPUsleep 10done - 创建systemd服务
Terminal window nano /etc/systemd/system/gitea_docker_log.servicegitea_docker_log.service [Unit]Description=Gitea Log MonitorAfter=docker.serviceRequires=docker.service[Service]ExecStart=/root/docker_data/gitea/gitea_log_monitor.shRestart=alwaysUser=root[Install]WantedBy=multi-user.target - 启动服务
Terminal window systemctl daemon-reloadsystemctl enable gitea_docker_log.servicesystemctl start gitea_docker_log.service - 检查服务状态
Terminal window systemctl status gitea_docker_log.service
配置fail2ban监控SSH log
不要使用官方的过滤规则,根本就是乱写,完全抓不到任何一个爆破行为,下面是我实际使用的过滤规则
- 创建fail2ban过滤器
nano /etc/fail2ban/filter.d/gitea.conf
filter.d/gitea.conf [Definition]failregex = ^.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST> .*^.* Invalid user .* from <HOST> .*^.* <HOST> not allowed because not listed in AllowUsers.*^Disconnected from invalid user .* <HOST> port.*^Connection closed by invalid user .* <HOST> port.*^Timeout before authentication for connection from <HOST> .*ignoreregex = - 创建fail2ban jail
Terminal window nano /etc/fail2ban/jail.d/gitea-docker.localjail.d/gitea-docker.local [gitea-docker]# 是否启用此防护规则。true 表示启用。enabled = true# [关键] 指定 iptables 防火墙规则应该应用在哪条链上。# 对于 Docker 容器,所有外部到容器的流量都经过宿主机的 FORWARD 链。# 因此,必须设置为 FORWARD 才能正确地封禁访问 Docker 容器的 IP。chain = FORWARD# 指定用于解析日志文件的过滤器(filter)。# "gitea" 对应于 /etc/fail2ban/filter.d/gitea.conf 文件。# 这个过滤器定义了如何从日志中识别出失败的登录尝试(例如,通过正则表达式匹配错误信息)。filter = gitea# [关键] 指定要监控的日志文件的完整路径。# 这里指向的是你在宿主机上,通过脚本收集并整合的 Gitea 容器日志。# Fail2Ban 将会实时读取这个文件来检测攻击行为。logpath = /root/docker_data/gitea/gitea.log# [安全策略] 最大重试次数。# 在 `findtime` 定义的时间窗口内,如果同一个 IP 地址的失败尝试次数达到 3 次,# Fail2Ban 就会触发封禁动作。这是一个比较严格的设置,能快速响应攻击。maxretry = 3# [安全策略] 观察时间窗口。# Fail2Ban 只会计算最近 10 分钟内的失败次数。# 例如,一个 IP 在 10:00 失败了 2 次,在 10:11 又失败了 1 次,这不会触发封禁,# 因为在任何一个 10 分钟的窗口内,失败次数都没有达到 3 次。可以自行改大findtime = 10m# [安全策略] 封禁时长。# 一旦一个 IP 被封禁,它将在 146 小时(约 6 天)内无法访问任何服务。# 这是一个长期封禁,能非常有效地阻止持续的暴力破解或扫描攻击。bantime = 146h# [安全策略] 封禁动作。# 定义当触发封禁时,具体执行什么操作。# "iptables-allports" 是一个预定义的动作,会使用 iptables 封禁该 IP 的所有端口。# "blocktype=DROP" 是传递给这个动作的参数,指定封禁模式为 DROP。# DROP 模式会直接丢弃来自该 IP 的数据包,让攻击者连接超时,比 REJECT (拒绝) 更隐蔽。banaction = iptables-allports[blocktype=DROP] - 重启fail2ban服务
Terminal window systemctl restart fail2ban - 检查fail2ban状态
Terminal window fail2ban-client status && fail2ban-client status gitea-docker - 配置
logrotate服务Terminal window nano /etc/logrotate.d/gitea_docker_loglogrotate.d/gitea-docker /root/docker_data/gitea/gitea.log {# 每天轮转一次daily# 保留最近 3 份的归档日志rotate 3# 归档时使用 gzip 压缩compress# 推迟到下一次轮转时再压缩,避免服务切换文件句柄时出问题delaycompress# 如果日志文件不存在,不报错missingok# 如果日志文件为空,不进行轮转notifempty# 复制log文件并清空原文件内容copytruncate}
关于 Docker Gitea 非 rootless 版无法获取SSH log信息解决办法
https://blog.useforall.com/posts/solve-docker-gitea-ssh-log-issue/ 最后更新于 2025-11-03,距今已过 13 天
部分内容可能已过时
Lim's Blog