日: 2026年10月31日

Linuxカーネルの脆弱性 CVE-2026-98432 続報:nftablesによる暫定緩和策と永続化

概要

先日、Linuxカーネルの脆弱性「CVE-2026-98432」について、原因と暫定対策を記事にしました。

その後、2026年10月30日付で、Red HatおよびCIQからnftablesを利用した緩和策が公開されました。

今回の脆弱性は、IPv4 TCP接続の処理中に解放済みメモリへアクセスするUse-After-Free(UAF)に起因するものです。

攻撃者がIPv4オプションを含むTCPパケットを送信することで、問題のある処理経路に到達する可能性があります。

そこで、IPv4オプション付きTCPパケットをカーネルのTCP処理に到達する前に破棄するというのが、今回の緩和策です。

参考資料:

CIQの資料では、MPTCPを無効化した状態でも通常のTCP通信から脆弱な処理経路に到達できることが確認されています。そのため、MPTCPの無効化だけに頼らず、nftablesによる通信制御を追加することにしました。

今回は、実際に運用しているサーバに暫定ルールを追加し、systemdによる永続化の設定まで行った記録です。

環境

  • OS:Ubuntu 24.04 LTS
  • Webサーバ:Apache
  • ファイアウォール:UFW
  • IPアドレス制御:ipset
  • 不正アクセス対策:fail2ban
  • iptables:v1.8.10(nf_tables)
  • 作業日:2026年10月31日

筆者環境では、UFWとipsetを組み合わせたアクセス制御を行っています。

今回の作業前に、nftablesのルールセットを確認しました。

sudo nft list ruleset | wc -l

結果は、

6089

6,089行。

この時点で、今回の作業方針はほぼ決まりました。既存のファイアウォールには、できる限り手を加えないことです。

実際、iptablesのバージョンを確認すると、

sudo iptables -V
iptables v1.8.10 (nf_tables)

となっていました。また、nftablesのテーブル一覧は以下のとおりです。

sudo nft list tables
table ip6 filter
table ip filter
table ip nat
table ip6 nat
table ip raw
table inet f2b-table

UFWなどがiptables-nftを通じて管理しているテーブルに加え、fail2ban用の独立したテーブルも存在しています。

今回の緩和策は、これらとは別に専用テーブルを作成する方針としました。

フェイズゼロ:政治交渉

以前の記事でも触れましたが、システムの保守作業には技術的な準備だけでなく、作業時間の確保や関係者との調整が必要です。

今回も例外ではありません。

ただし、今回の作業では、もう一つ交渉相手がいました。

自分自身です。

既に稼働しているファイアウォールの設定を変更するのは、できれば避けたい作業です。

しかも、SSHで接続しているサーバのネットワーク制御を変更するとなれば、設定を間違えた瞬間に自分自身を締め出す可能性があります。

そこで、今回の作業では以下を徹底しました。

  • 既存のUFW・ipset・fail2banの設定は変更しない。
  • nftablesにCVE対策専用のテーブルを作成する。
  • 変更前のルールセットを保存する。
  • シリアルコンソールを確保する。
  • 問題が発生した場合は、専用テーブルだけを削除する。

特に重要なのが、シリアルコンソールです。

SSH接続を失った場合でも、ネットワーク経由ではない復旧手段を確保してから作業に入りました。

退路を確保してから前進する。

今回は、これが最も重要な準備でした。

さっくりとした手順

  1. 作業ディレクトリへ移動 cd /home/hoge/work/cve-2026-98432

任意のディレクトリを指定します。

  1. 既存ルールセットをバックアップ sudo nft -a list ruleset > nftables-before-cve-2026-98432.txt
  2. テーブル一覧をバックアップ sudo nft list tables > nftables-tables-before.txt
  3. 既存のCVE対策用テーブルを確認 sudo nft list table inet cve_2026_98432
  4. 暫定ルールの設定ファイルを作成 nano cve-2026-98432.nft
  5. 構文チェック sudo nft --check --file cve-2026-98432.nft
  6. 暫定ルールを適用 sudo nft --file cve-2026-98432.nft
  7. 適用結果を確認 sudo nft -a list table inet cve_2026_98432
  8. 永続化用の設定ファイルを作成 sudo nano /etc/nftables/cve-2026-98432.nft
  9. systemdユニットを作成 sudo nano /etc/systemd/system/cve-2026-98432-nft.service
  10. 永続化用設定の構文チェック sudo nft --check --file /etc/nftables/cve-2026-98432.nft
  11. systemdユニットの検証 sudo systemd-analyze verify /etc/systemd/system/cve-2026-98432-nft.service
  12. systemdの設定を再読み込み sudo systemctl daemon-reload
  13. 自動起動を有効化 sudo systemctl enable cve-2026-98432-nft.service
  14. 自動起動の登録状態を確認 systemctl is-enabled cve-2026-98432-nft.service
  15. 既存の防御機構を確認 sudo ufw statussudo ipset list -namesudo fail2ban-client status

