Chapter 11. Netfilter と iproute でパケットに印を付ける

ここまで、iproute がどのように動作するかについて見てきましたが、 netfilter についても何回か言及しました。 このあたりで、Rusty's Remarkably Unreliable Guides を通して眺めておくといいかもしれません。 netfilter そのものは こちら にあります。

netfilter を用いるとパケットをフィルタしたり、 ヘッダを書き換えたりできます。 特殊な機能として、パケットに数値の印を付けることもできます。 これには --set-mark オプションを使います。

例として、以下のコマンドはポート 25 に向けた、 送信メールのパケットにすべて印を付けています。

# iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 25 \
 -j MARK --set-mark 1

いま複数の回線があるとして、 ひとつは高速ですが従量制で高く、 もうひとつは低速ですが定額で安いとしましょう。 ほとんどの場合、送信メールは安いほうの経路で送りたいでしょう。

既にパケットには '1' という印を付けました。 ではここで経路ポリシーデータベースに、 このような動作をするよう指示しましょう。

# echo 201 mail.out >> /etc/iproute2/rt_tables
# ip rule add fwmark 1 table mail.out
# ip rule ls
0:	from all lookup local 
32764:	from all fwmark        1 lookup mail.out 
32766:	from all lookup main 
32767:	from all lookup default 

ここで mail.out テーブルに、 遅いが安い回線に向かう経路を作ります。
# /sbin/ip route add default via 195.96.98.253 dev ppp0 table mail.out

これで終わりです。例外を設けたい場合、やり方はたくさんあります。 netfilter の文を修正して特定のホストを除外してもいいですし、 除外ホストに対して、main テーブルを指すような、 優先度が高いルールを挿入する方法もあります。

この機能は、TOS ビットを尊重するのにも使えます。 Type of Service の違いによってパケットに印を付け、 それらに対して作用するルールを作ればよいのです。 こうすれば、例えば ISDN 接続を、 対話的なセッション専用にすることもできます。

言うまでもありませんが、これは NAT (マスカレード) を行っているホストでも問題なく動作します。

重要: パケットへの印付けは、少なくとも MASQ と SNAT とに衝突してしまう、 という報告を受けました。これに関する Rusty Russell の説明は この投稿で与えられています。 正しく動作させるには、reverse path filter を無効にしてください。

注意: パケットに印を付けるには、 いくつかのカーネルオプションを有効にする必要があります。

IP: advanced router (CONFIG_IP_ADVANCED_ROUTER) [Y/n/?]
IP: policy routing (CONFIG_IP_MULTIPLE_TABLES) [Y/n/?]
IP: use netfilter MARK value as routing key (CONFIG_IP_ROUTE_FWMARK) [Y/n/?]

クックブックSection 15.5 も参照してください。