VPCデフォルトのDNSサーバへの通信はSecurity GroupのOutboundルールで制御できないことを確認してみた

Security GroupのOutboundルールで通信許可設定がなくても、Amazon DNSサーバ(Amazon Route 53 Resolver / Amazon Provided DNS)への通信が可能で名前解決に成功します。
2021.10.29

はじめに

清水です。タイトルのとおりですが、VPCデフォルトのDNSサーバへの通信はSecurity GroupのOutboundルールで制御ができません。このことを確認する機会があったのでまとめてみます。

VPCデフォルトのDNSサーバ

Amazon VPC使用時、DNSサーバを特に指定しない場合はVPC内にデフォルトで用意されているDNSサーバを使用することになります。現在の正式名称としては「Amazon Route 53 Resolver」、従来は「Amazon Provided DNS」や「.2 Resolver」と呼ばれ、またドキュメントには「Amazon DNSサーバ」と記載がある場合もあります。

「.2 Resolver」の名前の通り、VPCのCIDR(ネットワーク範囲)に2をプラスした値がこのDNSサーバのIPアドレスとなります。「10.0.0.0/16」のCIDRのVPCなら「10.0.0.2」、「172.31.0.0/16」なら「172.31.0.2」という具合ですね。また「169.254.169.253」で利用することも可能です。

利用の際には、VPCの設定で「DNS resolution」がEnabledであること、また使用しているDHCP options setsの「Domain name servers」でAmazonProvidedDNSが指定されてることを確認しておきましょう。

Security GroupのOutboundルール

EC2などに設定するSecurity Groupについては、例えばEC2へのSSH接続を制御するといったInbound(受信用)のルールのほか、EC2から外部のHTTPSへアクセスを許可するといったOutbound(送信用)のルールも設定可能です。デフォルト(マネジメントコンソールでSecurity Groupを作成する場合の初期状態など)ではすべてのトラフィック、すべてのプロトコル、すべてのポートをすべての送信先に開放している全開放の状態ですね。

実際にOutbound通信を制限する場合はこのルールを削除、必要な通信を許可していきます。例えば以下のような設定であれば、HTTPS (443)とHTTP (80)は許可されていますが、それ以外のポートを使った通信、例えば外部サーバにSSHするなんてことはできません。

Outbound通信を制御する場合は必要な通信までブロックしないよう注意が必要です。ただしステートレスなため戻りの通信は考慮する必要がありません。

例えば上記のようなHTTPS、HTTPのみ許可する設定を行った環境で、本DevelopersIOにアクセスすることを考えてみます。今回のテーマとなるVPCのデフォルトのDNSサーバ(Route 53 Resolover/Amazon Provided DNS)を使用している環境で、Amazon Linux 2のAMIを使ってEC2を起動します。curlコマンドでhttps://developers.ioへアクセスしてみると、無事にアクセスできました。https://dev.classmethod.jp/へのリダイレクトのレスポンスが確認できます。

[ec2-user@ip-10-84-21-235 ~]$ curl -v https://developers.io
*   Trying 13.35.49.96:443...
* Connected to developers.io (13.35.49.96) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
*  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=developers.io
*  start date: Dec 18 00:00:00 2020 GMT
*  expire date: Jan 16 23:59:59 2022 GMT
*  subjectAltName: host "developers.io" matched cert's "developers.io"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: developers.io
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Content-Length: 0
< Connection: keep-alive
< Date: Thu, 28 Oct 2021 13:18:03 GMT
< Location: https://dev.classmethod.jp/
< Server: AmazonS3
< X-Cache: Miss from cloudfront
< Via: 1.1 b5da80309d8134bb22b986ed78f27b2a.cloudfront.net (CloudFront)
< X-Amz-Cf-Pop: NRT20-C1
< X-Amz-Cf-Id: hWiiHCtpP8Xu8EN7aeFpryY9gNxMw-alzhvpLsT4I9pYEAnzkMKMnw==
<
* Connection #0 to host developers.io left intact

ところで、HTTP(S)の通信を考えてみると、実際のサーバ(ここでは13.35.49.96)への通信の前に、DNSによる名前解決の処理が入ることになります。EC2からVPCデフォルトのDNSサーバへ名前解決を行っているはずですが、Outbound通信許可(DNSなので53番ポート)は設定していなかったですよね。

Amazon DNSサーバへの通信はSecurity Groupで制御できない