作業詳細

1. 既存のルールセットをバックアップ

まずは、作業ディレクトリを用意しました。

今回の作業ディレクトリは以下です。任意のディレクトリを指定してください。

cd /home/hoge/work/cve-2026-98432

現在のルールセットを保存します。

sudo nft -a list ruleset > nftables-before-cve-2026-98432.txt

続いて、行数を確認しました。

wc -l nftables-before-cve-2026-98432.txt
6089 nftables-before-cve-2026-98432.txt

既存の6,089行を保存できています。

次に、テーブル一覧も保存します。

sudo nft list tables > nftables-tables-before.txt

ファイルの状態は以下でした。

nftables-before-cve-2026-98432.txt  239547 bytes
nftables-tables-before.txt              94 bytes

これで、変更前の状態を記録できました。なお、これらのファイルは復旧時の参照用です。

iptables-nftで管理されているテーブルも含まれるため、バックアップ全体を無条件に読み戻すことはしません。

2. nftablesの専用テーブルを作成

まず、同名のテーブルが存在しないことを確認します。

sudo nft list table inet cve_2026_98432

続いて、作業ディレクトリに設定ファイルを作成しました。

nano cve-2026-98432.nft

内容は以下です。

table inet cve_2026_98432 {
    chain prerouting {
        type filter hook prerouting priority -300; policy accept;
        ip hdrlength > 5 meta l4proto tcp counter drop
    }
}

それぞれの意味は以下のとおりです。

  • table inet cve_2026_98432:今回のCVE対策専用テーブル
  • hook prerouting:受信パケットの早い段階で評価
  • priority -300:raw優先度
  • ip hdrlength > 5:IPv4ヘッダーが通常の20バイトを超えるパケットを対象
  • meta l4proto tcp:TCP通信を対象
  • counter drop:該当パケットをカウントして破棄

ここで重要なのは、IPv4のIPオプションとTCPオプションは異なるという点です。

今回のルールは、TCPタイムスタンプなどの一般的なTCPオプションを一律に遮断するものではありません。

一方、IPv4オプションを使用する正当なTCP通信は遮断されるため、適用先の通信要件を考慮する必要があります。

3. 構文チェック

設定ファイルを保存したら、構文チェックを実施します。

sudo nft --check --file cve-2026-98432.nft

エラーは表示されませんでした。終了ステータスも確認します。

echo $?
0

構文チェック成功です。この段階では、まだ通信制御は変更されていません。

4. シリアルコンソールを確保

実際に適用する前に、vpsのシリアルコンソールへ接続しました。

今回の作業で最も避けたいのは、SSH接続を失ってサーバへアクセスできなくなることです。

現在のUFWでは、以下のポートを許可しています。

80/tcp
443/tcp
22/tcp

今回のnftablesルールはポート番号による判定ではないため、これらのポートにも条件が一致すれば適用されます。

そのため、SSHセッションを維持したまま作業し、必要になればシリアルコンソールから切り戻せるようにしました。

5. 暫定ルールを適用

準備ができたところで、設定を適用します。その前に:深く深呼吸を3回ぐらいしましょう。ここから先、タイポ、コマンド忘れ、全てが致命的になり得ます。

sudo nft --file cve-2026-98432.nft

エラーは表示されませんでした。続いて、適用結果を確認します。

sudo nft -a list table inet cve_2026_98432

結果は以下です。

table inet cve_2026_98432 { # handle 10
        chain prerouting { # handle 1
                type filter hook prerouting priority raw; policy accept;
                ip hdrlength > 5 meta l4proto tcp counter packets 0 bytes 0 drop # handle 2
        }
}

設定ファイルではpriority -300と指定しましたが、表示上はpriority rawとなっています。これはnftablesが数値を定義済みの優先度名で表示しているためです。

また、

counter packets 0 bytes 0

となっています。この時点では、遮断条件に一致したパケットはありませんでした。

6. Webサイトの動作確認

適用後、自サイトへアクセスし、記事の登録まで行いました。

HTTPSによるアクセス、ログイン状態の維持、記事の登録と保存が正常に行えています。

