跳至主内容

fail2ban

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

Fail2ban 是一款入侵防御软件框架,用于保护计算机服务器免受暴力破解攻击。 Fail2ban 通过监控日志文件(如 /var/log/auth.log、/var/log/apache/access.log 等)中的特定条目,并根据其内容执行相应脚本。

Jellyfin 生成的日志可被 Fail2ban 监控,用于防止针对您设备的暴力破解攻击。

先决条件

  • Jellyfin 需可远程访问

  • 已安装并运行 Fail2ban

  • 了解 Jellyfin 日志存储位置:桌面版默认为 /var/log/jellyfin/,Docker 容器则为 /config/log/

  • 将 Jellyfin 日志级别设为 Info(失败的认证条目不会记录在 Error 级别)。该设置可在 logging.json 文件中找到。

第一步:创建 jail

您需要为 Fail2ban 创建 jail。若使用 Ubuntu 系统并以 nano 作为编辑器,请运行:

sudoedit /etc/fail2ban/jail.d/jellyfin.local

将以下内容添加到新文件中,并将 /path_to_logs 替换为上述日志路径(例如 /var/log/jellyfin/):

[jellyfin]

backend = auto
enabled = true
port = 80,443
protocol = tcp
filter = jellyfin
maxretry = 3
bantime = 86400
findtime = 43200
logpath = /path_to_logs/log_*.log

保存并退出 nano。

