LoginSignup
1
1

以前の記事を社内で紹介した際、いろいろと議論が進みまして、非常に面白いツッコミを入れてくださった先輩がいらっしゃいます。
そのツッコミの内容はタイトルの通りなのですが、
「あ、確かにどうなんやろか?Route 53は明確に公式ドキュメントに権威サーバって書いているけど、暗黙的にできるDNSサーバはどうなんやろか?」
と疑問に思いましたので、検証してみました。

長くインフラエンジニアやってる癖に非常にお恥ずかしのですが、DNSの構成にあんまり詳しくないです。
間違えてたらごめんなさい。

検証環境を簡易に作成するために前提としてお伝えすること

AWSもAzureもどちらもEC2、VMを構築した際、暗黙的に内部ネットワーク(AWSだと同一VPC、Azureだと同一仮想ネットワーク、AWSもAzureもどちらもVPC Peering、Vnet Peeringで接続した場合はこの接続されたVPC、仮想ネットワークも含みます)で名前解決可能なFQDNが割り振られます。

検証環境

はい。
当然AWSのEC2もAzureのVMもローカルIPアドレスを持っているので、このローカルIPアドレスと暗黙的に割り振られるFQDNとを管理している権威DNSサーバがどこかにいるはずです。
この暗黙的に割り振られるFQDNと、暗黙的に構築されるDNSサーバで検証を行います。

確認したいこと

この権威サーバが暗黙的に構築されるDNSサーバなのか、はたまた別で権威サーバが構築されているのか?
これを調べます。

環境構築

直前にアップした記事はAWSでSpotインスタンスについての記事ですが、これ実はこの検証環境を作るためのコードなんですよね。
ついでにSpotインスタンスの検証も終わらせました。
なのでTerraformのコードもそのまま同じものを使い回します。

変数設定

varriable.tf
# ---------------------------
# Variables - 変数設定
# ---------------------------

# region
# ap-northeast-1 東京リージョン
# ap-south-1 ムンバイリージョン
variable "region" {
  default = "ap-south-1"
}

# 環境種別(本番:prd,ステージング:stg,開発:dev)
variable "env_type" {
  default = "dev"
}

# システム名
variable "sys_name" {
  default = "test_lb_dns"
}

# availability_zone
variable "availability_zone" {
  type = object({
    a = string
    b = string #ムンバイリージョンで利用
    c = string
  })
  default = {
    a = "ap-south-1a" # ムンバイ(インド)のアベイラビリティゾーン
    b = "ap-south-1b" # ムンバイ(インド)のアベイラビリティゾーン
    c = "ap-south-1c" # ムンバイ(インド)のアベイラビリティゾーン
  }
}

# ------------------------------
# Web Server と Application Load Balancer用VPC作成
# ------------------------------
# vpc address
variable "vpc_address_pre" {
  default = "10.0."
}

variable "vpc_address_suf" {
  default = "0.0/23"
}

# private subnet suffix address01
variable "private_address_suf01" {
  default = "1.0/26"
}

# private subnet suffix address02
variable "private_address_suf02" {
  default = "1.64/26"
}

# private subnet suffix address03
variable "private_address_suf03" {
  default = "1.128/26"
}

# public subnet suffix address01
variable "public_address_suf01" {
  default = "0.0/24"
}

# EC2のインスタンスタイプ
variable "ec2_instance_type" {
    default = "t2.micro"
}

# VPC Endpoint
variable "vpc_endpoints" {
  type    = list(any)
  default = ["ssm", "ssmmessages", "ec2messages"]
}

はい。
どうってことは無いです。

main.tf

main.tf
# ---------------------------
# main
# ---------------------------

terraform {
  required_version = ">= 1.4" # Terraformのバージョンを1.4以上に指定
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "= 5.22.0" # AWSプロバイダのバージョンを5.22.0に固定
    }
  }
}

# プロバイダー設定
provider "aws" {
  region = var.region
}
これも至ってシンプルですね。

VPC

vpc.tf
# ---------------------------
# Web Server用VPC 構築
# ---------------------------