単純なHTTP応答だけでなく、普段利用しているWebアプリケーションの操作が継続できることを確認しました。

少なくとも、今回確認した範囲ではWebサイトの利用に支障は発生していません。

永続化

1. 永続化用の設定ファイルを作成

暫定ルールの動作を確認できたため、再起動後にも読み込めるようにします。ただし、既存のUFWやipsetを管理している仕組みには手を加えません。

今回は、CVE対策専用の設定ファイルとsystemdユニットを作成しました。

sudo mkdir -p /etc/nftables
sudo nano /etc/nftables/cve-2026-98432.nft

内容は以下です。

add table inet cve_2026_98432
delete table inet cve_2026_98432

table inet cve_2026_98432 {
    chain prerouting {
        type filter hook prerouting priority -300; policy accept;
        ip hdrlength > 5 meta l4proto tcp counter drop
    }
}

冒頭の、

add table inet cve_2026_98432
delete table inet cve_2026_98432

は、既存の専用テーブルが存在する場合でも、同じ名前のテーブルを作り直せるようにするためのものです。

削除対象はcve_2026_98432テーブルに限定しています。

UFWやfail2banのテーブルには触れません。

2. systemdユニットを作成

続いて、専用のsystemdユニットを作成します。

sudo nano /etc/systemd/system/cve-2026-98432-nft.service

内容は以下です。

[Unit]
Description=Temporary nftables mitigation for CVE-2026-98432
Wants=network-pre.target
Before=network-pre.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/nft -f /etc/nftables/cve-2026-98432.nft
ExecStop=-/usr/sbin/nft delete table inet cve_2026_98432

[Install]
WantedBy=multi-user.target

このユニットでは、起動時に専用のnftables設定ファイルを読み込みます。停止時には、今回追加したテーブルだけを削除します。

RemainAfterExit=yesを指定しているため、ルールの読み込みが完了した後もsystemd上ではサービスを有効な状態として扱います。

3. 設定ファイルの構文チェック

まず、nftables設定ファイルを検証します。

sudo nft --check --file /etc/nftables/cve-2026-98432.nft

終了ステータスを確認しました。

echo $?
0

正常終了です。

続いて、systemdユニットも検証します。

sudo systemd-analyze verify /etc/systemd/system/cve-2026-98432-nft.service

4. systemdに登録

ユニット定義を再読み込みします。この作業の前に、もう4回ほど深呼吸をして、飲み物を何か飲みましょう。お茶菓子などがあれば更に最高です。

システムをいじる作業は全て自分の指先に全責任が伴います。

sudo systemctl daemon-reload

続いて、自動起動を有効化します。

sudo systemctl enable cve-2026-98432-nft.service

ここでは--nowを付けませんでした。

既に手動で適用したルールが動作しているため、現時点で専用テーブルを作り直す必要がないからです。

最後に、自動起動の登録状態を確認します。

systemctl is-enabled cve-2026-98432-nft.service

結果は、

enabled

となりました。

これで、systemdによる自動起動の登録まで完了です。

なお、再起動後に実際にルールが復元されるかは、まだ確認していません。

既存の防御機構を確認

今回の作業で最も気になっていたのは、既存のUFW・ipset・fail2banへの影響です。

設定ファイルを作成し、自動起動を登録した後、改めて状態を確認しました。

1. nftables

sudo nft list table inet cve_2026_98432
table inet cve_2026_98432 {
        chain prerouting {
                type filter hook prerouting priority raw; policy accept;
                ip hdrlength > 5 meta l4proto tcp counter packets 0 bytes 0 drop
        }
}

専用テーブルは維持されています。

2. UFW

sudo ufw status
状態: アクティブ

To                         Action      From
--                         ------      ----
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
22/tcp                  ALLOW       Anywhere

UFWはアクティブのままです。

既存の許可ポートにも変更はありません。

3. ipset

sudo ipset list -name
ufw-blocklist

既存のipsetが存在していることを確認できました。

4. fail2ban

