iptablesでNAPTする
TRexのDUTとしてUbuntu 18.10を選び、いろいろと試そうとしたときのメモ。TRexでNAPTでの戻り通信がどう処理されるのか検証するため、iptablesでのNAPT手法を調査した。
そもそものTRex環境構築はこちらを参照.
#基本的なところ
Statusを見る
-L
現行の設定を表示。ただし、tableを指定しないとfilter tableが表示される。natを見たいなら、-t natもつけてあげる必要がある。
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
##設定する
-t/--table
iptablesはTABLEとして4種類を持つ。NATで遊ぶ場合は、natを利用する。
Tableタイプ | その役割 |
---|---|
filter | パケットの透過や遮断を制御 |
nat | ネットワークアドレス変換 |
mangle | ToSフィールドの書き換え |
raw | 追跡を除外(特定の通信については、iptableでの制御をしないようにする等) |
rawに関してはちょっと特殊。iptablesを動かしている装置で処理をせず、素通しをさせたい場合に利用するらしい。DNSサーバへのアクセスはDNSサーバ自体に(あるいはその前に設置したLoad Balancerに)処理させるとか。
-j/--jump
target | 設定可能なtable | その説明 |
---|---|---|
SNAT | POSTROUTING | 出ていくパケットのIPを変換 --to-sourceオプションでは、送信元アドレスの変換範囲を指定する。 -pオプションでTCP/UDPを指定した場合、:をつけて変換後のPort番号の範囲も指定可能。 |
DNAT | PREROUTING | 宛先アドレスを変換する。入ってくるパケットのIPを変換し、サーバへRoutingする |
MASQUERADE | POSTROUTING | 変換後のアドレスを動的に割り当て |
##SNATとMASQUERADE
変換先アドレスが不定な場合(DHCP/PPPなどで割り当てられる)を想定された機能。固定的なIP接続であればSNATを利用するべき。SNATオプションとの違いとして、MASQUERADEでは、変換先IFが閉塞されるとTable情報が削除される(閉塞解除された際にアドレスが変わる可能性が高いため)。SNATではテーブルが維持される(静的な接続だから)
Static NAT
アドレス空間が被るNWの間でRoutingをするのなら、これでいいのだろうね。
iptables -t nat -A POSTROUTING -o ens39 -j SNAT --to-source 2.2.2.2
iptables -t nat -A PREROUTING -i ens38 -j DNAT --to-destination 1.1.1.1
Dynamic NAT
Globalアドレスを使いまわすのならこっち。Private:Globalを16:1とか128:1とかの比率で割り当てるようなこともしたいのだけれど、そこまで制御するやり方は見つけられなかった。TCP/UDPにだけ絞れば出来そうだったんだけれど、ICMPが入ってくると、さて。
iptables -t nat -A POSTROUTING -s 1.1.1.0/24 -o ens39 -j MASQUERADE
ICMPのDynamic NAT
ICMPのNATってどうやるのと調べてみると、ICMPのIdentifierフィールドで制御できるっぽい、ということまでは分かった。じゃあ、iptablesでそれをどうやって実現するの、というと、よく分からない。A10なんかだと、すでにあるセッション情報と同じ接続先と思われるICMPパケットが来ると、その中身を見て処理してくれる。同じような仕組みはiptablesでもあるのではないだろうか?(未調査)
NAPTのStatus確認
conntrackで確認可能。検索したらnetstat-natでと書いてあるサイトもいくつか見かけたが、少なくとも検証した条件ではnetstat-natではNAPTのステータスは確認できなかった。conntrackはaptで入手する。
sudo apt install conntrack
実際の表示は下記のようになる。
conntrack -L
tcp 6 393813 ESTABLISHED src=16.0.0.16 dst=48.0.0.14 sport=23195 dport=80 src=48.0.0.14 dst=2.2.2.3 sport=80 dport=23195 [ASSURED] mark=0 use=1
tcp 6 393813 ESTABLISHED src=16.0.0.12 dst=48.0.0.10 sport=19111 dport=80 src=48.0.0.10 dst=2.2.2.3 sport=80 dport=19111 [ASSURED] mark=0 use=1
表示例はこうなんだけれど、それぞれの意味するところはまだ調査が必要
NAPTのロギング
どのようにNAPTされたのかを調べるために、logを吐かせたい。基本的なアイデアとして
-
独自Targetを定義する(ここではNATwithLogging)
-
独自Target内でNAT変換とLoggingを行う
-
独自TargetをPOSTROUTINGにジャンプさせる
色々と考えたけれど、conntrackで変換Statusが取れるのなら、ここまでは不要かも。/var/log/syslogの溜まり方も凄まじかったし(ちょっと遊んでたら数百MBに達した)iptables -t nat -N NAPTwithLogging
iptables -t nat -A NAPTwithLogging -m state --state NEW -j LOG --log-prefix " [>] New Forward"
iptables -t nat -A NAPTwithLogging -s 1.1.1.0/24 -o ens39 -j MASQUERADE
iptables -t nat -A NAPTwithLogging -s 16.0.0.0/24 -o ens39 -j MASQUERADE
iptables -t nat -I POSTROUTING -o ens39 -j NAPTwithLogging
iptablesの初期化
-tオプションでTableを指定しないと、デフォルトのfilter Tableの設定が消される。-t natを指定して、nat Tableの設定を削除する。
iptables -F
iptables -t nat -F
iptablesの永続化
iptablesで指定したルールはOSを再起動すると消えてしまう。このため、起動後に再度設定をする必要がある。Ubuntuではiptables-persistentパッケージを使うことでコントロール可能。
sudo apt install iptables-persistent
iptablesの中身は下記に書き込まれる。
/etc/iptables/rules.v4
保存と再読み込み
sudo /etc/init.d/netfilter-persistent save
sudo /etc/init.d/netfilter-persistent reload