VPCでグローバルIP有り、IGW有りで特定のIPアドレス向けにだけ、NATを通す方法
既にグローバルIPアドレスを振っているにもかかわらず、サーバーからのアクセスは特定のIPアドレスだけにしたい場合、どうしようかという話です。そんなケース有るの?と思いますが、例えばブラウザからのGETを受けて、他のサーバーへRESTなどGETを投げる場合が当たります。
ELBやリバースプロキシを利用した場合は、Web/Appサーバー側にグローバルIPが必須ではないので、素直にPrivateSubnetとして、DefaultGatewayをNATにするのが良いですが、autoScallingを行っており、外部からの制御にグローバルIPアドレスも必要で、EIPも使えず、かつサーバーからのアクセスはNAT経由にしたい場合、どうするかを書きます。
まず、グローバルIPアドレスが必要なので、インターネットゲートウェイは必須です。NATは普通はインターネットゲートウェイがない場合にサーバー -> インターネットへ抜ける線として指定します。しかし今回は、ターゲットのIPアドレスを絞り込んで、特定の経路向けのみNATを使うという方法で、これを成り立たせます。
最終的な構成図は下記になります。
ポイントは、NATとサーバーを同じSubnetには置けないということです。正確には、同じルーティングテーブルが使えません。理由は、NATといえども、所属するSubnetに紐付けられたルーティングテーブルを参照します。ということは、NATが参照するルーティングテーブルに自分の名前が乗ってたらNATの立場に立って語りましょう
1. お、なんか来たぞ、ルーティングか、やったんぞ
2. ルーティングテーブル見に行くで
3. このアドレスは誰に投げるかというと、、俺やんけ!
4. じゃあ、俺に投げるわ
5. お、なんか来たぞ、ルーティングか、やったんぞ
....つづく
というわけでループします。正確にはNATが自分に投げるのではなくて、ユーザーがコントロール出来ないAWSシステム上に組み込まれている、いわば仮想ルーターが投げ返すはずです。
検証方法としては、EC2上にWebサーバーを立てて、そこに対してGetを打ってみて、Remote_Addrを確認しました。問題なくNATのIPアドレスが返って来ました。
ただ、「サーバー内のルーティングテーブルをいじればいいんじゃないの?」と言われればその通りです、が、台数が多い場合は、AWSのルーティングテーブルで回避するのもよいのではないでしょうか。