# VPC
resource "aws_vpc" "vpc" {
  cidr_block           = "${var.vpc_address_pre}${var.vpc_address_suf}"
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    Name = "${var.env_type}-${var.sys_name}-vpc"
  }
}

# ---------------------------
# Subnet 構築
# ---------------------------

resource "aws_subnet" "sn_public_1a" {
  vpc_id            = aws_vpc.vpc.id
  cidr_block        = "${var.vpc_address_pre}${var.public_address_suf01}"
  availability_zone = var.availability_zone.a
  tags = {
    Name = "${var.env_type}-${var.sys_name}-sn-public-1a"
  }
}

# Internet Gateway
resource "aws_internet_gateway" "igw_vpc" {
  vpc_id = aws_vpc.vpc.id
  tags = {
    Name = "${var.env_type}-${var.sys_name}-igw-vpc"
  }
}

# ---------------------------
# Route table 作成
# ---------------------------
resource "aws_route_table" "rt_sn_public" {
  vpc_id = aws_vpc.vpc.id
  # Default GatewayをInternet Gatewayに向ける
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw_vpc.id
  }
  tags = {
    Name = "${var.env_type}-${var.sys_name}-rt-sn-public"
  }
}


# SubnetとRoute tableの関連付け
resource "aws_route_table_association" "associate_rt_sn_public_1a" {
  subnet_id      = aws_subnet.sn_public_1a.id
  route_table_id = aws_route_table.rt_sn_public.id
}

シンプルな構成にしたので本来Public SubnetとPrivate Subnetに分けて管理すべきところをPublic Subnetのみにしました。

security group

security_group.tf
# ---------------------------
# Security Group
# ---------------------------

# ---------------------------
# EC2用 Security Group作成
# ---------------------------

