脳みそスワップアウト

揮発性なもので。おもにPHPのこととか。

iptablesによる透過プロキシ

メールサーバの移行の際に、DNS浸透の有無によって新旧サーバにメールが届くのを回避するために透過プロキシを使った。

IPv4 フォワーディング設定

有効になっているか確認。

$ sysctl net.ipv4.ip_forward
### "1" であることを確認
net.ipv4.ip_forward = 1

無効(0)になっている場合は有効化と、ネットワーク再起動時用に設定を行う。

$ sudo sysctl -w net.ipv4.ip_forward=0
net.ipv4.ip_forward = 0

/etc/sysctl.conf

@@ -7 +7 @@
-net.ipv4.ip_forward = 0
+net.ipv4.ip_forward = 1

透過プロキシ設定

以下を /etc/sysconfig/iptables の先頭に追記する。
ここではSMTPの(25,587)、POP(110)、IMAP(143)を転送している。

*nat
-A PREROUTING -m multiport -p tcp --dports 25,587,110,143 -j LOG --log-prefix "MAIL_NAT_LOG: " --log-level=info
-A PREROUTING -m multiport -p tcp --dports 25,587,110,143 -j DNAT --to-destination ${新サーバ}
-A POSTROUTING -m multiport -p tcp --dports 25,587,110,143 -j SNAT --to-source ${旧サーバ}
COMMIT

適用。
これを実施した瞬間からプロキシが有効となり、すべてのパケットは新サーバへと転送される。
DNSが浸透しているクライアントからは直接新サーバへ、
浸透していないクライアントからは旧サーバからproxyされて新サーバへ。

$ sudo service iptables restart

おまけ

もちろんポートを変えた転送もできる。
PREROUTING で、サーバA 12345/tcp へのパケットのDESTを、サーバB:80 に書き換える。
POSTROUTING で、そのパケットのSRCを、サーバA:12345 に書き換える。
これでクライアントには サーバA:12345 とやりとりしているように見える。

*nat
-A PREROUTING -p tcp --dport 12345 -j DNAT --to-destination ${サーバB}:80
-A POSTROUTING -p tcp -d ${サーバB} --dport 80 -j SNAT --to-source ${サーバA}:12345
COMMIT

独自のチェインを作っていたり、ローカルからはproxyしない必要があったりする場合は、
チェイン指定やインタフェイス指定などでより細かな制御をすること。

L3レベルでの制御なのでバーチャルドメイン単位の移行などはできないけど、
運用的に許されるのであれば、下位層での対応はとても楽ちん。