注意:

  1. 若 Jellyfin 运行在 Docker 容器中,请在 jellyfin.local 文件中添加:

    action = iptables-allports[name=jellyfin, chain=DOCKER-USER]
  2. 若 Jellyfin 使用非标准端口,请将端口号从 80,443 改为实际端口(如 8096,8920

第二步:创建过滤器

过滤器包含一组规则,Fail2ban 将据此识别失败的认证尝试。通过以下命令创建过滤器:

sudoedit /etc/fail2ban/filter.d/jellyfin.conf

粘贴以下内容:

[Definition]
failregex = ^.*Authentication request for .* has been denied \(IP: "<ADDR>"\)\.

保存并退出,然后重新加载 Fail2ban:

sudo systemctl restart fail2ban

检查 Fail2ban 是否正常运行:

sudo systemctl status fail2ban

第三步:测试

假设至少存在一次失败的认证尝试,您可以使用 fail2ban-regex 测试新建的 jail:

sudo fail2ban-regex /path_to_logs/log_*.log /etc/fail2ban/filter.d/jellyfin.conf --print-all-matched

高级 Fail2Ban 配置:在上游代理服务器上转发和管理封禁

为增强安全性,Fail2Ban 可在上游反向代理服务器而非 Jellyfin 服务器上管理 IP 封禁。此配置允许您在网络入口点就近拦截恶意 IP,并可能惠及使用同一代理的其他服务。

本指南提供使用**动态链(Dynamic Chains)**的配置方案,使 Fail2Ban 能在上游反向代理服务器管理 IP 封禁。每个 Fail2Ban jail 会在上游服务器创建并管理独立的 iptables 链。

前提条件

  • Fail2Ban 已安装在本地服务器(运行 Jellyfin 的服务器)

  • 上游服务器已配置 iptables

第一步:设置基于 SSH 密钥的认证

确保 Fail2Ban 服务器可通过 SSH 无密码登录上游服务器。这对自动化 IP 封禁/解封流程至关重要。

<upstream-server-ip> 替换为您上游服务器的实际 IP 地址。

  1. 生成 SSH 密钥(如尚未创建)

    ssh-keygen -t rsa -b 4096 -f /root/.ssh/id_rsa
  2. 将 SSH 公钥复制到上游服务器

    ssh-copy-id -i /root/.ssh/id_rsa.pub root@<upstream-server-ip>
  3. 测试 SSH 访问

    确保 SSH 连接无需密码即可正常工作:

    ssh -i /root/.ssh/id_rsa root@<upstream-server-ip>

步骤二:配置 Fail2Ban 实现动态链

  1. 创建 Fail2Ban 动作文件

    在 Fail2Ban 服务器上创建新动作文件:

    sudo nano /etc/fail2ban/action.d/proxy-iptables-dynamic.conf

    添加以下配置,该配置将为每个 jail 在上游服务器动态创建、管理和删除 iptables 链:

    请将 <upstream-server-ip> 替换为您上游服务器的实际 IP 地址。

    [Definition]

    # Option: actionban
    # 1. Create the chain if it doesn't exist
    # 2. Add the banned IP to the dynamic chain based on the jail name
    # 3. Log the event
    actionban = ssh -i /root/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@<upstream-server-ip> \
    'iptables -N f2b-<name> 2>/dev/null || true; \
    iptables -C INPUT -j f2b-<name> 2>/dev/null || iptables -I INPUT -j f2b-<name>; \
    iptables -I f2b-<name> 1 -s <ip> -j DROP' && \
    echo "Banned <ip> from jail <name> via upstream proxy" >> /var/log/fail2ban.log

    # Option: actionunban
    # 1. Remove the banned IP from the dynamic chain
    # 2. Remove the chain if it becomes empty (cleanup)
    # 3. Log the event
    actionunban = ssh -i /root/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@<upstream-server-ip> \
    'iptables -D f2b-<name> -s <ip> -j DROP; \
    if ! iptables -L f2b-<name> | grep -q "DROP"; then \
    iptables -D INPUT -j f2b-<name>; \
    iptables -F f2b-<name>; \
    iptables -X f2b-<name>; \
    fi' && \
    echo "Unbanned <ip> from jail <name> via upstream proxy and cleaned up chain if empty" >> /var/log/fail2ban.log

    修改完成后,保存并关闭文件。

  2. 更新 Fail2Ban Jails 使用动态链动作

    打开 jail 配置文件(通常位于 /etc/fail2ban/jail.local):

    sudo nano /etc/fail2ban/jail.local

    对于要通过上游代理管理的每个 jail,添加或修改 action 行以使用 proxy-iptables-dynamic 动作。以下是两个 jail 的配置示例:

    [jellyfin]
    enabled = true
    filter = jellyfin
    logpath = /path/to/jellyfin/log
    maxretry = 3
    bantime = 3600
    action = proxy-iptables-dynamic

    [nginx-http-auth]
    enabled = true
    filter = nginx-http-auth
    logpath = /var/log/nginx/error.log
    maxretry = 5
    bantime = 3600
    action = proxy-iptables-dynamic

    修改完成后,保存并关闭文件。

步骤三:向 Jellyfin 添加代理 IP

  1. 获取代理 IP

    由于您使用代理服务器,需要让 Jellyfin 在日志中输出正确的 IP 供 fail2ban 读取。

    根据您的主机配置,这些 IP 范围可能来自内部 Docker IP、haproxy 或其他服务。

    Jellyfin 接受带子网掩码的 IP 地址(如 172.18.0.1/24),您需要提供这些 IP 的逗号分隔列表。

  2. 向 Jellyfin 添加代理

    打开 Jellyfin 服务器仪表板,进入 Advanced -> Networking,滚动至 Known proxies选项。

    输入您的逗号分隔代理 IP 范围列表。根据提示重启 Jellyfin 服务器。

第四步:重启 Fail2ban 并测试设置

  1. 重启 Fail2ban:

    完成配置更改后,重启 Fail2ban 以应用新设置:

    sudo systemctl restart fail2ban
  2. 检查监禁状态:

    验证您的监禁状态以确保其正常运行:

    sudo fail2ban-client status jellyfin
  3. 测试封禁:

    通过执行无效登录尝试或手动封禁 IP 来触发封禁。例如:

    sudo fail2ban-client set jellyfin banip 192.168.1.100
  4. 在上游服务器验证:

    检查该 IP 是否在上游服务器对应的监禁链('f2b-jail-name')中被封禁:

    ssh root@<upstream-server-ip> "iptables -L f2b-jellyfin"
  5. 测试解封:

    要测试解封功能,请手动解封该 IP:

    sudo fail2ban-client set jellyfin unbanip 192.168.1.100
  6. 验证解封

    确认 IP 已从对应 jail 的链('f2b-jail-name')中移除:

    ssh root@<upstream-server-ip> "iptables -L f2b-jellyfin"

第五步:监控日志

监控 Fail2ban 日志以确保操作正常执行:

tail -f /var/log/fail2ban.log

每当有 IP 被封禁或解封时,该日志将显示消息,帮助您确认配置是否按预期工作。