Security GroupのOutboundルールでHTTPS、HTTPのみを許可した状況下で、Amazon DNSサーバへの通信が行えていたようです。こちらをもう少し確認していきましょう。先ほどと同じ、VPCのデフォルトのDNSサーバを使用している環境のAmazon Linux 2、Security GroupのOutboundルールは何も許可していない状態で確認していきます。

digコマンドで名前解決をしてみます。Security GropuのOutboundルールでDNSの通信許可はしていませんが、問題なく名前解決ができています。

[ec2-user@ip-10-84-21-235 ~]$ dig developers.io

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> developers.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60007
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;developers.io.                 IN      A

;; ANSWER SECTION:
developers.io.          60      IN      A       18.65.166.28
developers.io.          60      IN      A       18.65.166.76
developers.io.          60      IN      A       18.65.166.81
developers.io.          60      IN      A       18.65.166.5

;; Query time: 5 msec
;; SERVER: 10.84.0.2#53(10.84.0.2)
;; WHEN: 木 10月 28 09:19:08 UTC 2021
;; MSG SIZE  rcvd: 106

digコマンドの出力結果から、問い合わせたネームサーバは「10.84.0.2」でした。「/etc/resolv.conf」を確認しても「10.84.0.2」が指定されていることが確認できます。

[ec2-user@ip-10-84-21-235 ~]$ cat /etc/resolv.conf
options timeout:2 attempts:5
; generated by /usr/sbin/dhclient-script
search ap-northeast-1.compute.internal
nameserver 10.84.0.2

digコマンドの問い合わせ先ネームサーバをAmazon DNSサーバ(Amazon Route 53 Resolver / Amazon Provided DNS / .2 Resolver)のもう一つのIPアドレスである「169.254.169.253」に指定して確認してみましょう。こちらも名前解決に成功します。

[ec2-user@ip-10-84-21-235 ~]$ dig developers.io @169.254.169.253

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> developers.io @169.254.169.253
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33506
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;developers.io.                 IN      A

;; ANSWER SECTION:
developers.io.          52      IN      A       13.35.49.122
developers.io.          52      IN      A       13.35.49.96
developers.io.          52      IN      A       13.35.49.104
developers.io.          52      IN      A       13.35.49.24

;; Query time: 0 msec
;; SERVER: 169.254.169.253#53(169.254.169.253)
;; WHEN: 木 10月 28 09:23:00 UTC 2021
;; MSG SIZE  rcvd: 106

Amazon DNSサーバへの通信はSecurity GroupのOutboundルールで制御できない点が確認できましたね。なぜAmazon DNSサーバへの通信がSecurity GroupのOutboundルールの制御を受けないのか、具体的な理由までは確認できなかったのですが、AWSドキュメントにはしっかりと「制限できない」旨の記述がありました。ネットワークACLも同様だそうです。

ネットワーク ACL またはセキュリティグループを使用して、Amazon DNS サーバーとの間のトラフィックをフィルタリングすることはできません。

「Amazon DNS サーバー」 VPC の DHCP オプションセット - Amazon Virtual Private Cloud

Amazon DNSサーバ以外を指定した場合

Security GroupのOutboundルールは何も許可していない状態で、Amazon DNSサーバ以外を指定してdigコマンドで名前解決を行う場合も確認しておきましょう。

以下はネームサーバに「8.8.8.8」、Google Public DNSを指定した場合です。タイムアウトしてしまいますね。

[ec2-user@ip-10-84-21-235 ~]$ dig developers.io @8.8.8.8

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> developers.io @8.8.8.8
;; global options: +cmd
;; connection timed out; no servers could be reached

続いて、同じVPC内に建てたSimple ADをネームサーバとして指定してみます。こちらもタイムアウトしてしまいました。

[ec2-user@ip-10-84-21-235 ~]$ dig developers.io @10.84.31.187

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> developers.io @10.84.31.187
;; global options: +cmd
;; connection timed out; no servers could be reached

Amazon DNSサーバ以外のネームサーバとの通信が必要な場合、以下のようにOutboundルールでTCP、UDPそれぞれの53番ポートを許可する必要があります。

Outboudルール追加後は、以下のようにタイムアウトせず名前解決が成功しました。

[ec2-user@ip-10-84-21-235 ~]$ dig developers.io @8.8.8.8

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> developers.io @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52606
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;developers.io.                 IN      A

