Knock敲门安全网关技术解析:零信任架构下的iptables IP阻断原理
从官网介绍来看,“Knock 敲门"是一款运行在飞牛 OS 下、同时也支持普通 Linux 部署的安全软件,定位为安全网关产品。但它没有直接说明底层原理,只提到基于零信任授权,仅让经过验证的用户访问公开端口。我们更关心的其实是:它究竟如何阻断恶意 IP。
先看一下官方对设计初衷的说明:
https://docs.fnknock.cn/origin/why-knock
为何设计 Knock 敲门:默认拒绝的零信任理念
购买 NAS 的人,往往希望将照片、文档和私有服务牢牢掌握在自己手里。可一旦将设备暴露在公网上,性质就完全不同了:对你而言,那是家庭数据中心;但在自动化扫描器眼中,它只是一个活跃的 IP、一组开放的端口和一扇没关严的门。
“Knock 敲门"的初心并不是再造一个反向代理面板,也不是堆砌复杂的配置项,而是解决一个基础却长期被忽视的问题:在飞牛 OS 面朝公网之前,先把防盗门装上,再谈访问体验。
在直连模式下,产品仍然支持将公网访问收敛到独立的 7999 端口,在系统底层阻止外部对其他业务端口的直连尝试。用户完成身份验证后,系统通过动态白名单机制,放行当前受信任客户端的 IP。但这种模式更适合少量必须保留原始端口访问的场景,不建议作为大多数新部署的首选。
Knock 不再猜测某个 HTTP 请求"像不像攻击”,而是默认拒绝所有未经授权的连接。这种 Deny-by-default(默认拒绝)机制从网络架构层面直接切断了像 /app-center-static 越权访问这类漏洞的触发链条。正是这种零信任的设计思维,使 Knock 假设自己暴露出去的服务本身就存在漏洞。基于这一前提,可以非常有信心地说,即使你继续安装旧版本、存在漏洞的飞牛 OS,也仍然是安全的。
其代码仓库位于:
https://github.com/kci-lnk/fn-knock-turborepo
下面我们借助代码分析,搞清楚 IP 阻断的工作原理。
是否用到 iptables?
经过对项目代码的详细分析,可以确认:Knock 确实用到了 iptables,但并不是在 Node.js 中直接调用 iptables 命令,而是通过一个 Go 后端服务作为中间层来操作 iptables。下面是完整的架构梳理:

基于 iptables 的防火墙层(Go 后端)
项目在 iptables 里创建了两个自定义链:

Go 后端提供了一组 iptables 操作 API(对应代码中的 go-backend.ts):
- initIptables() → 初始化自定义链和规则
- allowIP(ip) → 将 IP 加入白名单(放行)
- blockIP(ip) → 阻断 IP
- removeIP(ip) → 移除 IP 规则
- blockTCPPortForIP(ip, port) → 阻断特定端口的 IP 访问
- syncSSHFirewall() → 批量同步 SSH 防火墙策略
- cleanIptables() → 清除所有 fn-knock 相关规则
三大攻击检测机制
SSH 安全服务(ssh-security/service.ts)
该模块检测 SSH 暴力破解和非法访问,并将决策直接写入 iptables 进行阻断。
实时监控 SSH 登录日志(支持 journalctl 和 auth.log)
封禁触发条件:
- failed_login_threshold — 失败登录次数超限(例如 5 分钟内失败 N 次)
- cidr_not_allowed — 即便登录成功,但 IP 不在允许的 CIDR 地域范围内
封禁后调用 goBackend.syncSSHFirewall(),将被阻断的 IP 写入 FN-KNOCK-SSH 链
支持自动过期,定时器到期后自动解封
HTTP 扫描检测(scan-detector.ts)
检测恶意扫描行为,在应用层实施阻断。
- 分析请求路径,判断是否为"非常见路径”
- 利用 Redis 有序集合记录每个 IP 的可疑访问记录
- 在配置的时间窗口内(默认 5 分钟),如果非常见路径的访问次数超过阈值(默认 5 次),则加入黑名单
- 黑名单存储在 Redis 中,通过 isBlacklisted() 方法在请求进入时判断是否阻断
- 这部分属于应用层阻断,不走 iptables,而是在 Node.js 请求处理层面直接拒绝
登录退避保护(login-backoff.ts)
防止登录接口被暴力破解。
- 基于 Redis 记录每个 IP 的登录失败次数
- 使用指数退避算法(2^attempts × baseDelay + 随机抖动)
- 基础延迟 2 秒,最大延迟 1 小时,最大尝试次数 8 次
- 超过 8 次失败后触发"硬阻断"(shouldHardBlock)
- 同属于应用层阻断,在认证逻辑中通过 ensureNotBlocked() 检查
白名单机制(whitelist-manager.ts)
白名单 IP 通过 iptables 进行放行:
- 支持三种目标类型:IP、CIDR(如 192.168.1.0/24)、CNAME(域名,自动解析为 IP)
- 添加白名单时调用 goBackend.allowIP(target),写入 iptables 的 FN-KNOCK-FW 链
- 移除时调用 goBackend.removeIP(target),从 iptables 中删除
- 支持手动添加和登录成功后自动添加(source: “auto”)
- 具备自动过期机制,由 Redis 有序集合跟踪过期时间
整体原理示意:

