通过 SSH 审计远程 Linux 主机是否存在 Copy Fail 和 Dirty Frag 内核模块漏洞,并可选择应用缓解措施:
| CVE | 名称 | 受影响的模块 |
|---|---|---|
| CVE-2026-31431 | Copy Fail | algif_aead |
| CVE-2026-43284 | Dirty Frag (IPsec) | esp4, esp6, ipcomp4, ipcomp6, xfrm_user |
| CVE-2026-43500 | Dirty Frag (RxRPC) | rxrpc, kafs |
对于每个受影响的模块,vcheck 会报告它当前是否已加载、是否内置于运行的内核中、在内核日志中是否有过去的痕迹、是否有活跃的 AF_ALG 套接字(仅针对 Copy Fail),以及是否已在 /etc/modprobe.d/ 下被列入黑名单。
使用 -fix 时,vcheck 会报告初始状态,为尚未被列入黑名单的任何模块写入一个 cve-XXXX-XXXXX-disable.conf 片段,然后重新执行检查并报告最终状态。使用 -fix -unload 时,vcheck 还会尝试卸载修复前已加载的受影响模块,然后通过最终扫描验证它们是否仍在加载。使用 -fix -rebuild-initramfs 时,vcheck 会在写入片段后仅为当前运行的内核重建 initramfs,从而将黑名单嵌入下一次启动映像中。较旧的内核条目保留其原始 initramfs 作为回退。
-fix务必先运行不带 -fix 的 vcheck。 阅读报告并确认受影响模块在此主机上可以安全禁用后,再使用 -fix 重新运行。禁用合法工作负载所依赖的内核模块可能会影响用户并破坏应用程序。
特别需要注意:
mitigated 或 module not blacklisted(没有 VULNERABLE 或 blacklisted but currently loaded 行)– 才可将 -fix 视为安全。已加载的模块几乎总是意味着主机上某些内容正在活动使用它;在黑名单之前确认这一点。esp4、esp6、ipcomp4、ipcomp6、xfrm_user)是所有 IPsec/strongSwan/基于 IPsec 的 WireGuard/IKE 部署所必需的。ipcomp4/ipcomp6 模块实现了 IPComp 负载压缩,即使在未明确配置时也可能作为 IPsec SA 的一部分自动协商。不要在 VPN 网关、IPsec 端点或任何 ip xfrm policy 返回规则的主机上将它们列入黑名单。请注意,xfrm_algo 框架模块特意在此列表中 — 根据供应商指南(Red Hat、Ubuntu、AWS),阻止 ESP 和 IPComp 协议模块以及 netlink 配置接口就足够了,而将 列入黑名单会破坏所有其他 xfrm 转换,没有任何额外好处。vcheck 写入的黑名单片段仅在模块加载时生效(通常是下次启动,或在系统空闲时执行 modprobe -r <module>)。一个已经加载的模块即使在 -fix 之后也会继续运行——vcheck 会将其报告为 blacklisted but currently loaded; run 'modprobe -r' or reboot。将 -unload 与 -fix 一起传递时,vcheck 会在写入黑名单片段后为已加载的受影响模块运行 modprobe -r。仅当你已确认这些模块可以从运行中的内核安全移除时再使用它。
将 -rebuild-initramfs 与 -fix 一起传递时,会为当前运行的内核独有重新生成 initramfs(Debian/Ubuntu 上为 update-initramfs -u -k $(uname -r),RHEL/Fedora 上为 dracut -f --kver $(uname -r))。其他已安装的内核保留其现有 initramfs 不变,因此如果重启后出现问题,你可以从启动菜单中选择较旧的内核条目进行恢复。未来的内核安装会从当前的 /etc/modprobe.d/ 状态重建自己的 initramfs,因此黑名单会自动传播,无需重新运行 vcheck。如果既不存在 update-initramfs 也不存在 dracut(例如 Arch、Alpine、不可变镜像),vcheck 会发出警告并继续——请在重启前使用发行版工具手动重建。
重建可能需要几分钟(尤其是在驱动程序众多的主机上使用 dracut),这可能会超过诊断用的 -command-timeout。它使用自己的 -initramfs-timeout(默认 10m)来运行,以便重建获得所需的时间,而快速检查保持其紧凑的预算。对于慢速硬件,可增大 -initramfs-timeout,或传入 0 完全禁用超时。在长时间运行的远程命令期间,vcheck 默认每 30s 发送一次 SSH 保活请求,以防止 NAT/防火墙空闲计时器断开连接。使用 -ssh-keepalive 调整此值,或传入 0 禁用它。
Homebrew(macOS):
brew install --cask krisiasty/tap/vcheck
预编译二进制文件 适用于 Linux、macOS 和 Windows,发布在 releases 页面 上。
从源代码编译(需要 Go 1.26+):
go install github.com/krisiasty/vcheck@latest
vcheck -host HOST [flags]
-agent、-identity 或 -password 中至少有一个必须能产生可用的身份验证方法。方法按列出的顺序尝试。
目标主机上需要 sudo 权限。如果已配置无密码 sudo,工具将静默进行;否则会提示输入一次密码(输入被隐藏),并通过 sudo -S 为后续每个命令提供密码。
$ vcheck -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF mitigated cve=CVE-2026-31431 module=algif_aead
INF mitigated cve=CVE-2026-43284 module=esp4
INF mitigated cve=CVE-2026-43284 module=esp6
INF mitigated cve=CVE-2026-43284 module=ipcomp4
INF mitigated cve=CVE-2026-43284 module=ipcomp6
INF mitigated cve=CVE-2026-43284 module=xfrm_user
INF mitigated cve=CVE-2026-43500 module=rxrpc
INF mitigated cve=CVE-2026-43500 module=kafs
$ vcheck -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF mitigated cve=CVE-2026-31431 module=algif_aead
ERR VULNERABLE cve=CVE-2026-43284 module=esp4 loaded=true
ERR module not blacklisted cve=CVE-2026-43284 module=esp6
ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp4
ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp6
ERR module not blacklisted cve=CVE-2026-43284 module=xfrm_user
ERR module not blacklisted cve=CVE-2026-43500 module=rxrpc
ERR module not blacklisted cve=CVE-2026-43500 module=kafs
-fix——首次运行$ vcheck -fix -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF findings before fix
INF mitigated cve=CVE-2026-31431 module=algif_aead
ERR VULNERABLE cve=CVE-2026-43284 module=esp4 loaded=true
ERR module not blacklisted cve=CVE-2026-43284 module=esp6
ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp4
ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp6
ERR module not blacklisted cve=CVE-2026-43284 module=xfrm_user
ERR module not blacklisted cve=CVE-2026-43500 module=rxrpc
ERR module not blacklisted cve=CVE-2026-43500 module=kafs
INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43284-disable.conf modules="[esp4 esp6 ipcomp4 ipcomp6 xfrm_user]"
INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43500-disable.conf modules="[rxrpc kafs]"
INF re-scanning after fix snippets_written=2
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF findings after fix
INF mitigated cve=CVE-2026-31431 module=algif_aead
ERR blacklisted but currently loaded; run 'modprobe -r' or reboot cve=CVE-2026-43284 module=esp4
INF mitigated cve=CVE-2024-43284 module=esp6
INF mitigated cve=CVE-2026-43284 module=ipcomp4
INF mitigated cve=CVE-2026-43284 module=ipcomp6
INF mitigated cve=CVE-2026-43284 module=xfrm_user
INF mitigated cve=CVE-2026-43500 module=rxrpc
INF mitigated cve=CVE-2026-43500 module=kafs
黑名单已就位,但 esp4 在写入片段之前已加载到内核中。重启或在目标主机上运行 sudo modprobe -r esp4 以完全清除它。
$ vcheck -fix -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF findings before fix
INF mitigated cve=CVE-2026-31431 module=algif_aead
ERR blacklisted but currently loaded; run 'modprobe -r' or reboot cve=CVE-2026-43284 module=esp4
INF mitigated cve=CVE-2026-43284 module=esp6
INF mitigated cve=CVE-2026-43284 module=ipcomp4
INF mitigated cve=CVE-2026-43284 module=ipcomp6
INF mitigated cve=CVE-2026-43284 module=xfrm_user
INF mitigated cve=CVE-2026-43500 module=rxrpc
INF mitigated cve=CVE-2026-43500 module=kafs
INF fix: nothing to do — all affected modules already blacklisted
modprobe -r esp4 之后$ vcheck -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF mitigated cve=CVE-2026-31431 module=algif_aead
INF mitigated cve=CVE-2026-43284 module=esp4
INF mitigated cve=CVE-2026-43284 module=esp6
INF mitigated cve=CVE-2026-43284 module=ipcomp4
INF mitigated cve=CVE-2026-43284 module=ipcomp6
INF mitigated cve=CVE-2026-43284 module=xfrm_user
INF mitigated cve=CVE-2026-43500 module=rxrpc
INF mitigated cve=CVE-2026-43500 module=kafs
-rebuild-initramfs$ vcheck -fix -rebuild-initramfs -host host.example.com -identity ~/.ssh/id_ed25519
...
INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43284-disable.conf modules="[esp4 esp6 ipcomp4 ipcomp6 xfrm_user]"
INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43500-disable.conf modules="[rxrpc kafs]"
INF rebuilding initramfs for running kernel timeout=10m0s
INF initramfs rebuilt for running kernel tool=update-initramfs
INF re-scanning after fix snippets_written=2
...
仅重建当前运行内核的 initramfs。其他已安装的内核保留其现有 initramfs,因此启动菜单中的较旧条目在新建的 initramfs 引发问题时可作为有效的回退。在既没有 update-initramfs 也没有 dracut 的主机上,vcheck 会记录 WRN no supported initramfs tool found ... 并继续执行。
-insecure$ vcheck -insecure -host host.example.com -identity ~/.ssh/id_ed25519
WRN host key not in known_hosts; accepting due to -insecure host=host.example.com:22 remote=192.0.2.42:22 fingerprint=SHA256:AAAAEXAMPLEfingerPrint000000000000000000000
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
...
-insecure 接受尚未在 known_hosts 中的主机。如果主机已记录但呈现不同的密钥,连接仍然会失败——该标志仅适用于“首次接触”的覆盖,并非用于抑制已知主机的中间人警告。
lsmod 的输出,并将模块名称与第一列匹配。/lib/modules/$(uname -r)/modules.builtin 和 /sys/module,因为 modprobe 片段无法禁用编译到运行内核中的代码。/etc/modprobe.d/ 下的每个文件(grep -rE),查找 install <module> /bin/false 指令——与 vcheck 使用 -fix 写入的形式相同。其他禁用形式(例如 blacklist)不会被识别。journalctl -k,回退到 /var/log/kern.log;每个模块保留最后五条匹配行。传入 -skip-logs 可跳过此步骤。algif_aead): ss -p --af-alg 列出打开的 套接字;除标题行以外的任何输出都计为活跃使用。所有命令通过 sudo 运行,并由 -command-timeout 限定时间——需要特权访问才能读取 /var/log/kern.log、列出 AF_ALG 套接字以及在 /etc/modprobe.d/ 下写入内容。使用 -unload 时,还需要特权访问才能运行 modprobe -r。使用 -rebuild-initramfs 时,vcheck 运行 update-initramfs -u -k $(uname -r)(Debian/Ubuntu)或 dracut -f --kver $(uname -r)(RHEL/Fedora),这些也需要 root 权限。
xfrm_userxfrm_algorxrpc、kafs)是所有挂载 AFS 文件系统的主机所必需的。禁用它们将在下次启动时破坏这些挂载。algif_aead 通过 AF_ALG 套接字族暴露内核密码学功能。应用程序代码很少直接使用它,但在将其列入黑名单之前,请通过列出实时套接字 (ss -p --af-alg) 并检查用户空间消费者来确认。| 标志项 | 默认值 | 描述 |
|---|
-host | (必需) | 远程主机 |
-user | $USER | 远程用户 |
-port | 22 | 远程 SSH 端口 |
-agent | true | 使用 SSH 代理进行身份验证 |
-identity | (空) | 私钥文件路径(如果加密则提示输入密码短语) |
-password | false | 提示输入 SSH 密码 |
-insecure | false | 接受尚未记录在 known_hosts 中的主机密钥;与已记录密钥不匹配时仍会失败 |
-fix | false | 为尚未被列入黑名单的模块写入 /etc/modprobe.d 片段 |
-unload | false | 与 -fix 一起使用时,在黑名单后卸载受影响的模块 |
-rebuild-initramfs | false | 与 -fix 一起使用时,仅为运行中的内核重建 initramfs(update-initramfs 或 dracut) |
-skip-logs | false | 跳过内核日志历史检查 |
-timeout | 15s | SSH 连接超时 |
-ssh-keepalive | 30s | SSH 保活间隔(0 禁用) |
-command-timeout | 30s | 远程命令超时(0 禁用) |
-initramfs-timeout | 10m | initramfs 重建步骤的超时(0 禁用);仅与 -rebuild-initramfs 一起使用 |
-debug | false | 增加日志详细程度 |
-version | false | 显示版本并退出 |
| 代码 | 含义 |
|---|
0 | 所有受影响的模块已列入黑名单、已卸载、未内置于内核且非活跃状态 |
1 | 用法错误 |
2 | SSH 连接失败 |
3 | Sudo 身份验证失败 |
4 | 一个或多个模块未列入黑名单(无当前暴露) |
5 | 一个或多个模块当前已加载、内置于内核或正在使用中 |
99 | 内部/检查失败 |
AF_ALG