nftが繋がらない時の対処法をお探しですね。

広告

nftablesでパケットが通らない?原因を見つけるためのログ確認と対処法

nftablesの設定をしていると、「ルールは書いたはずなのに通信が通らない…」という状況に遭遇することってありますよね。

iptablesとは書き方も構造も違うので戸惑いますし、どこでパケットが落ちているのか分からないと本当に困ります。

この記事では、そんなときに役立つログの見方や、意外と見落としがちなカーネルの設定について、実践的な解決方法を紹介していきます。

まずはログとトレース機能を使って「見える化」しよう

トラブルを解決する第一歩は、「何が起きているか分からない」状態から抜け出すことです。

nftablesには便利なログ機能とトレース機能があるので、これを使えば「どのルールでパケットが落ちたのか」がはっきり分かります。

最初に試したいのが、ドロップルールの手前に `log` を入れる方法です。

例えば、チェーンの最後でパケットが落ちている気がするなら、その直前に `log prefix “NFT-DROP: ” level warn` みたいな行を追加してみましょう。

こうすると、落とされたパケットの情報(送信元IP、宛先ポート、どのインターフェースから来たかなど)がカーネルログ(dmesgや/var/log/kern.log)に記録されます。

プレフィックスを付けておけば、後でgrepで検索するときも楽ちんです。

もっと詳しく調べたいときは、`meta nftrace set 1` を使ったトレース機能が強力です。

これは、条件に合ったパケットが「どのテーブルのどのチェーンを通って、最終的にどう判定されたか」を細かく記録してくれる機能です。

`nft monitor trace` コマンドと一緒に使えば、リアルタイムでパケットの動きを追いかけられるので、複雑なルールの中から問題箇所をピンポイントで見つけられます。

まずは「見えないパケット」を「見えるログ」にすることが、解決への近道です。

tcpdumpと組み合わせてパケットがどこまで届いているか確認する

nftablesの設定を見直してもログが出ない、あるいはログでは許可されているのに通信できない…そんなときは、調査の範囲を広げる必要があります。

ここで活躍するのが `tcpdump` です。

nftablesはカーネル内部のNetfilterという仕組みで動いていますが、tcpdumpはもっと物理層に近い、早い段階でパケットを観察できます。

なので、tcpdumpでパケットの到着は確認できるのにnftablesのログに出ない場合は、nftablesの処理に到達する前の段階で落ちている可能性があります。

逆に、tcpdumpでもパケットが見えないなら、もっと手前(ルーターやクラウドのセキュリティグループ、送信元の設定など)に問題があるかもしれません。

それと、通信の方向も意識しましょう。

受信(Input)ばかり気にしがちですが、送信(Output)や転送(Forward)のルールで引っかかっているケースも多いんです。

特にDockerやKubernetesなどのコンテナ環境では、ブリッジを通るときの転送ルールが複雑になりがち。

tcpdumpで `-i any` オプションを使いながら、送信側と受信側の両方でキャプチャして、パケットがどこまで届いているかを確認すると、nftablesの問題なのか、それ以外の経路の問題なのかがはっきりします。

設定以外の原因:rp_filterや他のツールとの競合をチェック

設定ファイルは完璧なのにパケットが通らない…そんなときは、Linuxカーネル自体のセキュリティ機能や、他のツールとの競合を疑ってみましょう。

特に「非対称ルーティング」がある環境では、`rp_filter`(リバースパスフィルター)に注意が必要です。

rp_filterは、パケットが入ってきたインターフェースと、返事が出ていくインターフェースが違う場合などに、「これは偽装されたパケットかも?」と判断してカーネルレベルで落としてしまう機能です。

しかもこの処理はnftablesのルール評価より前に行われることが多いので、どんなにnftablesで「accept」と書いても、ログにも残らず消えてしまいます。

原因が分からないときは、sysctlコマンドで `net.ipv4.conf.all.rp_filter` の値を確認して、試しに無効化(0または2に設定)してみると良いでしょう。

また、システム内に複数のファイアウォール管理ツールが動いているケースも要注意です。

nftablesを直接いじっているつもりでも、裏で `firewalld` や `ufw`、あるいはDockerが自動生成したルールが動いていると、それらが独自のテーブルやチェーンを作って、優先的にパケットを拒否している可能性があります。

**競合をチェックするポイント:**

– `systemctl status firewalld` などで不要なサービスが動いていないか確認
– `nft list ruleset` を実行して、自分が作った覚えのないテーブルやチェーンがないか確認
– iptables-nftレイヤーのルールが干渉していないかチェック

こういった原因の場合、nftablesだけをいくらデバッグしても解決しないので、システム全体のネットワーク構成を整理する必要があります。

さらに深く:dropwatchなどでカーネルの奥まで調べる

ここまでやっても原因が分からない、あるいはパフォーマンスの問題でパケットロスが起きている気がする…そんなときは、もっと低レイヤーのカーネルの動きを調べる必要があります。

そこで役立つのが `dropwatch` や `perf` といったツールです。

`dropwatch` は、カーネル内でパケットが破棄される瞬間(`kfree_skb` という関数が呼ばれる場所)を記録して、どのカーネル関数が原因かを教えてくれます。

これを使えば、「IPヘッダのチェックサムエラーで落ちてる」「ルーティングテーブルの検索に失敗してる」「メモリ不足で落ちてる」といった、設定ファイルでは見えない原因が分かります。

例えば、`nf_hook_slow` あたりでドロップしていればNetfilter(ファイアウォール)関連の可能性が高いですし、`tcp_v4_rcv` あたりならTCPスタックの処理での問題だと推測できます。

さらに詳しく調べたい場合は、eBPFベースのツールや `trace-cmd` を使ったカーネル関数のトレースも検討できます。

これらは少し高度な知識が必要ですが、「設定は絶対に正しいはずなのに動かない!」という状況では、システム内部で実際に何が起きているかを確かめる唯一の手段になります。

特に高負荷時のバッファあふれや、ドライバレベルの不具合が疑われるときは、これらのツールが出す情報が解決のヒントになるでしょう。

トラブルシューティングは、表面的な設定確認から始めて、少しずつカーネルの深い部分へと調査を進めていくのが確実です。

焦らず一つずつ確認していけば、必ず原因は見つかります。

頑張ってください!

広告