例えばNode.jsとかで作ったWEBサービスを外部に公開しようとした時に、80番ポートで公開したいけど一般ユーザだと1024番より上のポートしか使えない、かと言ってrootで実行はしたくない。そんなときは iptables でREDIRECTまたはDNATしてしまうのが便利です。
雑然としたメモレベルだけど備忘録として書いておく。
簡単な例
3000番ポートで動かしているサービスを80番で公開する例はこんなコマンドを打てはOK。
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000
設定ファイルに保存する場合はfilterとは別にnatテーブルの設定を追加して↓こんなふうに書けばよいです。
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# filter settings here...
COMMIT
で service iptables restart
とかしてやれば反映される。
複数IPが割り当てられてるサーバで受けたIPによって転送先のローカルポートを変える例
例えば 10.0.0.80 と 10.0.0.81 のIPを持っていた場合に、10.0.0.81に来たパケットは3001番ポートへ転送、それ以外のIPで受けた場合は3000番ポートへ転送とかする場合は↓こんな風に書けばいいです。
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -d 10.0.0.81 --dport 80 -j REDIRECT --to-port 3001
-A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# filter settings here...
COMMIT
こうすることで1台のサーバで開発環境と本番環境を別ポートで使い分けつつ、ポート指定無しのURLでアクセスが出来るようになります。
ローカルプロセスからの通信にも対応する場合はOUTPUTチェーンで書き換える
上述の設定だと外からきたパケットに対しては上手く働くけどローカルのプロセスで発生したパケットには効きません。ローカルプロセスで発生したパケットはPREROUTINGチェインを通らないからです。代わりにOUTEPUTチェインを通ります。なので外からとローカルからの両方対応しようとすると↓こうなります。
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -d 10.0.0.81 --dport 80 -j REDIRECT --to-port 3001
-A OUTPUT -p tcp -d 10.0.0.81 --dport 80 -j REDIRECT --to-port 3001
-A PREROUTING -p tcp -d 10.0.0.80 --dport 80 -j REDIRECT --to-port 3000
-A OUTPUT -p tcp -d 10.0.0.80 --dport 80 -j REDIRECT --to-port 3000
-A OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-port 3000
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# filter settings here...
COMMIT
OUTPUTチェーンで80版を全部書き換えてしまうと外部へのhttpアクセスもできなくなってしまうので、面倒ですが-d
で自分のIP全てを列挙した書き換えを行ってやる必要があります。
DNATでも出来る
DNATの場合は↓こうなる。
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination :3000
またDNATの場合はポートと一緒にIPも書き換えることが出来るという違いがある。
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.90:3000
参考
natテーブルのPREROUTINGチェインがどこに効くかとかは↓このへんの図とかが分かりやすいです。