やりたいこと
NLBまでの通信は、IPv6で通信し、 NLB以降の通信は、IPv4とする。
少々煩雑ですが、構成はこんなイメージです。
手順
VPC
VPCは既存のものを利用しましたので説明は省きます。
ない場合は、プライベートサブネットが最低2つ以上あるVPCを2つ準備しておきます。
EC2
NLBにリクエストするためにテスト用のEC2を準備しておきます。
IPv6を有効にする必要があるので以下の方の記事を参考に作成しておきましょう。
なお、セキュリティグループのアウトバウンドルールでIPv6を許可しておくことに注意が必要です。
EC2の作成が完了したら、ifconfigなどで、IPv6アドレスが取得できていることを確認しておきましょう。
ifconfig
enX0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 9001
inet 172.31.19.5 netmask 255.255.240.0 broadcast 172.31.31.255
inet6 fe80::c08:f3ff:fe7b:zzzz prefixlen 64 scopeid 0x20<link>
inet6 2406:da14:daa:7d00:yyyy:9f5f:c5c9:b43d prefixlen 128 scopeid 0x0<global>
VPCエンドポイント
API GatewayのVPCエンドポイントを作成します。
サービス名にcom.amazonaws.ap-northeast-1.execute-api
を指定します。
IPアドレスは固定にしておきたいため、「IPv4アドレスの指定」にチェックをいれ、「IPv4アドレス」を入力します。
API Gateway と Lambda
API GatewayとLambdaは、SAMでデプロイしてしまいます。
template.yaml
の プライベートサブネットid1,プライベートサブネットid2,セキュリティグループは自身のものに置き換えて下さい。
VPCエンドポイントidは先程の手順で作成しAPI GatewayのVPCエンドポイントのidに置き換えます。
後は sam build
,sam deploy
でデプロイしておきます。
ACM
既存のものを利用するので詳しい手順は省きますが、証明書を準備していない場合は、ドキュメントを参考に準備しておきましょう。次のNLBをTLSで通すのに必要です。
NLB
先にターゲットグループを作成しておきます。
「TLS 443」 を指定します。
指定するIPアドレスタイプは「IPv4」です。
VPCはNLBを配置するVPCを選択します。
IPアドレスに先程作成したVPCエンドポイントのIPを登録していきます。
次にNLBを作成していきます。
スキームはVPC内からのアクセスのみに許可するので、「内部」にします。
IPv4アドレスタイプはもちろん「Dualstack」を選択します。
プライベートサブネットを2つ以上選択します。(画像はパブリックサブネットとなっていますが気にしないでください。)
IPv4アドレス、IPv6アドレスは本当は固定にすべきなのですが面倒だったので、動的のままにしてあります。
つい最近のアップデートでNLBにセキュリティグループを適用させることができるようになりましたが、今回はシンプルにいきたいので、適用しません。
「TLS 443」 を指定し、先程作成したターゲットグループを指定します。
Route53
プライベートホストゾーンに、NLBを自身のドメインに対して、AAAAレコードを作成します。
動作確認
まず、EC2からNLBのDNS名に対して、名前解決ができるか確認しておきます。
dig nlb-XXX.elb.ap-northeast-1.amazonaws.com. AAAA
;; ANSWER SECTION:
nlb-XXX.elb.ap-northeast-1.amazonaws.com. 55 IN AAAA 2406:da14:daa:7d00:aaa:515:446a:879e
nlb-XXX.elb.ap-northeast-1.amazonaws.com. 55 IN AAAA 2406:da14:daa:7d01:bbb:ab6d:c9f7:8dc4
nlb-XXX.elb.ap-northeast-1.amazonaws.com. 55 IN AAAA 2406:da14:daa:7d02:ccc:dde1:6d28:4840
次に自身のドメインに対して名前解決ができるか確認しておきます。
dig test.XXX.com AAAA
;; ANSWER SECTION:
test.XXX.com. 60 IN AAAA 2406:da14:daa:7d00:aaa:515:446a:879e
test.XXX.com. 60 IN AAAA 2406:da14:daa:7d01:bbb:ab6d:c9f7:8dc4
test.XXX.com. 60 IN AAAA 2406:da14:daa:7d02:ccc:dde1:6d28:4840
名前解決ができることを確認できたら、早速自身のドメインに対して通信してみましょう。
curl -v https://test.XXX.com/prod/hello -H 'Host: XXX.execute-api.ap-northeast-1.amazonaws.com'
* Trying [2406:da14:daa:7d00:aaa:515:446a:879e]:443...
* Connected to test.XXX.com (2406:da14:daa:7d00:aaa:515:446a:879e) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
* CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
* subject: CN=test.XXX.com
* start date: Oct 23 00:00:00 2023 GMT
* expire date: Nov 20 23:59:59 2024 GMT
* subjectAltName: host "test.XXX.com" matched cert's "test.XXX.com"
* issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M02
* SSL certificate verify ok.
* using HTTP/1.x
> GET /prod/hello HTTP/1.1
> Host: XXX.execute-api.ap-northeast-1.amazonaws.com
> User-Agent: curl/8.3.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/1.1 200 OK
< Server: Server
< Date: Tue, 24 Oct 2023 09:43:55 GMT
< Content-Type: application/json
< Content-Length: 26
< Connection: keep-alive
< x-amzn-RequestId: f9421056-52bf-4d50-b23e-d41ae5bfcfe8
< x-amz-apigw-id: NTO6TFMqNjMFy0w=
< X-Amzn-Trace-Id: Root=1-653791db-29199c1f0b7e7f61a2ab530f;Sampled=0;lineage=9f7680ef:0
<
* Connection #0 to host test.XXX.com left intact
{"message": "hello world"}
無事IPv6から接続できたことが確認できたと思います。
ログ
一応ログを確認しておきましょう。(ログの作成手順は省きます。)
先程AAAAレコーは確認しておきましたが、NLBからAPI Gatewayまでの通信はIPv4になるので先にNLBのAレコードも確認しておきましょう。
dig nlb-XXX.elb.ap-northeast-1.amazonaws.com. A
nlb-XXX.elb.ap-northeast-1.amazonaws.com. 60 IN A 172.31.3.77
nlb-XXX.elb.ap-northeast-1.amazonaws.com. 60 IN A 172.31.17.207
nlb-XXX.elb.ap-northeast-1.amazonaws.com. 60 IN A 172.31.40.17
NLBのログ
EC2(2406:da14:daa:7d00:yyy:9f5f:c5c9:b43d)からNLB(2406:da14:daa:7d00:aaa:515:446a:879e)までは、IPv6で通信できていることが確認できます。
tls 2.0 2023-10-24T10:07:44 net/nlb/b2d777644ffaacc9 f25f1970aa026308 2406:da14:daa:7d00:yyy:9f5f:c5c9:b43d:53732 2406:da14:daa:7d00:aaa:515:446a:879e:443 77 37 124 352 - arn:aws:acm:ap-northeast-1:123456789012:certificate/- - TLS_AES_128_GCM_SHA256 tlsv13 - test.XXX.com - - - 2023-10-24T10:07:44
API Gatewayのログ
NLB(172.31.17.207)からアクセスが来ていることが確認できました。
{
"requestId": "8ecb4541-a106-40db-9785-d3b564917845",
"ip": "172.31.17.207",
"caller": "-",
"user": "-",
"requestTime": "24/Oct/2023:10:47:11 +0000",
"httpMethod": "GET",
"resourcePath": "/hello",
"status": "200",
"protocol": "HTTP/1.1",
"responseLength": "26"
}