;; ANSWER SECTION:
developers.io.          60      IN      A       13.249.162.113
developers.io.          60      IN      A       13.249.162.127
developers.io.          60      IN      A       13.249.162.49
developers.io.          60      IN      A       13.249.162.6

;; Query time: 9 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: 金 10月 29 04:22:50 UTC 2021
;; MSG SIZE  rcvd: 106
[ec2-user@ip-10-84-21-235 ~]$ dig developers.io @10.84.31.187

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> developers.io @10.84.31.187
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54863
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;developers.io.                 IN      A

;; ANSWER SECTION:
developers.io.          60      IN      A       13.249.162.49
developers.io.          60      IN      A       13.249.162.113
developers.io.          60      IN      A       13.249.162.127
developers.io.          60      IN      A       13.249.162.6

;; Query time: 7 msec
;; SERVER: 10.84.31.187#53(10.84.31.187)
;; WHEN: 金 10月 29 04:22:52 UTC 2021
;; MSG SIZE  rcvd: 95

その他のSecurity GroupのOutboundルールの制御を受けない通信

Amazon Time Sync Service

Amazon DNSサーバへの通信がSecurity GroupのOutboundルールで制御できない点を確認しました。その他にもこのような、Security GroupのOutboundルールの制御を受けない通信はないかな、と考えたところ、Amazon DNSサーバのIPアドレスである「169.254.169.253」と同じ169.254.169ではじまるIPアドレスを使用する、Amazon Time Sync Serviceが思い当たりました。AWSの提供するマネージドNTP(時刻同期)サービスですね。

リリースはAWS re:Invent 2017期間中、インターネット接続なしで時刻同期ができる点がメリットの1つでもあります。デフォルトのDHCP option setsを使用している場合やDHCP option setsでNTPサーバを指定していない場合、Amazon Linux 2やWindows Serverなどの最新のAMIを使用していれば、このAmazon Time Sync Serviceがデフォルトで利用できるようになっています。

デフォルトのDHCP option setsを使用している(つまりNTPサーバを指定していない)VPCで、Amazon Linux 2を起動、Outboundルールは何も許可していない状態で確認してみました。以下のようにchronyc sources -vコマンドの結果、Amazon Time Sync Service(IPアドレス「169.254.169.123」)との時刻同期が成功していることが確認できます。

[ec2-user@ip-10-84-21-235 ~]$ chronyc sources -v

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unusable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 169.254.169.123               3   4   377     3   +396ns[ +505ns] +/-  401us
^? y.ns.gin.ntt.net              0  10     0     -     +0ns[   +0ns] +/-    0ns
^? 132.226.11.60                 0  10     0     -     +0ns[   +0ns] +/-    0ns
^? tama.paina.net                0  10     0     -     +0ns[   +0ns] +/-    0ns
^? v118-27-19-72.cxxt.stati>     0  10     0     -     +0ns[   +0ns] +/-    0ns
^? net1.web.yas-online.net       0  10     0     -     +0ns[   +0ns] +/-    0ns
^? mx.execve.net                 0  10     0     -     +0ns[   +0ns] +/-    0ns
^? 104.41.187.183                0  10     0     -     +0ns[   +0ns] +/-    0ns
^? ntp-b2.nict.go.jp             0  10     0     -     +0ns[   +0ns] +/-    0ns

こちらもAmazon DNSサーバ同様、ドキュメントを確認するとSecurity GroupルールもしくはネットワークACLルールを設定する必要がない旨の記載がありました。

インスタンスはインターネットにアクセスする必要はなく、アクセスを許可するためにセキュリティグループルールまたはネットワーク ACL ルールを設定する必要はありません。

Linux インスタンスの時刻の設定 - Amazon Elastic Compute Cloud

まとめ

Amazon DNSサーバ(Amazon Route 53 Resolver / Amazon Provided DNS / .2 Resolver)への通信がSecurity GroupのOutboundルールで制御できないことを確認してみました。Outboundルールに必要な通信を列挙していく際、もしDNSサーバへの通信許可を忘れてしまったとしてもAmazon DNSサーバへの通信は可能です。ただしこのままAmazon DNSサーバから他のDNSサーバに切り替える場合などでは通信許可で漏れが発生することになります。OutboundルールにDNSの通信許可を設定していない状況下でも、このAmazon DNSサーバへの通信は許可されているということを把握しておくと良いかと思いました。