在家庭实验室(homelab)环境中,暴露服务到互联网往往面临安全风险。传统 VPN 方案虽可靠,但需要持久连接,增加了复杂性。而端口敲门(port knocking)技术作为一种隐秘访问控制方式,能通过特定序列的网络“敲门”包来临时开启服务端口。然而,经典端口敲门依赖动态端口扫描,容易受限于防火墙规则的复杂性和状态维护开销。对于静态 homelab 设置,轻量级实现更实用。Knocker 项目正针对此,提供一种基于 HTTP 的敲门序列认证机制,利用 netfilter hooks 和最小状态跟踪,实现远程访问的安全防护,而无需复杂的密钥轮换。
Knocker 的核心在于其单包授权(SPA)网关设计。它通过一个简单的 HTTP POST 请求到 /knock 端点,使用 API 密钥验证身份,并临时将客户端 IP 添加到白名单中。该白名单的有效期由 TTL(Time-To-Live)参数控制,默认可配置为数分钟到数小时。这避免了传统端口敲门中多包序列的检测开销,转而使用用户空间的轻量状态管理,仅跟踪 IP 和过期时间。证据显示,这种设计在 homelab 中特别高效,因为它不要求服务端持续监听隐秘端口,而是集成到现有反向代理或防火墙中。“Knocker is a configurable, and self-hosted service that provides an HTTP based 'knock-knock' single-packet authorization (SPA) gateway for your Homelab”——其 GitHub 描述强调了这种低开销特性。
要落地 Knocker,首先需准备 Docker 环境,因为项目以容器化部署为主。下载 docker-compose.yml 和 knocker.example.yaml 文件,重命名为 knocker.yaml,并修改默认 API 密钥为随机强密钥(如使用 openssl rand -hex 32 生成)。在 YAML 中配置 trusted_proxies 列表,确保匹配反向代理的 Docker 网络子网,例如默认的 172.18.0.0/16。启用 Firewalld 集成时,设置 firewalld.enabled: true,并调整 monitored_ports 列表,如添加 22(SSH)或 8096(Jellyfin)。容器需以 root 运行,并挂载宿主 D-Bus 套接字:-v /run/dbus:/run/dbus:ro。启动命令为 docker-compose up -d,这将拉取最新镜像(标签 latest),并运行 knocker 和 caddy 服务。验证部署:curl -H "X-Api-Key: your_key" https://knock.your-domain.com/knock,应返回白名单条目和过期时间。
与反向代理的集成是 Knocker 的关键应用场景。以 Caddy 为例,在 Caddyfile 中定义 (knocker_auth) 片段:forward_auth knocker:8000 { uri /verify copy_headers X-Forwarded-For }。然后为受保护服务导入该片段,如 jellyfin.your-domain.com { import knocker_auth reverse_proxy jellyfin:8096 }。当用户访问时,Caddy 先调用 /verify 端点检查 IP 白名单,若未授权返回 401,拒绝连接。这实现了应用层的访问控制,无需修改服务本身。参数建议:对于 homelab,设置 API 密钥 TTL 为 3600 秒(1 小时),允许远程白名单(allow_remote_whitelist: true)以支持多设备场景,但限制为 /24 CIDR 以防滥用。排除路径如 /health 以绕过认证,确保监控端点始终可用。
进一步提升安全性,可启用 Firewalld 集成,这利用 netfilter 的 rich rules 实现网络层控制。Knocker 创建专用 zone(如 knocker),优先级高于默认(设置 priority: 100),并添加 DROP 规则阻塞 monitored_ports。敲门成功后,动态插入 ACCEPT 规则:firewall-cmd --zone=knocker --add-rich-rule='rule family="ipv4" source address="client_ip" port protocol="tcp" port="22" accept timeout="3600"'。规则自动过期,减少手动清理。落地清单:1. 安装 FirewallD 2.0+(Ubuntu 24.04 默认支持);2. 在 docker-compose.yml 中添加 --privileged 和 D-Bus 挂载;3. 配置 whitelist.json 路径为持久卷(如 -v ./data:/app/data);4. 监控日志:journalctl -u firewalld -f,检查规则变化。风险点:Docker 已发布端口(如 -p 22:22)与 Firewalld 冲突,建议使用 host 网络模式或避免发布端口。
在实际 homelab 中,Knocker 的客户端工具增强了可用性。Knocker-Web 是一个静态 PWA,支持页面重载时自动敲门;CLI 工具(Go 编写)可后台运行,检测 IP 变化触发敲门;Android App(React Native)提供移动端支持。这些工具使用相同 API 密钥,确保无缝集成。参数优化:对于动态 IP 用户,CLI 的 background_knock 间隔设为 5 分钟,避免频繁请求。状态跟踪最小化,仅维护 JSON 文件的白名单(内存 + 持久化),开销低于 1MB。即使在 ARMv7 设备上,Docker 镜像也兼容,适合 Raspberry Pi homelab。
潜在风险包括 API 密钥泄露,导致 unauthorized 白名单。缓解:定期轮换密钥(虽项目避免复杂轮换,但手动支持),并启用 always_allowed_ips 为静态 IP(如家庭宽带)。另一个限制是 IPv6 支持虽完整,但需配置 trusted_proxies 包含 ::/0 子网。监控要点:使用 Prometheus 刮取 /metrics 端点(默认启用),跟踪白名单添加/过期计数和 401 失败率。若失败率 >5%,检查 trusted_proxies 配置。回滚策略:若集成问题,临时禁用 forward_auth,重置为静态防火墙规则。
总体而言,Knocker 通过简化的敲门机制和 netfilter 集成,提供 homelab 安全的平衡点。其低开销设计(无多包序列,无动态密钥)区别于高级 iptables/fail2ban 方案,适合静态环境。实施后,服务暴露面最小化,仅在敲门期开放。
资料来源: