knockd通过端口敲门使ssh端口在序列正确前完全不响应扫描,实现真正隐身;其启动失败主因是配置中缺失interface参数,现代系统需显式指定如ens33等网卡名,否则默认查eth0导致静默失败。

knockd 能让 SSH 端口在敲对序列前完全不响应任何扫描,不是“隐藏端口”,而是让 iptables 规则根本不存在——攻击者连 22 端口是否监听都探测不到。
knockd 启动失败:/etc/knockd.conf 中 missing interface 导致服务无法启动
默认配置里没指定网卡名,knockd 就会去查 eth0,但现代系统(Ubuntu 22.04+、CentOS 8+、Debian 12)基本用 ens33、enp0s3 或 ens160 这类命名。不显式声明,systemctl start knockd 会静默失败,journalctl -u knockd 显示 “interface eth0 not found”。
- 先查真实网卡名:
ip -br a | grep UP,找带 IP 的那一行(比如ens160) - 在
/etc/knockd.conf的[options]段顶部加一行:interface = ens160(替换成你自己的) - 别漏掉
UseSyslog,否则日志全丢进黑洞,调试时只能靠knockd -D -v手动前台运行看输出
敲门序列不生效:tcpflags 和 seq_timeout 配合不当
常见现象是敲完三端口,iptables -L INPUT -n 里没看到新规则,SSH 依然连不上。问题往往出在两个参数上:
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
-
tcpflags = syn表示只认纯 SYN 包(无数据),但很多客户端工具(比如浏览器访问http://ip:7000)发的是完整 HTTP 握手,带 ACK+SYN 或数据,knockd 直接忽略 -
seq_timeout = 5是指整个序列必须在 5 秒内完成,不是每个端口间隔 5 秒。如果网络延迟高或敲门命令执行慢(比如用telnet手动敲),中间卡顿超时就重置计数器 - 建议调成
seq_timeout = 15,并统一用knock工具(非 telnet/browser):例如knock -v your-server-ip 7000 8000 9000
iptables 命令执行失败:-A 和 -D 不匹配导致关门失败
配置里 [openSSH] 用 -A INPUT 追加规则,[closeSSH] 用 -D INPUT 删除,但 iptables 删除规则必须和添加时**完全一致**(包括顺序、参数、空格)。一旦中间有人手动改过 iptables,或者 knockd 重启过,-D 就会报错 “Bad rule (does a matching rule exist in that chain?)”,关门动作失效,22 端口一直开着。
- 更稳妥的写法是把 open/close 改成基于链名+注释管理:
command = /sbin/iptables -I INPUT 1 -s %IP% -p tcp --dport 22 -m comment --comment "knock-ssh" -j ACCEPT,关门时用iptables -D INPUT -s %IP% -p tcp --dport 22 -m comment --comment "knock-ssh" -j ACCEPT - 或者直接用
iptables-save | grep -v "knock-ssh"+iptables-restore彻底清理,但性能开销略大 - 务必确认
command路径正确:/sbin/iptables在某些发行版(如 CentOS Stream)可能在/usr/sbin/iptables,用which iptables查准
firewalld 和 iptables 冲突:knockd 规则被覆盖或不生效
如果你的系统启用了 firewalld(默认在 CentOS/RHEL/Fedora),它会接管 iptables 链,knockd 直接调 iptables 命令写的规则会被 firewalld 下次 reload 时清掉,或者压根不生效。
- 最干净的做法是停用 firewalld:
sudo systemctl stop firewalld && sudo systemctl disable firewalld - 如果必须保留 firewalld,就得换方案:用
firewall-cmd --direct替代 iptables 命令,例如:command = firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -s %IP% -p tcp --dport 22 -j ACCEPT,但注意--permanent不会立即生效,得配合--runtime-to-permanent或 reload,复杂度陡增 - 验证是否冲突:敲门后执行
iptables -L INPUT -n --line-numbers,看规则是否真出现在链里;再执行firewall-cmd --list-all,确认里面没有 22 端口
真正容易被忽略的是时间窗口与连接保持的关系:knockd 开放 22 端口后,iptables 规则不会自动过期,它靠的是你后续的 [closeSSH] 序列或人工清理。如果你只开不关,又没 fail2ban 配合,那一次成功敲门等于永久开门——这反而比裸开 22 更危险。










