🦔

Route53 Inbound Resolver Endpoint を CDK で作成してみた

に公開

AWSの他アカウントのVPCや、マルチクラウドのDNS連携、オンプレとのDNS連携を行う構成では、Route53 Resolver Endpoint(Inbound/Outbound) を利用する場面が多くあります。
その中でも、オンプレミス環境や別ネットワークから Route53 Private Hosted Zoneを参照したい 場合に利用するのが Inbound Resolver Endpoint です。

今回は、この Inbound Resolver Endpoint を AWS CDK(TypeScript)で作成した際のコード例とポイントをまとめます。

Route53 Inbound Resolver Endpoint に関する説明

Classmethod 様が大変分かりやすい記事を書いてくれていますので、参照してください。

【ざっくり解説】Route 53 ResolverとResource Access Managerについて3段階で図解説する

というのはあまりにも乱暴なので、若干解説します。

無い場合の問題点

オンプレからALBの名前解決を考えます。
通常、ALBは固定IPを持たず、内部的に複数のENIを保持しており、そのIPアドレスはスケールやAZの状態に応じて都度変動します。
そのため、オンプレ側でALBのIPを静的に登録することはできず、必ずDNSによる名前解決が必要となります。

  1. ALBのIPは固定されないため、オンプレ側で静的に登録できない
    • ALBは内部的に複数IPを持ち、スケールやAZの状態に応じて変動する。
    • そのため、オンプレで「ALBのIPを直接指定してアクセスする」ことはできない。
  2. オンプレからRoute53 Resolverに直接アクセスできない
    • AWSの内部DNS(VPC DNS)は、VPC内からのみ利用可能。
    • オンプレ環境からは、この内部DNSへ直接DNSクエリを送ることができない。
  3. オンプレはRoute53 Private Hosted Zoneを参照できない
    • PHZはVPCに紐づく内部専用ゾーンであり、外部ネットワークからは参照できない。
    • そのため、ALBのエイリアスレコードをオンプレ側のDNSが解決することはできない。

以上の ①〜③ により、
オンプレから内部 ALB に接続するための前提条件である “名前解決” がそもそも成立しない
という問題が発生します。

ある場合の名前解決

オンプレから内部ALBの名前解決を行うためには、Route53 Resolver Inbound Endpointを利用します。

Inbound Endpointを配置すると、オンプレから送られてきたDNSクエリを
AWS内部のRoute53 Resolverが受け取り、Private Hosted Zone(PHZ)のレコードを参照して名前解決できるようになります。

  1. オンプレからInbound EndpointにDNSクエリをフォワード
    • オンプレのDNSサーバー(またはクライアント)に対して、ALBのFQDNを自環境内で解決できない場合、AWS側のInbound Endpointにフォワードするように設定する。
    • これにより、オンプレ側では直接AWSのDNSにアクセスできなくても、DNSクエリをAWS側に転送できる。
  2. Route53 Resolver が PHZ を参照して名前解決
    • Inbound Endpointが受信したクエリは、VPC内のRoute53 Resolverに渡される。
    • Resolver は、VPCに紐づくPrivate Hosted Zoneを参照し、ALBのエイリアスレコード(Alias Target)を評価して内部的に割り当てられたALBのIPを特定する。
  3. 解決したALBのIPをオンプレへ返却
    • Resolverによって名前解決が完了すると、そのDNS応答がInbound Endpoint → Transit Gateway → Direct Connectの経路でオンプレ側へ返却される。
    • オンプレのDNSクライアントは、ALBのIPを取得し、内部ALBへアクセスできる。

今回作成するリソース

ということで、今回作成するリソースを紹介します。
CDKで以下、2種類のリソースを作成します。

  1. Security Group(Route53 Resolver Inbound Endpoint 用)
  2. Inbound Resolver Endpoint(ResolverEndpoint 本体)

1. Inbound Resolver Endpoint 用 Security Group

まずは、Resolver Endpoint が利用するセキュリティグループです。
以下が作成した CDK コードです。

