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