iptablesのNOTRACKターゲットを使う

Linux

Linux管理者のみなさん、iptables使ってますか?

iptablesとは、Linuxカーネルが持っているipファイヤウォール機能です。カーネル本体が持っている機能ということもあり、お手軽に使えるし、そもそも大抵のディストリビューションではインストール直後から有効になっているので、気付かないうちに恩恵に預かっていることもあると思います。

デフォルト機能ということで、機能が少なかったりするのかな、と思われるかもしれませんが、結構凝ったこともできて、何しろ設定を覚えることでネットワークの勉強にもなります。iproute2と組み合わせて、パケットラベリングしてDSR構成とか。あんな構成が組めるのも、LinuxのIPスタックの面白さですよね。

閑話休題。この便利なiptablesですが、時折不可解な挙動をすることがあります。フィルタに引っかかってもいないのに、パケットが落とされるという謎事象です。

私が具体的に困ったケースとしては、Linux-HAでheartbeat構成を組んだ時です。なぜかkeepaliveパケット(UDP/694)が落とされるケースがある。パケットキャプチャしてみると、どうにも受信側で何かがパケットを吸い込んでいるように見えます。

結論から言いますと、これ、conntrackがパケットをINVALIDと評価するケースに当って、パケット消失していることが分かりました。

conntrackとは何かというと、所謂ステートフルフィルタの実装です。デフォルトのiptablesの設定等に入っているstateモジュールの設定のところが、この機能を指定しているものになります。

-A INPUT -m state –state RELATED,ESTABLISHED -j ACCEPT

こんな記述を見たことがあると思います。これは何かと言うと、IP通信において、関連性のあるパケットのみを通信状態を見て通そうというものです。TCP通信であれば、シーケンスに従ったものを、UDP通信であれば、送受信ポートに整合性のあるものを通すという、便利でセキュアな機能です。

ただ、このconntrack、結構トラブルに当たるケースがあります。良くあるのが、高トラフィックのWebサーバー等で、conntrackのステート管理メモリが足りなくなるというヤツ。セッションが足りなくなって、通信が出来なくなります。net.ipv4.netfilter.ip_conntrack_maxを増やすという対応で回避できます。

じゃぁ、上記、heartbeatも、あまりにkeepaliveパケットが多すぎてセッションが足りないのか?というと、そうではありません。この場合、UDPのステートフルフィルタが過剰に反応して、パケットを落としてしまうケースになる(実は再現は出来ていないのですが・・・)。

通常、DNSクエリに代表されるUDPの通信は、リクエスト元portに対して応答が帰るというのが通常のシーケンスです。なので、ステートフルフィルタは基本的に、「通信が発生したUDPの戻りポート宛のパケットを通そう」とします。ところが、heartbeatのようなパケットを投げ合うサービスでは、いきなり相手からUDPが飛んでくる。もちろん、フィルタを開けておけば通ってしかるべきところなのですが、そんな通信は知らん、とステートフルフィルタで落とされてしまうことがあるんです。

iptablesの設定順で、ステートフルフィルタの前に通すルールを書いておくというのも試してみたのですが、これがなぜか効かないし、効いたとしていかんせん安定性に欠ける(不意にルールを追加した時に間違えそう)。なんとかこのconntrackを回避する手段を探していましたが、そして見つけたのが、notrackターゲットです。

notrackターゲットとはズバリ言えば、該当ルールに当たった通信について、ステートフルフィルタの対象外とするというものです。経験上、この設定を入れてからは、不慮のパケットロスに悩まされることも無くなりました。

*raw
:PREROUTING ACCEPT
:OUTPUT ACCEPT
-A PREROUTING -i eth0 -p udp -m udp –dport 694 -j NOTRACK
-A OUTPUT -o eth0 -p udp -m udp –dport 694 -j NOTRACK

NOTRACKターゲットはrawテーブルで指定します。あくまでconntrackの管理外にするだけなので、別途INPUTチェインで許可を与える必要があります。

もちろん、何でもかんでもNOTRACKすれば良いというものでは無いです。ステートフルフィルタは相応に強力でセキュアな機能なので、ぜひ有効化すべきだと思います。性能的にも優秀で、conntrackの有効・無効でネットワーク速度が変わるようなこともありません(1GbEでワイヤースピード程度までなら見たことがあります。10GbEとかなると、正直分かりません)。

なんだか動きがおかしい・・・というような場合には、ステートフルフィルタがINVALIDと判定しているケースがあるかもしれませんという話。そんな時は、NOTRACKです。他にも、iptablesはホント多機能でいろんなことが出来ますので、有効活用しましょう。困った時、意外と読んでおくと良いと思ったのが、Tutorialです。iptablesの基本的な構造や処理の流れが理解出来ますので、オススメ。

ぜひ、iptablesは使いこなしましょう。

コメント

タイトルとURLをコピーしました