引き続き、linuxでルーターを作る話。

IPマスカレードしているときに、外部に対してNATでサーバーを公開する場合、iptablesのnatテーブルはこんな感じになると思います。

-A POSTROUTING -o wan -j MASQUERADE
-A PREROUTING -i wan -p tcp –dport 8080 -j DNAT –to 192.168.0.100:80

そして、そのサーバーへLANの外からも中からも同じようにアクセスしたいとします。

通常は、DDNSなどでルーターのグルーバルアドレスをサーバー名にひも付けていると思いますので、LAN側からだとルーターそのものへアクセスしてしまいます。

一つの方法としては、LANの中でDNSを立ててLANからアクセスした際にはローカルのアドレスを返すというものです。これでも大体の場合はうまくいくのですが、上記のように外と中で使っているポートが違う(WANの8080をサーバーの80に転送している)ときは、うまくいきません。

これをよしなにパケット転送して解決するのがループバックNAT(ヘアピンNAT)です。

WAN側のアドレスがわかっている場合、書き方は簡単で、

-A POSTROUTING -o wan -j MASQUERADE
-A PREROUTING -i wan -p tcp –dport 8080 -j DNAT –to 192.168.0.100:80
-A POSTROUTING -o lan -s 192.168.0.0/24 -d 192.168.0.100/32 -p tcp –dport 80 -j MASQUERADE
-A PREROUTING -i lan -p tcp -d (WANアドレス) –dport 8080 -j DNAT –to 192.168.0.100:80

外からきた場合と同じように、中からWAN側アドレスに対してアクセスした場合にはマスカレードするだけです(ここまではググれば出てくる話)。

しかし、これをサーバー上の設定ファイルに書こうと思うと困ったことがあります。それはWAN側のアドレスが変わってしまうということです。iptable-save/restoreは、マクロを展開するような機能を持っていないようですし、そもそもグローバルアドレスが変わるたびに実行しなおす仕組みが必要です。

WAN側アドレスを汎用的に指定する方法がないか探していたところみつけたのが、addrtype拡張のLOCALアドレスタイプです。これはルーティングテーブル上ローカルに配送されるものが含まれるようです。(詳細はmanを参照)

これを使えば、最後の部分は

-A PREROUTING -i lan -p tcp -m addrtype –dst-type LOCAL –dport 8080 -j DNAT –to 192.168.0.100:80

と書けて無事解決です(ルーターのLAN側アドレスを除外しないと厳密には同じではないですが)。