ルールを編集し、ルールセットを再読み込みしても、トンネルの挙動は以前とまったく同じです。この結果にはよくある原因が二つあり、それぞれ別のテストが必要です。新しいルールがすでにパケットを許可した先行ルールの後ろに置かれているか、監視しているやり取りが、変更では再評価されない追跡済みのコネクションであるかのどちらかです。ファイル上のルールは意図を表すだけで、パケットを決めるのはそれが実際に出会う有効な経路です。以下の確認を順番に進め、その間は戻る道を確保しておいてください。

ルール順序とコネクション状態は別の障害である

順序付きチェーンは上から下へ評価され、最終的な判定に達した最初のルールでそのチェーンの走査は終わります。丁寧に書いたロックダウンルールの上に広い許可を置くと、ロックダウンルールは単なる記録になります。ルールセットには存在し、カウンタはゼロで、どのパケットもそこには到達しません。同じ記述を別のチェーンに適用しても何も証明できません。nftables ではベースチェーンが優先度ごとにフックへ接続されるため、あるチェーンでの許可が、別のフックや優先度にある別のチェーンが同じパケットを見ることを妨げません。

コネクション追跡が二つ目の症状を生み、外から見るとまったく同じに見えます。フローが状態テーブルに入ると、チェーンの先頭付近にある established-or-related の許可が、新しいルールを参照する前に戻ってしまいます。NAT マッピングも同じ性質を持ちます。変換はフローの開始時に固定されるため、postrouting のルールを編集しても、すでに走っているセッションは書き換わりません。09:00 に新しい接続では変更が効いたように見え、08:55 に誰かが開いたセッションでは何も起きないように見えるのは、このためです。

クラウドのセキュリティグループは三つ目のモデルを追加し、iptables で学んだ人を捕まえます。受信ルールは最初の一致をたどる方式ではなく集合として評価される許可リストで、ステートフルであり、許可ルールを削除してもすでに追跡されているフローは終了しません。最初の一致という意味論がないプラットフォームでそれを前提にすると、自信に満ちた誤った結論に至ります。

編集したファイルではなく、有効なルールセットを読む

カーネルが今まさに適用しているものから始めます。適用されなかった保存済みの設定は、驚くほど多くの「変わらない挙動」を説明してくれます。切り分けはコマンド一つで済みます。

nft list ruleset
iptables-save

次に、自分のルールにそもそも到達しているかを問います。パケットカウンタはそれを直接示し、意図についてのどんな推論よりも雄弁です。

iptables -L FORWARD -v -n --line-numbers
nft list chain inet filter forward

実際にテストした後のカウンタがゼロのロックダウンルールは、ポリシーの問題ではなく位置の問題です。動かすのは一行の変更で、原因はまさにその構文にあります。iptables では -Iが先頭に挿入し、-Aが末尾に追加します。nftables では insertがチェーンの先頭にルールを置き、addが末尾に追加します。ルールを勝たせたいなら、たまたま読み込まれた順序を信じるのではなく、明示的に指定してください。

フローが追跡されているかを証明する

ルールを疑う前に、その通信がそもそも追跡済みのコネクションかを確認します。状態テーブルを全部吐き出すのではなく、該当のフローだけを尋ねてください。

conntrack -L -p tcp --dport 1194
conntrack -E -p tcp --dport 1194

一覧は状態と残りタイムアウトを示し、これで確立済みのセッションと新規の試行を区別できます。イベントモードは更新が起きた時点で出力するので、クライアントを再接続するときに役立ちます。何も触る前にフローが確立済みの状態で存在しているなら、フィルタルールをどう編集してもその運命は変わりません。これはファイアウォールの不具合ではなく、ステートフルフィルタリングの契約です。

本番ゲートウェイでテーブル全体をフラッシュする近道には抗ってください。conntrack -Fは利用できますが、マシン上のすべての追跡済みフローを破壊します。作業中の管理セッションや、シェルを運ぶトンネルも含まれます。個別のエントリは本当に必要なら削除できますが、新しい送信元ポートからの新しいフローを作るほうが通常はきれいな実験です。

追跡されない経路もあり、こちらは逆の挙動をします。raw テーブルで notrackとマークされた通信、通常のフックを迂回する一部のトンネル、フローを二つのゲートウェイに分ける非対称ルーティングは、いずれもパケットを一つずつ評価させ、両端で状態が作られないことがあります。カウンタがパケットごとに動くなら、順序を疑う前にそうした経路を疑ってください。

戻る道を確保した新しいフローでテストする

遠隔アクセスを断ち切る可能性のあるルールを試す前に、復旧経路を用意します。プロバイダのコンソール、シリアルコンソール、帯域外の管理アドレス、あるいはそのルールに一致しない二つ目のインターフェースです。ロールバックタイマーも妥当な相棒で、テストの途中でセッションが死んでも以前のルールセットを復元します。

次に、状態ですでに覆われていないやり取りでテストします。クライアントを切断して再接続し、新しい五つ組を作り、その間に両端を観察します。

tcpdump -ni eth0 'tcp port 1194'
journalctl -k -n 50 --no-pager

テストは両方向で行います。新しい受信ハンドシェイクを遮断するルールでも、応答経路は通ることがあり、その逆もあります。片方向だけの結果は、ロックダウンが半分しか効かない典型的な理由です。テスト後にもう一度接続し直して定常状態を確認し、正規の管理アクセスが生き残ったことを確かめてください。一つのポートに合わせて書いたルールは、意図より広い範囲に一致しがちです。

ルールと一緒に目的と位置を記録する

記録された目的のないルールは、誰も削除できないルールです。ロックダウンの各エントリには、保護するフロー、それが属するチェーンとフック、より広い許可に対して保つべき位置、それを証明したテストを添えてください。半年後に誰かが周囲のルールセットを編集するとき、そのメモだけが、この位置が意図的だったことを伝える警告になります。

変更を閉じる前に四つを確認します。稼働中のルールセットがファイルと一致しているか、新しい試行の後に新しいルールのカウンタがゼロでないか、逆方向と管理アクセスがまだ通るか、そして変更前から続くセッションの状態ではなく定常状態を証明するために一度接続し直したか。どれかが未確認なら、トンネルがどう振る舞っていても変更は終わっていません。

関連記事