SSem SecuMon 免费指南
从一台个人服务器起步 · 2026 年 10 月版
准备中安装包的发布正在准备中。
本指南先行公开准备工作、安装步骤以及运维中需要了解的事项。发布开始后,下载地址会写在这里。
1. 准备工作
| 项目 | 要求 |
|---|---|
| 要保护的服务器 | Linux(systemd)+ fail2ban · nftables · sqlite3。amd64 或 arm64。已在 Ubuntu 22.04 · CentOS 8 上验证。 |
| 控制台服务器 | 1 台。JDK 21 · Tomcat 11 · PostgreSQL 17。用 Docker 启动最简单。 |
| 网络 | 各服务器需能通过 HTTPS 访问控制台地址。服务器无需开放任何入站端口。建议将控制台置于 VPN 或内网之后。 |
| 时钟 | 所有服务器和控制台的时钟都需用 NTP 同步。签名时间偏差超过 60 秒,请求即会被拒绝。 |
| 证书 | 控制台使用的 HTTPS 证书(例如 Let's Encrypt)。登录 Cookie 只通过 HTTPS 传输,因此无法通过明文 HTTP 登录。 |
先在每台要保护的服务器上安装软件包。
# Debian · Ubuntu apt-get update && apt-get install -y fail2ban nftables sqlite3 # RHEL · Rocky · CentOS dnf install -y epel-release && dnf install -y fail2ban nftables sqlite systemctl enable --now fail2ban
2. 启用 fail2ban 指数封禁
设置为同一 IP 再犯次数越多,封禁时间越长。SecuMon 根据这些倍数计算“当前处于第几级”和“下次会被封禁多久”。
# /etc/fail2ban/jail.local [DEFAULT] bantime = 1h findtime = 10m maxretry = 5 bantime.increment = true bantime.multipliers = 1 2 4 8 16 32 64 168 bantime.maxtime = 168h ignoreip = 127.0.0.1/8 ::1 <你的 VPN IP 段> # /etc/fail2ban/fail2ban.local — 屡犯记录保留 60 天(默认仅 1 天,一天后又会被当作初犯) [DEFINITION] dbpurgeage = 60d
按上述设置,封禁时长如下。fail2ban 会加入少量随机时间,因此实际值会略有出入。
| 累计封禁 | 1 次 | 2 次 | 3 次 | 4 次 | 5 次 | 6 次 | 7 次 | 8 次及以上 |
|---|---|---|---|---|---|---|---|---|
| 封禁时长 | 1 小时 | 2 小时 | 4 小时 | 8 小时 | 16 小时 | 32 小时 | 64 小时 | 7 天 |
请务必把你自己的访问路径(如 VPN IP 段)加入 ignoreip。这样就不会因为输错几次密码,而被自己的服务器封禁。
3. 安装控制台
3-1. 机密文件
机密值不写在代码或环境变量中,而是作为文件统一放在一个目录里。控制台容器会以只读方式将该目录挂载到 /App/secrets。
mkdir -p /srv/secumon/secrets/tls && chmod 700 /srv/secumon cd /srv/secumon/secrets openssl rand -hex 24 > db_password openssl rand -base64 18 > admin_password # 首次登录密码(账户名 admin) openssl genpkey -algorithm ed25519 -out console_ed25519.key openssl pkey -in console_ed25519.key -pubout -out console_ed25519.key.pub # 文件设为 644,以便容器账户读取 — 由上级目录的 700 负责保护 chmod 644 db_password admin_password console_ed25519.key console_ed25519.key.pub
| 文件 | 用途 | 缺少时 |
|---|---|---|
db_password | 数据库连接 | 控制台无法启动 |
admin_password | 首个管理员账户 admin 的密码 | 账户不会被创建,因而无法登录 |
console_ed25519.key · .pub | 命令签名 | 只能查看,无法执行 |
abuseipdb.key | AbuseIPDB API 密钥(可选) | 无法使用举报和信誉查询 |
telegram.env | Telegram 通知(可选) | 不会发送通知 |
tls/cert.pem · chain.pem · privkey.pem | 控制台 HTTPS 证书 | 无法通过 HTTPS 访问 |
仅凭 console_ed25519.key 这一个文件,就能签发对所有服务器都有效的命令。请勿将此文件放在代码仓库或共享网盘中,务必单独保管。
3-2. 数据库
数据库端口不对外开放。控制台在同一 Docker 网络内通过容器名连接数据库。
docker network create secumon-net docker run -d --name secumon-db --network secumon-net --restart unless-stopped \ -e POSTGRES_DB=secumon -e POSTGRES_USER=secumon \ -e POSTGRES_PASSWORD_FILE=/run/secrets/db_password \ -v /srv/secumon/secrets/db_password:/run/secrets/db_password:ro \ -v secumon_pgdata:/var/lib/postgresql/data \ postgres:17
数据表和初始数据由控制台在首次启动时自动创建,无需另外用 psql 导入表结构。
3-3. 控制台配置
控制台是运行在 Tomcat 11 上的 Web 应用。运行方法将随发布包一同公开,这里先整理需要事先确定的环境变量。
| 环境变量 | 默认值 | 含义 |
|---|---|---|
F2B_DB_URL | jdbc:postgresql://…:5432/secumon | 数据库地址。使用容器名填写。 |
F2B_CANONICAL_HOST | 必须改为你自己的值 | 你的控制台域名。通过明文 HTTP 或其他地址访问时,会跳转到该地址的 HTTPS。 |
F2B_PROTECTED_CIDRS | 必须改为你自己的值 | 绝不封锁的 IP 段 — 你的 VPN · 内网 · 服务器公网 IP。私有网络和回环地址无论此值如何,始终受保护。 |
F2B_BLOCK_TTL_DAYS | 30 | IP 段封锁的默认期限(天)。0 表示永久。 |
F2B_AUTO_BLOCK_ENABLED | true | 开启或关闭屡犯 IP 自动封锁。 |
F2B_AUTO_BLOCK_THRESHOLD | 3 | 从第几次封禁开始自动封锁。 |
F2B_AUTO_BLOCK_TTL_DAYS | 30 | 自动封锁的期限(天)。 |
F2B_FEED_REFRESH_HOURS | 24 | 重新下载公开封锁列表和国家列表的周期(小时)。 |
F2B_BAN_MULTIPLIERS | 1 2 4 8 16 32 64 168 | 须与 jail 配置中的倍数完全一致。 |
F2B_ABUSE_DAILY_LIMIT | 1000 | AbuseIPDB 每日使用上限。 |
启动后检查状态。看到 "db":"ok" 即表示正常。
curl -s https://<控制台地址>/api/health
4. 注册服务器 — 代理程序
- 以
admin登录控制台,在目标标签页中输入服务器名称,然后点击注册 + 签发令牌。 - 界面上会显示目标 ID 和一次性令牌。令牌只在此时显示一次,15 分钟后过期。
- 在要保护的服务器上以 root 身份运行安装脚本。
# 在要保护的服务器上执行(root) tar xzf agent-amd64.tgz && cd agent ./install-agent.sh --console https://<控制台地址> \ --target-id <目标 ID> --token <一次性令牌> journalctl -u secumon-agent -f # 30 秒内出现下面这样的一行即为正常
正常时会输出类似这样的一行 secumon-agent: 2026/10/06 16:40:12 전송 완료 — jail 2개, 밴 5건
安装脚本只做以下几件事,不会开放任何防火墙端口。
- 创建一个无法登录的专用账户
f2bagent— 代理程序不以 root 运行。 - 只允许通过 sudo 调用一个 root 权限包装脚本
/usr/local/sbin/f2b-agent-exec。 - 代理程序的签名密钥在该服务器上生成,私钥不会经网络传出。
- 向控制台注册后,以
secumon-agent服务常驻运行。
控制台地址请勿使用含下划线(_)的主机名。Tomcat 11 会以违反规范为由拒绝。请先用 getent hosts <控制台域名> 确认服务器能否解析控制台域名。
如果注册已完成、但之后的步骤失败了,排除原因后原样重新运行同一条命令即可。已注册的代理程序不会再次使用令牌。
要移除服务器,请在控制台中将其停用(该代理程序的请求会立即被拒绝),然后在服务器上运行 systemctl disable --now secumon-agent。
5. 如何看懂界面
- 仪表盘 — 所有服务器的当前封禁、累计封禁、屡犯 IP 和趋势。如果服务器卡片上的“最后接收”远超 30 秒,请检查该服务器的代理程序。
- 封禁列表 — 当前被拦截的 IP,同时显示屡犯等级、剩余时间和国家。国家信息来自控制台内置的查询表。
- IP 详情 — 该 IP 被封禁的服务器、封禁历史、下次封禁的预计时长、AbuseIPDB 信誉。
“当前封禁”读取自 fail2ban 当前实际生效的封禁列表,“屡犯次数”则单独读取自 fail2ban 的封禁记录。因此,已解除的封禁不会被误显示为当前封禁。
6. 封禁 · 解封 · IP 段封锁
- 封禁 · 解封需要操作员及以上角色。封禁可针对任意 IP;未选择 jail 时默认为
sshd。 - IP 段封锁仅限管理员。必须再次输入要封锁的 IP 段才会执行,大于 IPv4 /16 · IPv6 /48 的会被拒绝。默认 30 天后自动解除。
- 可以一次对多个 IP 段 × 多台服务器下发封锁。只有全部通过检查才会下发任何一条 — 因为只生效一半的状态最危险。
- 命令必须由服务器上的代理程序在 60 秒内取走才会执行。结果可在执行标签页的命令历史中查看,分为完成、失败、过期。
如果封错了,可在控制台的执行 → 解除封锁中解除。若情况紧急到无法进入控制台,就直接在该服务器上删除。
# 仅删除一个 IP 段 nft delete element inet f2b_console blocklist4 '{ 203.0.113.0/24 }' # 删除 SecuMon 添加的全部封锁(fail2ban 规则在另一张表中,不受影响) nft delete table inet f2b_console
7. 自动封锁
屡犯 IP 自动封锁
每 5 分钟挑出累计被封禁 3 次及以上的 IP,在所有服务器上封锁 30 天。这是唯一无需人工批准就会修改防火墙的功能,因此加了多重限制。
- 只封锁单个 IP(
/32·/128),不封锁 IP 段。 - 跳过受保护 IP 段。每次最多只下发 20 条。
- 同一 IP 不会重复升级,所有操作都记录到审计日志并通知到 Telegram。
要关闭此功能,请为控制台设置 F2B_AUTO_BLOCK_ENABLED=false 后重启。被误封的 IP 请先用解除封锁解除,再删除其升级记录,之后才会被重新判定。
docker exec secumon-db psql -U secumon -d secumon -c "DELETE FROM auto_block WHERE ip = '<IP>'"
公开封锁列表
在封锁订阅源标签页中开启。初始时两者均为关闭状态。
- Spamhaus DROP — 被劫持或专用于犯罪活动的 IP 段。不可能产生正常流量,几乎不必担心误封。
- FireHOL level1 — 未使用的地址和已确认的恶意 IP 段。其中也包含私有网络,因此控制台会先滤掉与受保护 IP 段重叠的条目再下发。
每天重新下载一次,内容不变则不会重复下发到服务器。从列表中移除的 IP 段会在下次更新时自动解除。
8. 国家封锁 — 启用之前
需要全球访问的服务,不能按国家封锁。
- 权威 DNS 服务器 — 全球的解析器都要能访问,你的域名才能被解析。SecuMon 始终放行 53 端口。
- 邮件接收(25)· VPN — 一旦封锁,邮件会中断,你在海外也无法连回自己的服务器。这类服务器请不要启用国家封锁。
- 搜索引擎爬虫 — 封锁大国时,搜索引擎爬虫也会一并被拦截,网站可能从搜索结果中消失。
在国家封锁标签页中选择国家后,会先显示该国的 IP 段数量。应用后立即下载列表,30 秒内写入所有服务器;关闭时则删除该国的列表。大国的 IP 段可多达数万个。
即使某个国家来的攻击很多,实际上往往也只是该国的少数 IP 段或租用的服务器。封锁之后,攻击者会换到其他国家的服务器。请把国家封锁视为与公开封锁列表、屡犯自动封锁配合使用的辅助手段。
SecuMon 在防火墙规则的最前面放行已建立连接的响应。如果没有这条规则,你的服务器向该国服务(软件包镜像 · 通知 API · 证书签发)发起的连接,其响应也会被拦截。
9. AbuseIPDB · Telegram
AbuseIPDB
将 abuseipdb.key 放入机密目录即可启用。密钥只存在于控制台服务器上,不会出现在界面、数据库或任何服务器上。
- 只能举报当前正被封禁或最近 30 天内被封禁过的 IP — 不能举报任意 IP。
- 同一 IP 在 15 分钟内不会重复举报。每日配额由控制台自行计数。
- 举报类别根据 jail 名称确定 — ssh → 18 · 22,Web(apache · nginx)→ 18 · 21,邮件 → 18 · 11,其他 → 18。
Telegram
# /srv/secumon/secrets/telegram.env
TELEGRAM_TOKEN=<机器人令牌>
TELEGRAM_CHAT_ID=<聊天 ID>
通知屡犯自动封锁和公开列表的变更,完整列表以附件文件发送。没有变化时不发通知 — 如果每天都收到“无变更”,真正重要的通知反而容易被忽略。
10. 账户 · 两步验证
| 角色 | 可执行的操作 |
|---|---|
VIEWER 只读 | 查看仪表盘 · 封禁列表 · IP 详情 · 命令历史 |
OPERATOR 操作员 | + 封禁 · 解封 · AbuseIPDB 举报与信誉查询 |
ADMIN 管理员 | + IP 段封锁 · 服务器注册 · 封锁订阅源 · 国家封锁 · 用户 · 审计日志 |
- 首次登录使用
admin和admin_password文件中的密码。登录后请在我的账户中修改密码。 - 在我的账户 → 两步验证中,用身份验证器应用扫描二维码,或手动输入密钥。同一个验证码不能使用两次。
- 密码输错 5 次将锁定 15 分钟;同一 IP 每分钟最多尝试 10 次。30 分钟无任何操作会自动退出登录。
如果丢失了身份验证器应用,无法在界面上解除,需要由能访问控制台服务器的人直接在数据库中解除。
docker exec secumon-db psql -U secumon -d secumon -c \ "UPDATE app_user SET totp_enabled=false, totp_secret=NULL, totp_last_counter=0 WHERE username='admin';"
11. 备份 · 密钥管理
# 数据库 — 密码是哈希,注册令牌也只以哈希形式保存 docker exec secumon-db pg_dump -U secumon secumon | gzip > secumon-$(date +%F).sql.gz # 机密目录 — 这才是真正的机密。与数据库备份分开存放 tar czf secumon-secrets-$(date +%F).tgz -C /srv/secumon secrets
- 更换控制台签名密钥后,所有代理程序都会拒绝命令。如已更换,请对每台服务器按以下顺序重新注册:停用 → 重新签发令牌 → 删除服务器上的
/etc/secumon/agent.json·agent_ed25519.key→ 重新安装。 - 定期检查:每天查看服务器状态和失败的命令;每周查看审计日志中的拒绝记录,以及未启用两步验证的账户。
12. 故障排查
代理程序和控制台的消息以韩语输出。请在日志中直接搜索下表中以代码样式显示的文字。
| 现象 | 原因 | 处理方法 |
|---|---|---|
代理程序日志 등록되지 않았거나 비활성 상태인 타겟 | 服务器已在控制台中被停用 | 重新获取令牌并重新注册 |
代理程序日志 요청 시각 편차가 허용치를 넘습니다 | 服务器时钟偏差超过 60 秒 | 用 NTP 同步时钟 |
代理程序日志 이미 사용된 nonce | 同一请求被重复发送 | 这是正常的防御。若持续出现,请排查网络重复发送 |
命令结果 거부: 만료된 명령 | 代理程序未能在 60 秒内取走命令 | 检查服务器上 secumon-agent 的状态后重新执行 |
命令结果 거부: 서명이 유효하지 않음 | 更换控制台签名密钥后未重新注册 | 按第 11 节的顺序重新注册 |
| 服务器卡片的最后接收时间停滞 · 日志中断 | 代理程序卡住 | systemctl restart secumon-agent |
| 已开启国家封锁,但服务器上未生效 | 代理程序日志中没有这一行: 국가 차단 적용 | 确认代理程序是否为最新版本,并查看日志中的错误 |
| 登录状态反复失效 | 通过非 HTTPS 地址访问 | 改用控制台的 HTTPS 地址访问 |
如有其他疑问,请发送邮件至 halo@levelupsoft.com。
fail2ban · nftables · AbuseIPDB · Spamhaus · FireHOL · Telegram · Let's Encrypt 归各自所有者所有,SSem SecuMon 与其均无合作关系,也未获得其背书。