sadeq-n-yazdi/simple-blocker

GitHub: sadeq-n-yazdi/simple-blocker

一个基于 Go 的动态 IP 黑名单守护进程,通过监控日志自动在防火墙层面封禁恶意探测与暴力破解 IP。

Stars: 1 | Forks: 0

# simple-blocker 一个小巧、轻依赖的 daemon,用于监控你的日志以防范恶意探测 和暴力破解尝试,然后通过防火墙封禁违规 IP, 并实施逐步升级的限时封禁。 它会追踪日志源(systemd journal、Docker 容器日志),将每一行 与可配置的 regular expressions 进行匹配,当某个地址在滑动窗口内 达到违规阈值时,就会通过 **ipset + iptables** 或 **nftables** 将其丢弃——具体取决于你的主机上安装了哪个。封禁会自动过期。 这是原始 Python 原型的 Go 重写版本,经过了重构以提高 可配置性和可扩展性。 ## 功能 - **配置驱动** — YAML *或* JSON(通过文件扩展名选择),无需重新编译。 - **内部或外部执行** — 防火墙以 **基于 netlink 的纯 Go nftables**(无需外部二进制文件)运行,或者通过 shell 调用主机上的 工具;通过 `firewall.mode` 或 `-firewall-mode` 为每个部署进行选择。 - **可插拔防火墙后端**(外部模式) — `ipset`+`iptables`(支持 `DOCKER-USER`)或原生 `nftables`,自动检测。 - **可插拔日志源** — 目前支持 `journal` (systemd) 和 `docker`;每一个都是 带有命名 `(?P...)` 捕获组的 regex,因此添加新的日志格式 只需修改配置,无需更改代码。 - **逐步升级的封禁** — 窗口内的违规次数越多 ⇒ 封禁时间越长。 - **滑动窗口** — 旧的违规记录会自动老化失效。 - **重启安全** — 规则和集合以幂等方式创建;现有的封禁 在重启后依然有效。 ## 工作原理 ``` log source ──▶ regex (?P…) ──▶ offense tracker ──▶ ban schedule ──▶ firewall (journal, per line sliding window offenses→time ipset/iptables docker) or nftables ``` ## 安装 需要一台装有 **systemd** 和 **Go 工具链**(用于构建)的 Linux 主机。 如果不存在防火墙后端,安装程序会为你获取一个。 ``` git clone https://code.sadeq.uk/simple-blocker.git # or your fork cd simple-blocker sudo ./scripts/install.sh ``` 安装程序(幂等 — 可安全重复运行): 1. 检查 `systemd`;如果缺失则中止。 2. 解析防火墙后端(`--backend auto|iptables|nftables`),如果缺失,则通过你的包管理器(`apt`、`dnf`、 `yum`、`pacman`、`zypper` 或 `apk`)安装 `ipset`+`iptables` 或 `nftables`。 3. 将二进制文件构建到 `/usr/local/bin/simple-blocker`。 4. 将默认配置安装到 `/etc/simple-blocker/config.yaml`(从不 覆盖现有文件)。 5. 安装、启用并启动 `simple-blocker.service` systemd unit。 选项: ``` sudo ./scripts/install.sh --backend nftables # force a backend sudo ./scripts/install.sh --no-enable # install but don't start ``` 安装后,**为你的主机编辑 `/etc/simple-blocker/config.yaml`** 并 重启:`sudo systemctl restart simple-blocker`。 ### 从预构建包安装 (.deb / .rpm) 每个带标签的发布版本都会在 [发布页面](https://github.com/sadeq-n-yazdi/simple-blocker/releases) 上为 Linux **amd64**、**arm64** 和 **armv7** 发布静态二进制文件和软件包。 ``` # Debian / Ubuntu(选择你的架构) curl -LO https://github.com/sadeq-n-yazdi/simple-blocker/releases/latest/download/simple-blocker__linux_amd64.deb sudo apt install ./simple-blocker__linux_amd64.deb # Fedora / RHEL / openSUSE sudo rpm -i simple-blocker__linux_amd64.rpm ``` 该软件包会将二进制文件安装到 `/usr/bin`,systemd unit 安装到系统中,以及 示例配置安装到 `/etc/simple-blocker` 下。首次安装时,它会初始化生成 `/etc/simple-blocker/config.yaml` 并启用(但不启动)该服务。 编辑配置,然后执行 `sudo systemctl start simple-blocker`。 ### 手动构建 ``` make build # -> dist/simple-blocker (embeds version + commit hash) make test # run the test suite sudo ./dist/simple-blocker -config /etc/simple-blocker/config.yaml ``` 随时检查构建元数据: ``` simple-blocker version # or: simple-blocker -version # simple-blocker v0.1.0(commit 1a2b3c4...,构建于 2026-06-28T...,go1.26.4) ``` 发布的二进制文件通过链接器标志进行标记;普通的 `go build` 仍然会 通过 Go 嵌入的 VCS 标记显示提交记录。 ## 配置 YAML 和 JSON 是可互换的 — 通过文件扩展名进行选择。参见 [`config.example.yaml`](config.example.yaml) 和 [`config.example.json`](config.example.json)。 ``` ipset_name: simple_blacklist # name of the ipset / nft set window: 3h # sliding window for counting offenses firewall: mode: internal # internal (pure-Go nftables) | external backend: auto # external only: auto | iptables | nftables chains: [INPUT, DOCKER-USER] # external+iptables only ban_schedule: # highest matching tier wins - { offenses: 2, ban: 10m } - { offenses: 3, ban: 30m } - { offenses: 5, ban: 1h } - { offenses: 7, ban: 24h } sources: - type: journal # journal | docker name: ssh # label shown in logs target: ssh # systemd unit (journal) or container (docker) since: -1d # journal lookback pattern: 'Invalid user \S+ from (?P\d{1,3}(?:\.\d{1,3}){3})' ``` ### 防火墙:内部 vs 外部 `firewall.mode: internal`(默认值)直接从进程内部通过 netlink 管理 nftables — 无需 `nft`、`iptables` 或 `ipset` 二进制文件,只需 带有 nftables 的内核。它会创建一个带有超时 集合和 `ip saddr @set drop` 规则的 `inet simple_blocker` 表。 `firewall.mode: external` 通过 shell 调用主机上的工具,并遵循 `backend` (`auto`/`iptables`/`nftables`) — 可在没有 nftables 的主机上使用,或者当你 需要 iptables `DOCKER-USER` 集成时使用。可在运行时使用 标志覆盖配置: ``` simple-blocker -firewall-mode external -config /etc/simple-blocker/config.yaml ``` 无论哪种方式,进程都需要 `CAP_NET_ADMIN`(以 root 身份或通过 systemd unit 运行)。在关闭时,丢弃规则会被移除,但封禁集合会被保留,因此生效中的 封禁在重启后依然有效。 持续时间使用 Go 语法(`10m`、`3h`、`24h`)。每个源 `pattern` 都必须 包含用于地址的捕获组 — 将其命名为 `(?P...)`;未命名的 第一个组可作为后备被接受。 ### 源模式:内部 vs 外部 每个源都有一个 `mode`: - **docker** — `internal`(默认)仅使用 Go 标准库直接从 **基于 unix socket 的 Docker Engine API**(`/var/run/docker.sock`,使用 `docker_host` 覆盖)读取容器日志 — 无需 `docker` CLI。`external` 则通过 shell 调用 `docker logs -f`。 - **journal** — 始终为 `external`(`journalctl`);`internal` 会被拒绝。 可在运行时使用 `-docker-mode internal|external` 覆盖 docker 源。 ### 添加源 在 `sources` 下追加另一个条目。例如,要封禁在 nginx 容器(内部 docker 模式,默认)中 探测 `.php`/`.env` 文件的 IP: ``` - type: docker name: nginx target: my-nginx-1 mode: internal # or external to use the docker CLI pattern: '(?P\d{1,3}(?:\.\d{1,3}){3})\s.*?"[A-Z]+\s+\S*\.(?:php|env|xml)\S*\s+HTTP/\d\.\d".*\s404\s' ``` ## 运维操作 ``` systemctl status simple-blocker # service health journalctl -u simple-blocker -f # live logs (bans are logged here) ``` ### `status` — 查看被封禁的内容 ``` sudo simple-blocker status # human table sudo simple-blocker status -json # machine-readable ``` `status` 显示**当前被封禁的 IP**(及剩余时间),并且当 daemon 运行时,显示其**违规追踪器**以及它们之间的**差异** — 最 有用的是找出任何超过封禁阈值但不知何故*不*在防火墙 集合中的 IP。它读取 daemon 的只读控制 socket (`control_socket`,默认为 `/run/simple-blocker.sock`);如果 daemon 未 运行,它会退回到直接读取防火墙集合(需要 root 权限)并 予以说明。你仍然可以自己检查原始集合: ``` sudo ipset list simple_blacklist # iptables backend sudo nft list set inet simple_blocker simple_blacklist # nftables backend ``` ### `check` — 模拟运行日志匹配 ``` simple-blocker check # scan recent logs, then exit simple-blocker check -follow # stream live until Ctrl-C simple-blocker check -source nginx # only one source simple-blocker check -actions=false # lines only, no action simple-blocker check -color never # disable IP highlighting ``` `check` 读取每个已配置的源,打印出与 其 pattern 匹配的每一行,并高亮显示**捕获的 IP**,而且 — 默认开启 — 根据你真实的封禁计划模拟出 daemon 将采取的 **行动**(升级违规计数,无实际封禁): ``` [nginx] 45.9.1.2 … "GET /wp-login.php HTTP/1.1" 404 … → offense #2 from 45.9.1.2 within 3h → would ban 10m ``` 它不会封禁任何 IP 且不需要任何权限 — 纯粹用于诊断。 关闭时,服务会移除其丢弃规则但**保留封禁集合**,因此 处理中的封禁在重启后依然有效。 ## 卸载 ``` sudo systemctl disable --now simple-blocker sudo rm /etc/systemd/system/simple-blocker.service /usr/local/bin/simple-blocker sudo rm -r /etc/simple-blocker sudo systemctl daemon-reload # 可选地移除 ban set: sudo ipset destroy simple_blacklist # iptables backend sudo nft delete table inet simple_blocker # nftables backend ``` ## 项目结构 ``` cmd/simple-blocker/ entrypoint (flags, wiring, signal handling) internal/config/ YAML/JSON loading, defaults, validation internal/blocker/ offense tracker (sliding window) + ban engine internal/firewall/ Firewall interface + iptables and nftables backends internal/source/ Source interface + journal and docker tailers scripts/install.sh installer (deps, build, systemd) ``` 扩展点是 `firewall.Firewall` 和 `source.Source` 接口 — 实现其中任意一个即可添加一个后端或一个日志源。 ## 需求 - 带有 systemd 的 Linux - Go(仅构建时需要;二进制文件是静态的,`CGO_ENABLED=0`) - 防火墙:带有 nftables 的内核(内部模式),或 `ipset`+`iptables` / `nftables` 工具(外部模式) - `docker` CLI 仅用于 `external` 模式下的 `docker` 源(内部模式直接使用 API socket) ## 许可证 MIT
标签:EVTX分析, Go, IP封禁, nftables, Ruby工具, 入侵防御, 日志审计, 请求拦截, 运维工具, 防火墙