export class InboundResolverEndpointSecurityGroupResource extends Construct {
  /**
   * @type {ec2.SecurityGroup} Route53 Inbound Endpoint用 セキュリティグループ.
   */
  public readonly securityGroup: ec2.SecurityGroup;

  constructor(scope: Construct, id: string, props: IInboundResolverEndpointSecurityGroupResourceProps) {
    super(scope, id);

    // セキュリティグループを作成
    this.securityGroup = new ec2.SecurityGroup(this, 'Resource', {
      vpc: props.vpc,
      allowAllOutbound: false,
      disableInlineRules: true,
      description: `Route53 Inbound Resolver Endpoint Security Group`,
    });

    // インバウント、アウトバウンドルール追加
    this.securityGroup.connections.allowToAnyIpv4(
      ec2.Port.allTcp(),
      'Route53 Inbound Resolver Endpoint - Any, All TCP',
    );
    this.securityGroup.connections.allowToAnyIpv4(
      ec2.Port.allUdp(),
      'Route53 Inbound Resolver Endpoint - Any, All UDP',
    );
    this.securityGroup.connections.allowFromAnyIpv4(
      ec2.Port.DNS_TCP,
      'Any, DNS TCP - Route53 Inbound Resolver Endpoint',
    );
    this.securityGroup.connections.allowFromAnyIpv4(
      ec2.Port.DNS_UDP,
      'Any, DNS UDP - Route53 Inbound Resolver Endpoint',
    );

    Tags.of(this.securityGroup).add('Name', `sg-route53-inbound-resolver`);
  }
}

設計ポイント

Inbound Resolverに付与するSecurityGroupのインバウンド、アウトバウンドルールには以下の要件が定められています。
Resolver endpoint scaling

アウトバウンドルールは不要だという説もありますが、
一旦は公式を信じて設定を行っています。

受信ルール

プロトコルのタイプ ポート番号 送信元 IP
TCP 53 0.0.0.0/0
UDP 53 0.0.0.0/0

送信ルール

プロトコルのタイプ ポート番号 送信先 IP
TCP All 0.0.0.0/0
UDP All 0.0.0.0/0

2. Inbound Resolver Endpoint の作成

今回のメインリソースである Inbound Resolver Endpoint を作成します。

export class InboundResolverEndpointResource extends route53resolver.CfnResolverEndpoint {
  constructor(scope: Construct, id: string, props: IInboundResolverEndpointResourceProps) {
    super(scope, id, {
      direction: 'INBOUND',
      ipAddresses: [
        {
          subnetId: props.endPoint1aSubnetId,
        },
        {
          subnetId: props.endPoint1cSubnetId,
        },
      ],
      securityGroupIds: props.securityGroupIds,
      protocols: ['Do53'],
      resolverEndpointType: 'IPV4',
      tags: [
        {
          key: 'Environment',
          value: 'Production',
        },
      ],
    });
  }
}

設計ポイント

■ direction: 'INBOUND'

Inbound Resolver Endpoint を作成するため、direction: 'INBOUND' を指定します。

■ Multi-AZ 構成

ipAddresses には複数のサブネットを指定できます。
複数のサブネットIDを指定することで、Endpointが複数AZに跨って展開され、Route53 Resolverの冗長性が確保されます。
一般的には2AZ以上での構成が推奨されています。

■ プロトコルの選択

protocols: ['Do53'] を指定しています。
Route 53 Resolverがサポートしているプロトコルのうち、最も一般的なDo53(DNS over Port 53)を利用します。
通常のDNS解決であればDo53だけで十分かなと思います。

■ Security Group

Security Group は、事前に作成した Resolver 専用のものを指定します。

作成物

SecurityGroup


Inbound Resolver Endpoint


まとめ

今回、CDK を使って Route53 Resolver Inbound Endpoint を構築するコードをご紹介しました。
なかなか使用しないサービスだと思うので、CDKでの作成方法もマスターできて良かったです。

参考

Discussion