> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashduty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Fail2ban 告警集成

> 在 Fail2ban 中添加自定义 action，用 curl 把封禁和解封事件推送到 Flashduty 的标准告警事件集成，解封时自动关闭告警。

Fail2ban 没有内置的 Webhook 通知，但它的 action 就是在封禁或解封 IP 时执行的 shell 命令（官方自带的 `abuseipdb` action 就是用 `curl` 调用外部 API）。因此不需要单独的 Fail2ban 集成：在 Fail2ban 里添加一个 action 文件，用 `curl` 把封禁事件 POST 到 Flashduty 的 [标准告警事件](/zh/on-call/integration/alert-integration/alert-sources/standard-alert) 集成；解封时再发一条恢复事件，关闭对应告警。

<div className="hide">
  ## 在 Flashduty On-call

  ***

  您可通过以下两种方式获取集成推送地址，任选其一即可。**集成类型都选择标准告警事件**，不是 Fail2ban。

  ### 使用专属集成

  1. 进入 Flashduty 控制台，选择 **协作空间**，打开一个协作空间
  2. 选择 **配置** → **集成数据** → **专属集成**，点击 **新增一个集成**
  3. 选择 **标准告警事件**，点击 **保存**
  4. 打开生成的集成卡片，复制 **推送地址**，形如 `https://api.flashcat.cloud/event/push/alert/standard?integration_key=<集成密钥>`

  ### 使用共享集成

  1. 进入 Flashduty 控制台，选择 **集成中心 → 告警事件**
  2. 选择 **标准告警事件**，填写集成名称
  3. 配置默认路由并选择协作空间；创建后可在 **路由** 中增加更多规则
  4. 点击 **保存**，复制生成的 **推送地址**
</div>

## 在 Fail2ban 中配置

***

以下操作在运行 Fail2ban 的主机上进行，需要 root 权限。

<Steps>
  <Step title="创建 action 文件">
    新建 `/etc/fail2ban/action.d/flashduty.conf`：

    ```ini theme={null}
    [Definition]

    # 重启后从数据库恢复的封禁不再重复通知
    norestored = 1

    actionban = curl -sS -X POST -H 'Content-Type: application/json' -d '{"event_status":"Warning","title_rule":"Fail2ban <name> banned::$ip","alert_key":"fail2ban-<name>-<ip>","description":"<failures> failed attempts, banned for <bantime> seconds","labels":{"jail":"<name>","ip":"<ip>","failures":"<failures>","bantime":"<bantime>"}}' '<flashduty_url>'

    actionunban = curl -sS -X POST -H 'Content-Type: application/json' -d '{"event_status":"Ok","title_rule":"Fail2ban <name> unbanned::$ip","alert_key":"fail2ban-<name>-<ip>","labels":{"jail":"<name>","ip":"<ip>"}}' '<flashduty_url>'

    [Init]

    flashduty_url =
    ```

    `<name>`、`<ip>`、`<failures>`、`<bantime>` 是 Fail2ban 在执行 action 时替换的标签（见 `jail.conf(5)` 的 Action Tags）：`<name>` 为 jail 名称，`<ip>` 为被封 IP，`<failures>` 为触发封禁的失败次数，`<bantime>` 为封禁时长（秒）。`flashduty_url` 是 `[Init]` 中的自定义参数，在 jail 里传入。

    <Warning>
      不要把 `<matches>` 放进 JSON。它包含原始日志行，可能带有用户名等敏感内容，也可能含有破坏 JSON 的引号。
    </Warning>
  </Step>

  <Step title="在 jail 中启用">
    编辑 `/etc/fail2ban/jail.local`，在需要通知的 jail 里追加 `flashduty` action，并把 Flashduty 推送地址传给 `flashduty_url`。`action` 可以写多行；第一行保留默认的封禁 action：

    ```ini theme={null}
    [sshd]
    enabled = true
    action  = %(action_)s
              flashduty[flashduty_url="https://api.flashcat.cloud/event/push/alert/standard?integration_key=YOUR_INTEGRATION_KEY"]
    ```

    如果想让所有 jail 都通知，把这两行 `action` 写在 `[DEFAULT]` 段。
  </Step>

  <Step title="重载并验证">
    ```bash theme={null}
    fail2ban-client reload
    fail2ban-client set sshd banip 192.0.2.10
    fail2ban-client set sshd unbanip 192.0.2.10
    ```

    `banip` 手动封禁一个 IP，`unbanip` 手动解封。第一条命令后 Flashduty 应出现标题为 `Fail2ban sshd banned / 192.0.2.10` 的告警，第二条命令后该告警被关闭。没有收到时，先在主机上用同样的 `curl` 命令手动请求推送地址，响应里会有错误码，Fail2ban 自己的报错在 `/var/log/fail2ban.log`。
  </Step>
</Steps>

## 字段映射

***

| Fail2ban | Flashduty |
| :- | :- |
| `alert_key`（`fail2ban-<jail>-<ip>`） | Alert Key。同一 jail 中同一 IP 的封禁与解封对应同一条告警 |
| `event_status: Warning` | 封禁时触发 Warning 告警；想要更高等级可改成 `Critical` |
| `event_status: Ok` | 解封时关闭告警 |
| `title_rule` | 告警标题，形如 `Fail2ban sshd banned / 192.0.2.1`；`::` 分隔标题片段，`$ip` 取自标签 `ip`，IPv6 地址中的 `::` 不会拆分标题 |
| `description` | 告警描述 |
| `labels` | 标签 `jail`、`ip`、`failures`、`bantime` |

## 恢复与去重

***

* Fail2ban 在封禁时间到期后执行 `actionunban`，Flashduty 用相同的 `alert_key` 关闭对应告警。
* 封禁时间设为永久（`bantime = -1`）时不会解封，告警不会自动关闭。请在接收该集成的协作空间开启 [超时自动关闭](/zh/on-call/channel/create-edit)，或处理完成后手动关闭。
* 同一 jail 内同一 IP 再次被封会更新同一条告警，不会产生重复告警。
* `norestored = 1` 让 Fail2ban 重启后从数据库恢复的封禁不再通知，避免重启时产生一批重复告警。

## 排查问题

***

* **Flashduty 没有收到告警**：确认 `fail2ban-client reload` 已执行；用 `curl` 在同一台主机上手动请求推送地址，看响应和网络是否可达 api.flashcat.cloud
* **返回 `InvalidParameter`**：推送地址缺少 `integration_key`，或 JSON 因引号被破坏；确认 `[Definition]` 里没有多余的换行
* **告警没有恢复**：确认 `actionunban` 存在，且 `alert_key` 与封禁时一致；永久封禁需要开启超时自动关闭
* **通知太多**：只在需要人工响应的 jail（例如 `recidive` 或 `maxretry` 较高的 jail）里启用 `flashduty`，普通的密码输错封禁不必通知
