# vcheck 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`を付けて再実行してください。正規のワークロードが依存するカーネルモジュールを無効にすると、ユーザーに影響を与えたり、アプリケーションを壊したりする可能性があります。 特に: - `-fix`は、影響を受けるモジュールのいずれも現在ロードされていない場合にのみ安全と見なしてください。つまり、すべてのモジュールが`mitigated`または`module not blacklisted`として報告されている場合です(`VULNERABLE`または`blacklisted but currently loaded`の行がないこと)。ロードされたモジュールはほとんどの場合、何かがホストで積極的に使用していることを意味します。ブラックリストに登録する前に確認してください。 - IPsecモジュール(`esp4`, `esp6`, `ipcomp4`, `ipcomp6`, `xfrm_user`)は、IPsec/strongSwan/WireGuard-over-IPsec/IKEデプロイメントに必要です。`ipcomp4`/`ipcomp6`モジュールはIPCompペイロード圧縮を実装し、明示的に設定されていなくてもIPsec SAの一部として自動ネゴシエーションされる可能性があります。VPNゲートウェイ、IPsecエンドポイント、または`ip xfrm policy`がルールを返す場所では、これらをブラックリストに登録しないでください。`xfrm_algo`フレームワークモジュールは意図的にこのリストに含まれていないことに注意してください。ベンダーガイダンス(Red Hat、Ubuntu、AWS)によると、ESPおよびIPCompプロトコルモジュールに加えて`xfrm_user` netlink設定インターフェースをブロックすれば十分であり、`xfrm_algo`をブラックリストに登録すると、他のすべてのxfrm変換機能が壊れるだけで、追加のメリットはありません。 - RxRPCモジュール(`rxrpc`, `kafs`)は、AFSファイルシステムをマウントするホストに必要です。無効にすると、次回ブート時にそれらのマウントが壊れます。 - `algif_aead`は、`AF_ALG`ソケットファミリーを介してカーネル暗号を公開します。アプリケーションコードで直接使用されることはほとんどありませんが、ライブソケットをリスト(`ss -p --af-alg`)し、ブラックリストに登録する前にユーザースペースのコンシューマを確認してください。 vcheckが書き込むブラックリストスニペットは、モジュールロード時にのみ有効になります(通常は次回ブート時、またはシステムがアイドル状態のときに`modprobe -r <module>`を実行)。すでにロードされているモジュールは`-fix`後も動作を続けます。vcheckはこれを`blacklisted but currently loaded; run 'modprobe -r' or reboot`として報告します。`-fix`とともに`-unload`を渡すと、vcheckはブラックリストスニペットの書き込み後、ロードされている影響を受けるモジュールに対して`modprobe -r`を実行します。これは、モジュールを実行中のカーネルから安全に削除できることを確認した場合にのみ使用してください。 `-fix`とともに`-rebuild-initramfs`を渡すと、**現在実行中のカーネル**のみのinitramfsが再生成されます(Debian/Ubuntuでは`update-initramfs -u -k $(uname -r)`、RHEL/Fedoraでは`dracut -f --kver $(uname -r)`)。他のインストール済みカーネルは既存のinitramfsを変更せずに残します。そのため、再起動後に問題が発生した場合は、ブートメニューから古いカーネルエントリを選択して回復できます。将来のカーネルインストールでは、現在の`/etc/modprobe.d/`の状態から独自のinitramfsを再構築するため、再実行しなくてもブラックリストは自動的に伝播します。`update-initramfs`も`dracut`も存在しない場合(例: Arch, Alpine, 不変イメージ)、vcheckは警告を出して続行します。再起動前に、ディストリビューションのツールを使用して手動で再構築してください。 再構築には数分かかる場合があり(特に多くのドライバがあるホストでの`dracut`)、診断用の`-command-timeout`を超える可能性があります。これは独自の`-initramfs-timeout`(デフォルト`10m`)の下で実行されるため、再構築に必要な時間が確保され、高速チェックは厳しい制限を維持します。低速ハードウェアの場合は`-initramfs-timeout`を増やすか、`0`を渡してタイムアウトを完全に無効にします。長時間のリモートコマンド中、vcheckはデフォルトで`30秒`ごとにSSHキープアライブリクエストを送信し、NAT/ファイアウォールのアイドルタイマーによる接続切断を防ぎます。`-ssh-keepalive`で調整するか、`0`を渡して無効にします。 ## インストール **Homebrew (macOS):** ```bash brew install --cask krisiasty/tap/vcheck ``` **プリビルドバイナリ**(Linux、macOS、Windows用)は[リリースページ](https://github.com/krisiasty/vcheck/releases)で公開されています。 **ソースから**(Go 1.26+が必要): ```bash go install github.com/krisiasty/vcheck@latest ``` ## 使い方 ```text vcheck -host HOST [flags] ``` | フラグ | デフォルト | 説明 | | -------------------- | ------------ | --------------------------------------------------------------------------------------------- | | `-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` | バージョンを表示して終了 | `-agent`、`-identity`、`-password`のうち少なくとも1つが使用可能な認証方法を生成する必要があります。メソッドはリストされた順序で試行されます。 ターゲットではsudoが必要です。パスワードなしのsudoが設定されている場合、ツールは静かに進みます。それ以外の場合は、パスワードを1回要求し(入力は非表示)、以降のすべてのコマンドで`sudo -S`経由で渡します。 ## 終了コード | コード | 意味 | | ---- | ------------------------------------------------------------------------------- | | `0` | すべての影響を受けるモジュールがブラックリストに登録され、アンロードされ、組み込まれておらず、非アクティブ | | `1` | 使用法エラー | | `2` | SSH接続失敗 | | `3` | Sudo認証失敗 | | `4` | 1つ以上のモジュールがブラックリストに登録されていない(現在の露出なし) | | `5` | 1つ以上のモジュールが現在ロードされている、カーネルに組み込まれている、またはアクティブに使用中 | | `99` | 内部/チェック失敗 | ## 出力例 ### 完全に緩和されたホスト ```console $ 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 ``` ### 緩和されておらず、部分的にロードされている — チェックのみ ```console $ 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` — 初回実行 ```console $ 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-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 ``` ブラックリストは適用されていますが、スニペット作成前に`esp4`がカーネルにロードされていました。完全にクリアするには、ターゲットで再起動するか`sudo modprobe -r esp4`を実行してください。 ### 2回目の実行 — esp4がまだロードされている ```console $ 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 ``` ### 3回目の実行 — `modprobe -r esp4`後 ```console $ 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`を使用 ```console $ 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` ```console $ 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`を1回取得し、モジュール名を最初の列と照合します。 - **組み込み:** `/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`を使用します。モジュールごとに最後の5行の一致行を保持します。この手順をスキップするには`-skip-logs`を渡します。 - **アクティブなソケット(`algif_aead`のみ):** `ss -p --af-alg`で開いている`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が必要です。