sudo fail2ban-client status
Status
|- Number of jail:      2
`- Jail list:   sshd, ufw

fail2banも、既存の2つのjailを維持しています。

これらの確認から、少なくともサービスの状態と設定の一覧については、作業前の構成が維持されていることを確認できました。

切り戻し

今回の暫定ルールに問題が発生した場合は、専用テーブルを削除します。

一時的にルールを撤去する場合

sudo nft delete table inet cve_2026_98432

この操作で、今回追加したテーブルとチェーンを削除できます。

ただし、systemdの自動起動設定は残るため、次回起動時には再び読み込まれます。

永続化設定も撤去する場合

まず、自動起動を無効化します。

sudo systemctl disable cve-2026-98432-nft.service

続いて、専用テーブルを削除します。

sudo nft delete table inet cve_2026_98432

systemdユニットを削除します。

sudo rm /etc/systemd/system/cve-2026-98432-nft.service

nftables設定ファイルも削除します。

sudo rm /etc/nftables/cve-2026-98432.nft

最後に、systemdの設定を再読み込みします。

sudo systemctl daemon-reload

今回追加した設定だけを撤去するため、既存のUFW・ipset・fail2banの設定はそのまま維持できます。

今後の確認事項

今回の作業では、以下まで完了しています。

  • 既存ルールセットのバックアップ
  • シリアルコンソールによる復旧経路の確保
  • nftables専用テーブルの追加
  • 設定ファイルの構文チェック
  • Webサイトの動作確認
  • systemdユニットの作成
  • 自動起動の有効化
  • UFW・ipset・fail2banの状態確認

残っているのは、再起動後の動作確認です。

次回の再起動後には、以下を確認します。

systemctl is-active cve-2026-98432-nft.service
sudo nft list table inet cve_2026_98432

activeと表示されるだけでなく、実際に専用テーブルが存在していることを確認します。

また、今回のルールはIPv4オプション付きTCPパケットを遮断する暫定措置です。

CIQが公開した検証結果はRocky Linux系の環境を対象としており、筆者環境のUbuntu 24.04 LTSで同等の攻撃パケットを用いた遮断試験までは実施していません。

そのため、今回確認できたのはルールの登録と通常通信の継続までです。

修正済みカーネルが提供された段階で更新を行い、不要になった暫定ルールを撤去する予定です。

おわりに

今回の作業で、最も神経を使ったのはnftablesの設定そのものではありません。

既に稼働している防御機構を壊さずに、新しい防御を追加することでした。

筆者環境では、UFW・ipset・fail2banを組み合わせてアクセス制御を行っています。その結果、nftablesのルールセットは6,089行に達していました。

そこへ緊急の脆弱性対策を追加するのですから、作業を始める前から気が重くなるのも無理はありません。

そこで、今回は既存のルールセットを編集せず、専用テーブルを追加する方式を採用しました。

さらに、シリアルコンソールを確保し、問題が発生した場合には今回追加したテーブルだけを削除できるようにしています。

結果として、既存のUFW・ipset・fail2banの設定を変更することなく、暫定緩和策の導入と永続化の登録まで進められました。

今回の作業で改めて感じたのは、システムの保守とは、何かを変更する技術だけでなく、変更しなくてよいものを見極める判断でもあるということです。

脆弱性を塞ごうとして、既存の防御機構を壊してしまっては意味がありません。

そして、その判断を支えるのがバックアップであり、切り戻し手順であり、シリアルコンソールという最後の退路です。

作業を終えた後の感想を一言で表すなら、

「心臓に悪い作業だった」

でしょうか。

とはいえ、これで修正済みカーネルが提供されるまでの間、攻撃経路を減らすための対策を一つ追加できました。

今後もカーネルの修正状況を確認しながら、必要な対応を続けていきます。

ピボット旅行2026-26『あるのがいけない!! Part2』

はじめに

とんでもない商店街だと理解らされた筆者に、更なる物欲が待っていました。

筆者のお茶の運用

ルピシア。筆者お気に入りのフレーバーティーを多数揃えており、筆者の「フレーバーティーという名の沼(1773年のボストン港ではないことに注意)」に、際限なく茶葉と水を供給し続けてきたお店です。

ただし、筆者には「買ったお茶を確実に飲みきる」という信条があります。

そのため、茶葉ごとに管理番号を振り、入手日・開封日・消費完了日を記録しています。種別やベース、購入先も管理対象です。

2025年はルピシアが中心で、80銘柄を記録しました。

2026年は様子が変わっています。大容量の茶葉を扱うボンマルシェを中心に、お気に入りを続けて飲むスタイルへ移行。カルディなど、ほかのお店で出会ったお茶も飲むようになりました。

項目2025年2026年
主な購入先ルピシアボンマルシェ、カルディなど
購入スタイル福袋中心好みのお茶を個別購入
飲み方幅広く試すお気に入りを続けて飲む
管理入手・開封・消費日を記録同じ方法で継続

背景には、昨今の値上げラッシュがあります。福袋は確かにお得ですが、好みでないお茶が混じることもあります。お気に入りでないお茶とは言え、手元にある者は飲みきる性分。

それならば、お気に入りをじっくり飲みつつ、新たなブレンダーのお茶を味わうのも一興です。

こうして筆者のお茶の運用は変化していました。

そして、ルピシアへ

そんな中でのルピシアは、「地元に行けば荷物も増えなくて済むし……」ぐらいの勢いでした。

しかし、前項でお話ししたとおり、秋雨が降り注いでいます。ここで時間を過ごすと決めた以上、入るのも一興です。

店内に入ってすぐのところで、見てしまいました。見つけてしまいました。

「四国限定フレーバーティー/ルイボスティー」

試供品の香りを確かめます。

あるのがいけない!! あるのがいけない!!

買っていました。何という即落ち2コマ。

ルイボスティーはそれほど飲まない筆者がカゴに入れたのですから、相当です。

追加で買った理由

さて、翻って。筆者は既に尾道で結構な量のお茶を買っています。そのうえで「倍プッシュ」に等しい買い物をしたのは「ハードルが低くなった」からです。

筆者の座右の書『オサムシ教授の事件簿』に以下のくだりがあります。

少し前 世間では
『なぜ人を殺してはいけないのか?』
という問が流行したそうだ
君はどう思う?

人類の歴史は人殺しの歴史…
人は人を殺すものだから――――
でしょう?

そうだな
いつまでも互いに殺し合っていては
種の繁栄にマイナスだからだ
私は人間が勝手に作った
常識や法律のほとんどを
下らんと思っている
だが人は殺さない
なぜだと思う?

人を殺すと殺し続けなくてはいけなくなるからだ

人は慣れてゆく生き物だ
良くも悪くもどんなことにも――――
そしてハードルが低くなる

少し気に入らないだけで殺す
バレそうになったから殺す
殺した相手の身内が復讐に来るかもしれない――――
殺されたくないから殺す
どのみち“死の連鎖”からは逃げられない

何でそんな話…
私には関係ないのに

逆に罪悪感にさいなまれる者もいるだろう
その時は――――
自分を殺す――――
文字通り自殺するか
ドロップアウトし身も心もボロボロになり
死んだように生きていくか
やはり待っているのは“死”だ

ここで死生観や哲学を問う気はありませんしそういう話ではありません。問題はここ。

人は慣れてゆく生き物だ
良くも悪くもどんなことにも――――
そしてハードルが低くなる

筆者は既に7500円ほどお茶を買っています。なので

  • 「もう3~4000円ほど増えても荷物の一つになるだけ」
  • 「このお茶を飲めば、あとでこのたびのことをも出すからいいだろう」
  • 「腐るもんでもないし」

という、「購買の連鎖」がここにも適用されました。

ハードルの低さという継続

さて、上記を踏まえ、筆者のブログの更新頻度をご覧ください。2020年1月の下旬から、一日も休まずWordPressへの投稿を続けています。

これもまた、筆者の慣れであり、ハードルの低下です。

  • 体調が悪くても書いたから、「やる気がない」は理由にならない。
  • 一日一記事を続けてきたから、記事を書くこと自体が特別な行為ではなくなった。

生存報告のため書く。今日が一番新しい日だから書く。書きたいことがあるから書く。その積み重ねが、いつしか毎日更新という形になっています。

そして、ここまで続けてくると、書かないことの方が普段と違う状態になるのでしょう。

慣れは敵にも味方にもなる

お茶を買うときには、ハードルが下がることで、追加の出費に対する抵抗が薄れました。ブログを書くときには、ハードルが下がることで、執筆を始める心理的な負担が軽くなりました。(余談ですが、万年筆のすらすらとした書き心地も、状況を選ばずガシガシ書けるThinkPadも、その慣れを続ける一助になっています)

どちらも、繰り返すうちに行動が特別なものではなくなった結果です。

人は慣れてゆく生き物です。

その慣れが購買の連鎖につながることもあれば、長く続く習慣を作ることもある。今回のお茶の買い物は、そんな仕組みを改めて実感する出来事となりました。

あるのがいけない!!

さて、ここまで書いておいて何ですが、筆者は四国限定のお茶を買いました。既に尾道でお茶を買っていたことも、手元に飲むべき茶葉があることも承知のうえです。

それでも、目の前にお気に入りのお店があり、限定品があり、試供品の香りがよかった。

あるのがいけない!!

これに尽きます。そして、買った以上は、いつものように管理番号を振り、開封日を記録し、最後まで飲みきることになるのでしょう。

……こうして、筆者のお茶の沼は、まだまだ続くのです。それがたとえ、旅先であろうと。

Powered by WordPress & Theme by Anders Norén