Linux iproute2でconntrackレスなStateless NAT
ども、大瀧です。
Linuxで静的NATを組むときの定番はNetfilter(iptables)ですが、iptablesのnatテーブルの運用にはconntrack(コネクション追跡テーブル)のサイジングがつきまといます。そこで今回は静的NATを組むLinuxカーネルのもうひとつの機能として、iproute2によるStateless NAT構成をご紹介します。
動作確認環境
- Linuxディストリビューション : Amazon Linux 2.0 RC
- iproute2のバージョン : 3.10.0
構成例と設定コマンド
今回はありがちな静的NAT構成として、以下で設定してみます。
クライアントPCはNAT Box宛(192.168.1.1
)のリクエストを送出、NAT Boxの静的NATでWebサーバー宛(10.10.0.100
)にDNAT、戻り用にSNATもペアで設定する感じですね。iptablesで書くと以下になります。
$ sudo iptables -A PREROUTING -i eth0 -j DNAT --to-destination 10.10.0.100 $ sudo iptables -A POSTROUTING -o eth0 -j SNAT --to-source 192.168.1.1
では、iproute2でやってみます。ググるとこの辺が引っかかるのですが、手元ではip route add nat
の結果がlocalテーブルに載るなど意図した結果になりません。もう少し調べてみるとカーネル3.16以降はtcに移ったよという記事に出会ったので、tc
でやってみることにします。以下のコマンドラインです。IPアドレスは登場回数が多いのでシェル変数にしました。
$ export FROMIP=192.168.1.1/32 $ export TOIP=10.10.0.100 $ sudo tc qdisc add dev eth0 ingress $ sudo tc filter add dev eth0 parent ffff: \ protocol ip prio 1 u32 match ip dst $FROMIP \ action nat ingress $FROMIP $TOIP $ sudo tc qdisc add dev eth0 root handle 1: htb $ sudo tc filter add dev eth0 parent 1: \ protocol ip prio 1 u32 match ip src $TOIP \ action nat egress $TOIP $FROMIP
コマンドラインが複雑になった感は否めませんが、tc filter
でeth0デバイスの自ホスト(FROMIP)宛のingressトラフィックのIPアドレスをTOIPにNAT、送信元がTOIPのegressトラフィックのTOIPをFROMIPにNATしているのが読めると思います。
もちろん、IP転送自体はiptablesと同様、事前に有効にしておきましょう。
$ sudo sysctl net.ipv4.ip_forward=1 net.ipv4.ip_forward = 1 $
これでOKです。conntrackのエントリー数を気にすることなく、静的NATを動かすことが出来ます。余談ですが、当初はIPv6でNAT66を行うためにiproute2での設定を探っていたのですが、iproute2のソースinclude/linux/tc_act/tc_nat.h
の以下の記述から
struct tc_nat { tc_gen; __be32 old_addr; __be32 new_addr; __be32 mask; __u32 flags; };
IPアドレスが32ビットBigEndian決め打ちでIPv6には対応していないようなのでした、残念。 *1
まとめ
Linux iproute2でStateless NATの構成例をご紹介しました。LinuxのNAT周りの情報として何かの参考になれば幸いです。
参考URL
- linux - 1:1 Stateless NAT kernel version 3.16 or later using TC - Unix & Linux Stack Exchange
- conntrackコマンド | ツチノコブログ
脚注
- ip6tablesはNAT66が出来るので、大人しくそちらで代用することにします ↩