“固定 IP で接続したい・・・” 送信元、あるいは接続先の IP を固定して接続したいケース、いろいろあるかと思います。最近はゼロトラストな考えでどんな IP だろうと信用しない、という考え方も見受けられるようになってきましたが、会社をまたいだ旧来のシステム間の連携など、まだまだ要件としては根強い状況かと思います。今回は “接続先の API Gateway の IP の固定化” について検討する機会がありましたので記録として残しておきたいと思います。

はじめに

残念ながら API Gateway 単体では IP を固定することはできません。他の AWS のサービスを組み合わせて実現することになります。
また、前提として名前ベースで接続できるものとしています。

アーキテクチャ

以下のようなアーキテクチャで実現してみました。

アーキテクチャ図

ポイントとしては以下の点になります。

  • API Gateway をプライベートなタイプにする
  • API Gateway に VPC エンドポイント経由で接続できるようにする
  • 外からの接続は NLB (Network Load Balancer) で受け、VPC エンドポイントに接続するようにする
  • パブリックなホストゾーンと、プライベートなホストゾーンに同じ DNS 名(カスタムドメイン)を設定する

これにより、名前ベースにはなりますが、NLB に設定されたほぼ固定的な IP アドレスへ接続することができます。「ほぼ」と書いたのは NLB を再作成すると IP アドレスが変わってしまうためです。消さない限りは固定された IP に接続が可能になります。

なお、NLB には マッピングした AZ(アベイラビリティゾーン)の数だけ IP アドレスが割り当てられます。Firewall などで許可する場合は、全ての IP について設定します(マッピングする AZ を1つにすることで IP を1つに限定できるようになりますが、その AZ で障害があったりすると接続できなくなるのでオススメしません。複数の AZ を利用しましょう)

設定のポイントなど

ここからは各サービスの設定ポイントなどを記録しておきます。リージョンはバージニア北部を利用していますので適宜読み替えてください。

VPC エンドポイント

まず初めに API Gateway の VPC エンドポイントを作成します。

サービス名として execute-api とでも入れて検索すればすぐに出てきます。
VPC を選択し、エンドポイントを作成するサブネットを選択します。
AZ(アベイラビリティゾーン)レベルの障害に備えるため、複数のサブネットを選択しましょう
また、ここで選択するサブネットはプライベートサブネットで OK ですVPC エンドポイントのサービス選択とサブネット選択

プライベート DNS 名を有効にします。
注意書きにもある通り、VPC の設定で「DNS ホスト名」と「DNS サポート(DNS 解決)」を有効化しておく必要があります。 VPC エンドポイントでのプライベート DNS 名を有効に

VPC エンドポイントに設定するセキュリティグループは NLB に設定するパブリックサブネットから HTTPS への接続ができるようにします( ANY (0.0.0.0/0) で開けておく必要はありません)。
VPC エンドポイントに設定するセキュリティグループ

ポリシーは必要に応じて設定してください(今回は割愛します)。

VPC エンドポイント に割り当てられた以下の値は後で利用するのでメモっておきます。

  • IP アドレス
  • VPC エンドポイント ID(vpce-xxxxx
  • DNS 名(vpce-XXXXXXXX.execute-api.<region>.vpce.amazonaws.com
    (※注 vpce-XXXXXXXX-XXXXXXXX-<AZ>.execute-api.<region>.vpce.amazonaws.com ではないのでご注意を)

API Gateway

続いて API Gateway です。

API Gateway はプライベートなタイプで作成します。

API Gateway の作成

「VPC エンドポイント ID」の指定で先ほど作成した VPC エンドポイントの ID を指定します。「v」と入れれば選択可能になるかと思います。

VPC エンドポイント ID の指定

左のメニューから 「リソースポリシー」を選択し、「ソース VPC の許可リスト」を選択します。
API Gateway に対し、特定の VPC からのみ接続を許可するように設定するわけです。

リソースポリシーの設定

今回は以下のように入力し、保存しました。
ハイライトしている 11行目 "aws:sourceVpc": "vpc-XXXXXXXX" は先ほどの “VPC エンドポイント ID” ではなく、“VPC ID” を設定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
	"Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpc": "vpc-XXXXXXXX"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*"
        }
    ]
}

適宜リソース、メソッドなどの設定をします(本題ではないので割愛します)。 左のメニューのリソースなどから API をデプロイします。

API のデプロイ