可以看到,SSH 安全服务和主防火墙的 IP 阻断最终是通过 iptables 自定义链实现的(通过 Go 后端间接调用),而 HTTP 扫描检测和登录退避则是在 Node.js 应用层,通过 Redis 状态管理完成。
具体的 IP 阻断方式可以总结为:
- iptables 层:Go 后端直接操作 FN-KNOCK-FW 和 FN-KNOCK-SSH 链,每个被封禁的 IP 都作为一条独立的 iptables 规则存在
- 应用层:通过 Redis 维护黑名单状态
这意味着,每增加一个被封禁的 IP,就会多出一条 iptables 规则。当封禁数量较大(例如几百上千)时,这种逐条规则的做法效率将低于 ipset:ipset 可以将大量 IP 放入一个集合,iptables 只需一条规则匹配该集合,内核层面的查找复杂度是 O(1) 哈希查找,而逐条规则则属于线性匹配。
进一步追溯 Go 后端的核心实现,代码在另一个项目中:
https://github.com/kci-lnk/Go-Reauth-Proxy
Go 后端直接调用 iptables/ip6tables 命令行来操作防火墙,完全没有使用 ipset。具体方式如下:
逐条规则操作(FN-KNOCK-FW 链)
// 允许 IP — 每个IP一条规则
m.runTable(table, "-I", m.Chain, insertPos, "-s", ip, "-j", "ACCEPT")
// 阻断 IP — 每个IP一条规则
m.runTable(table, "-I", m.Chain, insertPos, "-s", ip, "-j", "DROP")
// 移除规则 — 删除ACCEPT和DROP两条
m.runTable(table, "-D", m.Chain, "-s", ip, "-j", "ACCEPT")
m.runTable(table, "-D", m.Chain, "-s", ip, "-j", "DROP")
批量重建(FN-KNOCK-SSH 链)
SSH 安全链使用了 iptables-restore 做批量写入,效率相对较高,但仍然没有使用 ipset:
func (m *Manager) applyTCPPortAccessPolicy(table string, policy TCPPortAccessPolicy) error {
var builder strings.Builder
builder.WriteString("*filter\n")
builder.WriteString("-F " + chain + "\n") // 先清空
// 逐条写入 localCIDRs → blockRules → allowRules → defaultAction
for _, cidr := range localCIDRs { ... }
for _, source := range blockRules { ... }
for _, source := range allowRules { ... }
builder.WriteString("COMMIT\n")
m.runTableRestore(table, builder.String()) // 一次性 commit
}
当前架构的潜在问题

FN-KNOCK-SSH 链因为采用了 iptables-restore 全量重建,暂时还能应对一定规模。但 FN-KNOCK-FW 链的白名单管理是逐条 -I/-D 操作,当白名单 IP 数量较多时,每条规则都是独立的 iptables entry,匹配效率会逐步下降。如果后续要优化,引入 ipset 是一个值得考虑的方向。
大部分用户对 iptables 比较抗拒,尤其是涉及 Docker 混合部署的场景。这个项目的前后端都较为复杂,如果要在内网部署并完全理解其逻辑,可能需要花一些功夫。
“Knock 敲门"还提供了一个非常漂亮的前端管理界面,有兴趣的读者可以访问其官网进一步了解。
