シナリオ
インターネット上のサービスがPrivate Subnet上にあるRDSにJDBCでアクセスする
背景
インターネット(クラウド)上のサービスがAWS上のデータベースにアクセスできるように、データベースをPublic Subnetに置かないといけなくなったのですが、データベースを大公開しているようで気持ちが悪い。接続元のサービスのグローバルIPは帯域が決まっているので、もちろんSecurity Groupの設定で特定IPレンジの接続に限定できるのですが、やっぱり以下の絵のようにしたい!ということで考えました。
Private Subnetへの接続
Private Subnet上のホストにアクセスしたいという場合、以下のパターンが考えられます。
1. SSH Port Forwarding (SSH Tunneling)
手元のマシンからSSHを使って踏み台サーバーのポート(22)に接続します。踏み台サーバーからターゲットへはポート転送が設定されているため、閉じた領域のターゲットとあたかも直接通信しているような気になれる、それがSSHポートフォワーディングです。
2. VPN/DXでアクセス
VPNやDirect Connectの専用回線を使えば、AWS上のリソースはあたかもローカルネットワークにあるかのように扱えるので、経路を気にする必要はなくなります。
3. NATインスタンス/Proxyを経由してアクセス
今回取り上げるのがこれです。インターネット上のサービスからダイレクトにデータベースにアクセスしたいのですが、SSHポートフォワーディングのように自分のマシンにターゲットまでのSSHトンネル用セッションを張ることはできません。またVPNのような専用回線を張ることもできません。そこで、Public SubnetにNATインスタンスを立ててPrivate Subnetまでの経路を確保してもらいます。
シナリオとしては、パブリックアクセス可能な接続ポイントの適当なポートへ接続すると、裏側でデータベースのポートに転送される状態をNATインスタンスで実現します。squidやnginxのリバースプロキシでも実現できそうですが、より簡単そうなNATインスタンスを使います。
構築
事前準備
踏み台、VPC, Public Subnet, Private Subnet, RDSを作っておく
VPC一式はこちらで作れます。
https://aws.amazon.com/jp/quickstart/architecture/vpc/
作成
-
Amazon EC2 コンソールのAMI検索画面でamzn-ami-vpc-natを検索して起動する
-
EC2 コンソールから立ち上げたEC2インスタンスを選択し、「アクション」-「ネットワーキング」-「送信元/送信先の変更チェック」(SrcDestCheck)属性を無効にする
-
必要に応じてセキュリティーグループをattach。インバウンドの許可設定は、接続してくる適当なポート番号と
0.0.0.0/0
でOKですが、本番運用時に特定IPに変える -
必要に応じてルートテーブルを変更
-
iptablesの設定を変える
NATインスタンスにec2-userでログインする。初期状態では
/etc/sysconfig/iptables
がいないので、
sudo service iptables save
でつくる
その中にpreroutingのエントリーを追加する
iptables -t nat -A PREROUTING -p tcp -d <sourceのIPかCIDR> --dport <sourceのポート> -j DNAT --to-destination <targetのIP:targetのポート>
IPはどちらもPrivate IPなので注意。ターゲットのDBのIPはhost名からdigっておく
iptablesを変更した後はsudo service iptables save
しないとサービス再起動で元に戻るのため注意。
6.アプリケーションからNATのPublic IPとNATで指定したポートで接続してみる。接続した後に適当なクエリを実行してみて結果が返ってくればOK!
参考
アーキテクチャ
NATインスタンスとは
NATインスタンスの作成