次に、API Gateway に設定するカスタムドメインを作成します。
公開予定のドメイン名と同じものを設定します。(例 : api.example.com
「エンドポイントタイプ」 はリージョンを選択し、「ACM 証明書」から利用するサーバ証明書を設定します。

続いて、「API マッピング」を設定します。作成した API Gateway とカスタムドメインを関連付ける設定です。
(「ステージ」が選択できない場合は、左メニューのリソースなどから一旦 API をデプロイしてください。)

API マッピングの設定

ターゲットグループ

続いて NLB に関連付けるターゲットグループを作成します。VPC エンドポイントを作成した時に割り当てられた IP アドレスを利用します。

  1. 「ターゲットタイプ」は「IP アドレス」を選択します
  2. 「プロトコル」:「ポート」は「TLS」:「443」を選択します
  3. VPC はもちろん VPC エンドポイントを作成した VPC を選択します
  4. 「ターゲットの登録」で API Gateway の VPC エンドポイントに設定された IP (設定した複数サブネットの IP 全て)を追加します

NLB (Network Load Balancer)

NLB 作成時のポイントは以下の通りです。

「ネットワークマッピング」で指定する VPC はもちろん API Gateway のエンドポイントを作った VPC を選択します。

「マッピング」で AZ を選択しますが、VPC エンドポイントを作成した AZ と同じ AZ を選択し、サブネットはパブリックサブネットを選択します。
AZ レベルの障害に備えるため、複数のサブネットを選択しましょう

「リスナーとルーティング」では以下のように設定します。

  • プロトコル : TLS
  • ポート : 443
  • デフォルトアクション(転送先) : <先ほど作成したターゲットグループ>

「セキュアリスナーの設定」では

  • デフォルトの SSL 証明書 : API Gateway のカスタムドメインの作成時に指定したものと同じものを指定
  • ALPN ポリシー : None(なし)

Route 53

Route 53 では API Gateway のところで作成したカスタムドメインを パブリックホストゾーンプライベートホストゾーン 両方に設定します。
それぞれのホストゾーンに同じドメイン名を設定するのがポイントです。

パブリックホストゾーンでは

  • 「レコードタイプ」は A
  • 「エイリアス」を有効にし、
  • 「トラフィックのルーティング先」から「Network Load Balancer へのエイリアス」を選択し、先に作成した NLB を指定します
    「リージョン」はご利用のリージョンを選択してください

パブリックホストゾーン側の設定

プライベートホストゾーンでは

  • 「レコードタイプ」は A
  • 「エイリアス」を有効にし、
  • 「トラフィックのルーティング先」から「VPC エンドポイントへのエイリアス」を選択し、先に作成した VPC エンドポイント(vpce-XXXXXXXX.execute-api.<region>.vpce.amazonaws.com)を指定します
    (※注 vpce-XXXXXXXX-XXXXXXXX-<AZ>.execute-api.<region>.vpce.amazonaws.com ではないのでご注意を)

プライベートホストゾーン側の設定

確認として、インターネットからと VPC の中から dignslookup で名前解決できるか確認します。
例えばインターネットからは、以下のようにグローバル IP が返ってきます。

dig api.example.como
   :
 (略)
   :
;; ANSWER SECTION:
api.example.com.	60	IN	A	1.1.1.1
api.example.com.	60	IN	A	2.2.2.2
   :

VPC の中(例えば EC2 など)からは、VPC エンドポイントのプライベートな IP アドレスが返ってこれば OK です。

[ec2-user@ip-10-0-10-254 ~]$ nslookup api.example.com
   :
 (略)
   :
Non-authoritative answer:
Name:	api.example.com
Address: 10.0.12.31
Name:	api.example.com
Address: 10.0.10.19

上記の出力例でいう、1.1.1.12.2.2.2 の IP アドレスが NLB を再作成しない限り、固定的に利用できるようになります。
設定としては以上になりますので、curl などで接続できるか確認してみましょう。

まとめ

NLB や VPC エンドポイントの IP アドレスが一度作成したら変わらないという性質を利用して、API Gateway への接続先 IP を固定化してみました。接続先の IP アドレスを Firewall などでフィルタリングするため固定化する必要がある、といったケースなどで活用できるのではないかと思います。

また、AWS 公式からは Global Accelerator と ALB を使った実装例がブログで紹介されています。

[Accessing an AWS API Gateway via static IP addresses provided by AWS Global Accelerator]
https://aws.amazon.com/jp/blogs/networking-and-content-delivery/accessing-an-aws-api-gateway-via-static-ip-addresses-provided-by-aws-global-accelerator/

最後に・・・

この投稿は個人的なものであり、所属組織を代表するものではありません。ご了承ください。