Route 53 プライベートホストゾーンで Alias レコードを使わずに CNAME レコードを使ってしまうとハマることがある

Route 53 にはホストゾーンに登録したレコードの名前解決を別の AWS リソースにルーティングできる Alias レコードという機能があります。

例えば VPC にインターフェースエンドポイントを作成し、プライベート DNS ホスト名を有効にすると、このインターフェースエンドポイントに対して endpoint_id.service_id.region.vpce.amazonaws.com といったホスト名のレコードが自動的に裏で作られ、VPC 内で名前解決できるようになります。

ここで、自動的に作成されたプライベート DNS ホスト名ではなく、独自のドメインのホスト名でこのインターフェースエンドポイントの名前解決したい場合、独自のドメインのプライベートホストゾーンに Alias レコードを設定することで実現できます。

## Alias レコードの動作

Alias レコードの具体例を見てみます。
| レコード名 | タイプ | エイリアス | ルーティング先 |
|:-|:-|:-|:-|
| sftp.intra.example.com | A | Yes | endpoint_id.service_id.region.vpce.amazonaws.com |

上記の例だと、sftp.intra.example.com という独自ドメインのホスト名を名前解決すると、元のインターフェースエンドポイントのプライベート DNS ホスト名（endpoint_id.service_id.region.vpce.amazonaws.com）を名前解決した結果の IP アドレスが返ってくる仕組みです。

同様に、ALB などの AWS リソースに対するルーティングも Alias レコードで設定できます。

> エイリアスレコードを使用すると、CloudFront ディストリビューションや Amazon S3 バケットなど、選択した AWS リソースにトラフィックをルーティングできます。また、エイリアスレコードにより、ホストゾーン内のあるレコードから別のレコードにトラフィックをルーティングできます。

https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html

## CNAME レコードと Alias レコードとの違い

ここで、DNS には元々 CNAME レコードというものがあり、Route 53 ホストゾーンでも CNAME を使って上記の Alias レコードと同じようなことができます。

しかし、Route 53 ホストゾーンの Alias レコードと CNAME レコードには、名前解決の挙動に次の大きな違いがあります。

- Alias レコードは直接ルーティング先の AWS リソースのホスト名を名前解決した結果の IP アドレスを返す
- CNAME レコードは AWS リソースのホスト名を返すので、**再帰問い合わせをかけないと IP アドレスを受け取れない**

そのため、閉域のオンプレミスのように、**任意のドメインへの再帰問い合わせができない環境下では、CNAME レコードを使うと名前解決ができない場合があります**。

## CNAME レコードは再帰問い合わせができない環境下では名前解決できない

具体的なシチュエーションを例に挙げてみます。

閉域同士で接続されたオンプレミスと VPC があり、オンプレミスのリゾルバ DNS サーバーは、VPC に関連づけられた Route 53 プライベートホストゾーンで管理しているドメインへの名前解決要求を、VPC の Route 53 インバウンドエンドポイントへ条件付きフォワーダーで転送している環境があるとします。次の記事で作成したような環境です。

https://qiita.com/takeda_h/items/bd7269a539079daeaa5d

この環境で、intra.example.com というドメインをプライベートホストゾーンで管理していることとし、オンプレミスの DNS サーバーはこのドメインに対する名前解決要求をインバウンドエンドポイントにフォワードし、その他のドメインは再帰問い合わせをしない設定をしていることとします。

このプライベートホストゾーンに、次のような Alias レコードを設定します。

| レコード名 | タイプ | エイリアス | ルーティング先 |
|:-|:-|:-|:-|
| sftp.intra.example.com | A | Yes | endpoint_id.service_id.region.vpce.amazonaws.com |

この状態でオンプレミスの DNS サーバーに sftp.intra.example.com の名前解決を要求すると、インバウンドエンドポイントに要求が転送され、インバウンドエンドポイントからは直接 endpoint_id.service_id.region.vpce.amazonaws.com を名前解決した結果の IP アドレスが返るので、名前解決は成功します。

では、Alias レコードではなく以下のような CNAME レコードを設定した場合はどうなるでしょうか？

| レコード名 | タイプ | エイリアス | 値 |
|:-|:-|:-|:-|
| sftp.intra.example.com | CNAME | No | endpoint_id.service_id.region.vpce.amazonaws.com |

先ほどと同様にオンプレミスの DNS サーバーに sftp.intra.example.com の名前解決を要求すると、インバウンドエンドポイントに要求が転送されるのですが、インバウンドエンドポイントからは CNAME に設定された endpoint_id.service_id.region.vpce.amazonaws.com というホスト名が一旦返ります。そのため、DNS サーバーは endpoint_id.service_id.region.vpce.amazonaws.com を再帰問い合わせしようとします。

しかし、このオンプレミスの DNS サーバーでは .amazonaws.com への名前解決を許可していないため、名前解決は失敗します。

## Alias レコードを使える場合は Alias レコードを使おう

このように Route 53 ホストゾーンの Alias レコードと CNAME レコードは、一見同じような AWS リソースへのルーティングができそうですが、挙動が異なるため、Alias レコードが使える場合は Alias レコードを使うことが推奨されます。

Route 53 の DNS ルーティングについて分かりやすい記事を白鳥さんが書かれていたのでシェアします。

https://business.ntt-east.co.jp/content/cloudsolution/ih_column-201.html

以下 Alias レコードについて引用です。

> ### できるだけCNAMEレコードを使用せず、Aliasレコードを使用する
> 
> CNAMEレコードでも複数のルーティングポリシーを構成可能ですが、以下の理由でAliasレコードが使えるところではAliasレコードを使用します。
> 
> - DNSクエリ回数を減らし、パフォーマンスを改善する
> - AWSリソース名に対してAliasレコードを使うことでDNSクエリ料金が無料となるため、DNSクエリのコストを改善する

Alias レコードは再帰問い合わせにならないためパフォーマンスが改善され、また仕様上コスト的に有利なことが分かりました。

以上のことから、　Alias レコードが使える場合は優先して使うようにしましょう。