#ec2_app01(Front End EC2 1台目用SG)
resource "aws_security_group" "sg_ec2_app01" {
  name   = "${var.env_type}-${var.sys_name}-sg-ec2-app01"
  vpc_id = aws_vpc.vpc.id
  tags   = {
    Name = "${var.env_type}-${var.sys_name}-sg-ec2-app01"
  }

  # インバウンドルール
  # For SSM
  ingress {
    description     = "AllowHttpsInBoundFromVPC(for SSM)"
    from_port       = 443
    to_port         = 443
    protocol        = "tcp"
    cidr_blocks = ["${var.vpc_address_pre}${var.vpc_address_suf}"]
  }

  # アウトバウンドルール
  egress {
    description = "AllowAnyOutBound"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# クライアント相当Windows Server用SG
resource "aws_security_group" "sg_ec2_client01" {
  name   = "${var.env_type}-${var.sys_name}-sg-ec2-client01"
  vpc_id = aws_vpc.vpc.id
  tags   = {
    Name = "${var.env_type}-${var.sys_name}-sg-ec2-client01"
  }

  # インバウンドルール
  # For EC2-app01 ICMPv4
  ingress {
    description     = "AllowICMPv4InBoundFromEC2(for app01)"
    from_port       = -1
    to_port         = -1
    protocol        = "icmp"
    security_groups = [aws_security_group.sg_ec2_app01.id]
  }

  # For RDPアクセス
  ingress {
    description     = "AllowRdpInBoundFromHome"
    from_port       = 3389
    to_port         = 3389
    protocol        = "tcp"
    cidr_blocks = ["123.225.10.132/32"]
  }

  # アウトバウンドルール
  egress {
    description = "AllowAnyOutBound"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# ---------------------------
# SSM用 Vpc endpoint Security Group作成
# ---------------------------

resource "aws_security_group" "sg_ssm" {
  name   = "${var.env_type}-${var.sys_name}-sg-ssm"
  vpc_id = aws_vpc.vpc.id
  tags   = {
    Name = "${var.env_type}-${var.sys_name}-sg-ssm"
  }

  # インバウンドルール
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["${var.vpc_address_pre}${var.vpc_address_suf}"]
  }

  # アウトバウンドルール
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "sg_ssmmessages" {
  name   = "${var.env_type}-${var.sys_name}-sg-ssmmessages"
  vpc_id = aws_vpc.vpc.id
  tags   = {
    Name = "${var.env_type}-${var.sys_name}-sg-ssmmessages"
  }

  # インバウンドルール
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["${var.vpc_address_pre}${var.vpc_address_suf}"]
  }

  # アウトバウンドルール
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "sg_ec2messages" {
  name   = "${var.env_type}-${var.sys_name}-sg-ec2messages"
  vpc_id = aws_vpc.vpc.id
  tags   = {
    Name = "${var.env_type}-${var.sys_name}-sg-ec2messages"
  }

  # インバウンドルール
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["${var.vpc_address_pre}${var.vpc_address_suf}"]
  }

  # アウトバウンドルール
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

これもシンプルにしています。

iam

iam.tf
# ---------------------------
# IAM
# ---------------------------

# IAM ROLE 定義
resource "aws_iam_role" "ec2_role" {
  name               = "${var.env_type}-${var.sys_name}-iam-role"
  assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}

# IAMポリシー定義
data "aws_iam_policy_document" "ec2_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

# IAM ROLEのインスタンスプロフィールの作成
resource "aws_iam_instance_profile" "instance_prof" {
  name = "${var.env_type}-${var.sys_name}-instance-profile-ssm"
  role = aws_iam_role.ec2_role.name
}

# ---------------------------
# FOR SSM
# ---------------------------
# SSM用ポリシーをEC2ロールに設定
resource "aws_iam_role_policy_attachment" "ssm_control" {
  role       = aws_iam_role.ec2_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

LinuxのEC2のSSMを使うためのiam設定ですね。
あってもなくてもどっちでも良いかな。
LinuxのEC2に何かあたら困るので、念のため付けました。
結局使わなかったのでなくてもよかったです。

ssmのためのvpc endpoint

vpc_endpoint.tf
# ---------------------------
# VPC Endpoint
# ---------------------------

# SSM用 VPC endpointの作成
resource "aws_vpc_endpoint" "interface" {
  for_each            = toset(var.vpc_endpoints)
  vpc_id              = aws_vpc.vpc.id
  service_name        = "com.amazonaws.${var.region}.${each.value}"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = [aws_subnet.sn_public_1a.id]
  private_dns_enabled = true
  security_group_ids  = [aws_security_group.sg_ssm.id]
  tags                = { "Name" = "${var.env_type}-${var.sys_name}-vpc-endpoint-${each.value}" }
}

はい。
これもSSM結局使わなかったのでなくても大丈夫です。

EC2

ec2.tf
# ---------------------------
# EC2作成
# ---------------------------

# Amazon Linux 2023 の最新版AMIを取得
data "aws_ssm_parameter" "al2023-ami-kernel-default-x86_64" {
  name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64"
}

# ---------------------------
# 必要台数のEC2を作成
# ---------------------------

# Front End(Web Server)
# resource "aws_instance" "ec2_app01" {
 resource "aws_spot_instance_request" "ec2_app01" { #spot_priceとspot_typeを設定する
   spot_price                  = "0.0047"
   spot_type                   = "one-time"
   ami                         = data.aws_ssm_parameter.al2023-ami-kernel-default-x86_64.value
   instance_type               = var.ec2_instance_type
   availability_zone           = var.availability_zone.a
   vpc_security_group_ids      = [aws_security_group.sg_ec2_app01.id]
   subnet_id                   = aws_subnet.sn_public_1a.id
   associate_public_ip_address = "true"
   iam_instance_profile        = aws_iam_instance_profile.instance_prof.name
   root_block_device {
     volume_size = 30   # GB
     volume_type = "gp3" # 汎用SSD
     encrypted   = false
     tags        = {
       Snapshot = "false"      
     }
   }
   tags = {
     Name = "${var.env_type}-${var.sys_name}-ec2-app01"
   }
   # NAT Gateway構築後にEC2を構築するパラメーター→Route Table設定後に変更、App01はNAT Gateway構築後でもコケないが、App02と03がコケるため構成変更。(EC2構築前にNAT Gatewayが無いとヒアドキュメント内のdnfコマンドでこける)
   depends_on = [
    aws_route_table_association.associate_rt_sn_public_1a
   ]
 }

# クライアントPC相当のWindows Serverマシンを構築
# ---------------------------
# Windowsマシン用のKey pair作成
# ---------------------------
variable "key_name" {
  default = "kp-ec2-01"
}
variable "key_path" {
  default = "D:\\OneDrive - sh-style.work\\ドキュメント\\03.技術\\16.GitHub\\AWS\\13.dns_route_server"
}

# 秘密鍵のアルゴリズム設定
resource "tls_private_key" "kp-ec2-01" {
  algorithm = "RSA"
  rsa_bits  = 2048
}

# クライアントPCにKey pair(秘密鍵と公開鍵)を作成
# - Windowsの場合はフォルダを"\\"で区切る(エスケープする必要がある)
# - [terraform apply] 実行後はクライアントPCの公開鍵は自動削除される
locals {
  public_key_file  = "${var.key_path}\\${var.key_name}.id_rsa.pub"
  private_key_file = "${var.key_path}\\${var.key_name}.id_rsa"
}

resource "local_file" "kp_ec2_01_pem" {
  filename = "${local.private_key_file}"
  content  = "${tls_private_key.kp-ec2-01.private_key_pem}"
}

# 上記で作成した公開鍵をAWSのKey pairにインポート
resource "aws_key_pair" "kp_ec2_01" {
  key_name   = "${var.key_name}"
  public_key = "${tls_private_key.kp-ec2-01.public_key_openssh}"
}

# ---------------------------
# クライアント相当のEC2を作成
# ---------------------------

#20240523時点のAMI
#Microsoft Windows Server 2022 Base:ami-0f346136f3b372267
#Microsoft Windows Server 2019 Base:ami-01bd28d73d0053a15
#Microsoft Windows Server 2016 Base:ami-063d3d00f8a97a6d1

 #resource "aws_instance" "ec2_client01" {
 resource "aws_spot_instance_request" "ec2_client01" { #spot_priceとspot_typeを設定する
   spot_price                  = "0.14"
   spot_type                   = "one-time"
   ami                         = "ami-0f346136f3b372267" #Microsoft Windows Server 2022 Base
   instance_type               = "m4.large"
   availability_zone           = var.availability_zone.a
   vpc_security_group_ids      = [aws_security_group.sg_ec2_client01.id]
   subnet_id                   = aws_subnet.sn_public_1a.id
   associate_public_ip_address = "true"
   key_name                    = "${var.key_name}"
   iam_instance_profile        = aws_iam_instance_profile.instance_prof.name
   root_block_device {
     volume_size = 100   # GB
     volume_type = "gp3" # 汎用SSD
     encrypted   = false
     tags        = {
       Snapshot = "false"      
     }
   }
   tags = {
     Name = "${var.env_type}-${var.sys_name}-ec2-client01"
   }
 }

よく見たらLinux思いっきりヒアドキュメント残ってたんで消しました。

はい。
これで完成です。

同じVPC内、同一サブネット内にLinuxのEC2とWindowsのEC2を構築しました。

Terraform実行結果

image.png
まぁ問題起きるわけないですよね。
(最後Windows EC2のグローバルIPアドレスが出力されてませんが、AWSコンソールで確認できるので良いかな・・・)

確認作業

Windows EC2からnslookup -type=ns [Linux EC2の暗黙的に割り振られるFQDN]を実行してみます。
FQDNは
image.png
赤枠内の通りip-10-0-0-13.ap-south-1.compute.internalです。

実行結果

image.png
image.png

10.0.0.2がnslookupを実行した問い合わせ先DNSサーバですね。
1枚目の画像の赤枠内、primary name serverが権威サーバだと思うので、これを2枚目の画像の通り更にnslookupで引っ張てみたところ172.16.0.23と返ってきました。

結論

AWSで暗黙的に構築されるDNSサーバは権威サーバではない!
ということがわかりました。

調べ方があってるか不安だ・・・

あ、日付が変わってる。

本日はこれまで。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1