DNAT, SNATをつかった通信の転送
グローバルIPをもっていないMySQLに外部から接続したい場合、グローバルIPをもっている別のサーバのiptablesのDNAT
,SNAT
を使って通信を転送することで実現できる。
カーネルパラメータの設定
別のサーバへ転送するにはカーネルパラメータnet.ipv4.ip_forward
を有効にしなければならない。
# 確認
sysctl -a | grep net.ipv4.ip_forward
# 設定
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sysctl -p
# 確認
sysctl -a | grep net.ipv4.ip_forward
iptablesの設定
PREROUTING, FORWARD
リクエストを受けるとPREROUTING
で処理され、他のサーバへ転送されることになった場合、FORWARD
チェインに移る。今回はFORWARDは特に制限を入れずデフォルトACCEPT
としておく。
POSTROUTING
別のサーバへ転送された後は、そのサーバから直接接続元に通信を返そうとしてしまう。しかし接続元とコネクションをはっているのはグローバルIPを持っているサーバであり、グローバルIPをもっていない別のサーバとは通信できないため、このままでは転送しても接続が確立できない。
接続元 -> 【PREROUTING
-> FORWARD
-> POSTROUTING
】 -> 転送先 というようにiptablesのチェインを通るが、POSTROUTING
でこの問題を解決できる。
POSTROUTING
のSNAT
で送信元IPアドレスを変更することができる。
別のサーバのプライベートIPがdestinationになっている場合、PREROUTINGのDNATで転送しようとしているはず。送信元を本来の接続先からこのサーバのプライベートIPに変更することで、通信の戻りについてもこのサーバが中継することができる。
iptablesの設定
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
#-A FORWARD -p tcp -j LOG --log-prefix "FORWARD "
略
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# -A PREROUTING -p tcp -j LOG --log-prefix "PREROUTING "
-A PREROUTING -p tcp --dport 13306 -j DNAT --to-destination 別のサーバのプライベートIP:3306
# -A POSTROUTING -p tcp -j LOG --log-prefix "POSTROUTING "
-A POSTROUTING -p tcp --dport 3306 -d 別のサーバのプライベートIP -j SNAT --to-source このサーバのプライベートIP
COMMIT
ちなみにここではコメントアウトしているが、各チェインでログを出力した場合、このサーバが中継地点としてFORWARDを大量に行っている様子が見れる。
tailf /var/log/messages | grep 3306