2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EC2のWebサーバーのIPアドレスを固定せず、起動時にRoute53のレコードを自動更新(自作DDNS?)

Last updated at Posted at 2024-04-20

2024.6.2 IMDSV2(インスタンスメタデータV2)の利用パターンを追加

作業の経緯

実験用のAWSのEC2上のWebサーバーでhttpsを有効化するため、固定IPアドレス(Elastic IP)を使用しています。
サーバーは使用する時だけ起動してコスト削減を図っているのですが、ElasticIPはずっと課金されてしまうため、これを節約したいというのが今回の経緯です。

この記事で使用したEC2インスタンスはかなり古いモノですので、メタデータのバージョンがIMDSv1です。
IMDSv2の場合のスクリプトを追加しました。

IMDSv1は現在非推奨となっており、今年中には新しいインスタンスでIMDSv2が強制されるようになるはずですが、IMDSv2ではパブリックIPアドレスの取得方法が変わっています。
この手順は今後確かめて、改めて掲載しようと思います。

作業前の状態

  • EC2インスタンスでWebサーバーを構築
  • ElasticIPを確保して上記インスタンスに割り当て
  • お名前.comで独自ドメインを取得してRoute53サービスに権限を移譲
  • Route53のホストゾーンにサーバー名を登録
  • Let's Encryptで上記サーバー名の証明書を作成

作業後のイメージ

  • ElasticIPを解放してサーバーのIPアドレスを動的割り当てとする
  • サーバー起動時にパブリックIPアドレスを取得する
  • 取得したパブリックIPアドレスでRoute53のレコードを自動更新する

作業手順

パブリックIPアドレスの取得

EC3インスタンス上でパブリックIPアドレスを取得するには、以下のURLでメタデータを取得します。
このIPアドレスはメタデータを取得するために特別に割り当てられているようです。

【IMDSv1の場合】

curl -H "Metadata-Flavor: AWS-V2" http://169.254.169.254/latest/meta-data/public-ipv4

【IMDSv2の場合】
IMDSv2では、最初にPUTリクエストで一時トークンを生成、トークンを渡してメタデータを取得します。

(一時トークン)
curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds:300" http://169.254.169.254/latest/api/token
(結果例)
AQAAAP3MH9PAkcyqtZmB_S_q9n5Ah9eX8YawSmzb0n8L5UcKHpLJLQ==
(メタデータ取得)
curl -X GET -H "X-aws-ec2-metadata-token:AQAAAP3MH9PAkcyqtZmB_S_q9n5Ah9eX8YawSmzb0n8L5UcKHpLJLQ==" http://169.254.169.254/latest/meta-data/public-ipv4

レコード更新のための権限付与

IAMポリシーの作成

Route53のレコードを更新するためのIAMポリシーを作成する必要があります。

  • IAMサービスを開く
  • [アクセス管理]-[ポリシー]を開く
  • [ポリシーの作成]を選択
  • サービスの選択でRoute53を選ぶ
  • アクションの選択でChangeResourceRecordSetsを選ぶ
  • リソースARNにarn:aws:route53:::hostedzone/[ホストゾーンID]を選ぶ(ホストゾーンIDはRoute53サービスで自分のゾーンを選ぶと表示されている)
  • ポリシー名を付けて保存
IAMポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "route53:ChangeResourceRecordSets",
            "Resource": "arn:aws:route53:::hostedzone/<ホストゾーンID>"
        }
    ]
}

IAMロールの作成

EC2にポリシーを割り当てるためにIAMロールを作成します。

  • IAMサービスを開く
  • [アクセス管理]-[ロール]を開く
  • [ロールの作成]を選択
  • 信頼されたエンティティタイプで[AWSサービス]を選択
  • ユースケースで[EC2]を選ぶ
  • 許可ポリシーとして、前項で作成したポリシーを選択する
  • ロール名を付けて保存

EC2インスタンスへの割り当て

  • EC2サービスを開く
  • Webサーバーのインスタンスを選択
  • [アクション]-[セキュリティ]-[IAMロールの変更]を選択
  • 前項で作成したIAMロールを選択する

※もともとEC2にIAMロールを割り当てている場合は、そのロールに前述の手順で作成したポリシーを割り当てるか、新しいIAMロールに必要なポリシーを割り当てる必要があります。

Route53のレコード更新

AWS-CLIのインストール

Route53のレコードを更新するには、AWS-CLIコマンドを使用します。
私が使っているUbuntuのAMIにはデフォルトでAWS-CLIが入っていないのでインストールします。

sudo apt install aws

Route53レコード更新

AWS-CLIのコマンドは以下のような感じです。

aws route53 change-resource-record-sets --hosted-zone-id <Route53のゾーンID> --change-batch {"Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "<サーバーのFQDN>",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": "<パブリックIPv4アドレス>"
          }
        ]
      }
    }
  ]
}

自動更新のスクリプト作成

レコードの更新を自動化するため、スクリプトを作成します。

【IMDSv1の場合】

update.sh
#!/bin/bash

PUBIP=`curl -H "Metadata-Flavor: AWS-V2" http://169.254.169.254/latest/meta-data/public-ipv4`

ZONEID=${1:-"<ホストゾーンID>"}

JSON="{\"Changes\": [
    {
      \"Action\": \"UPSERT\",
      \"ResourceRecordSet\": {
        \"Name\": \"<サーバーのFQDN>\",
        \"Type\": \"A\",
        \"TTL\": 300,
        \"ResourceRecords\": [
          {
            \"Value\": \"$PUBIP\"
          }
        ]
      }
    }
  ]
}"

【IMDSv2の場合】

#!/bin/bash

# Route 53のホストゾーンID
ZONEID=${1:-"ZZZZAAAABBBBB11111"}
# サーバーのFQDN
FQDN=www.example.com

# パブリックIPv4アドレスを取得する
TOKEN=`curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds:300" http://169.254.169.254/latest/api/token`
PUBIP=`curl -X GET -H "X-aws-ec2-metadata-token:${TOKEN}" http://169.254.169.254/latest/meta-data/public-ipv4`

echo $PUBIP

# Route53のレコードを更新するためのJSON
JSON="{\"Changes\": [
    {
      \"Action\": \"UPSERT\",
      \"ResourceRecordSet\": {
        \"Name\": \"${FQDN}\",
        \"Type\": \"A\",
        \"TTL\": 300,
        \"ResourceRecords\": [
          {
            \"Value\": \"$PUBIP\"
          }
        ]
      }
    }
  ]
}"

# aws-cliコマンドによりRoute53のレコードを更新する
aws route53 change-resource-record-sets --hosted-zone-id $ZONEID --change-batch  "$JSON"

このシェルスクリプトを実行すると、EC2インスタンスのパブリックIPアドレスをホストゾーンのサーバー名のAレコードに登録します。

chmod +x update.sh
./update.sh <ホストゾーンID>

サービス登録

サーバー起動時にシェルを自動実行するため、サービス定義を作成して登録します。

/etc/systemd/system/dns-update.service
[Unit]
Description=Update Route53 Record to my address.
After=network.target

[Service]
Type=simple
User=root
ExecStart=/home/ubuntu/update.sh

[Install]
WantedBy=multi-user.target
sudo systemctl enable dns-update

以上で、サーバー起動時にパブリックIPアドレスを取得して更新します。

補足

EC2のインスタンス生成時にAmazon Linux 2023を使用すると、デフォルトでIMDSv2のみが有効になっており、IMDSv1は利用できません。
古いAMI(Amazon Linux 2など)を利用している場合は両方が有効になっていますが、セキュリティを向上するためにIMDSv1を無効化することが推奨されています。

EC2インスタンスのIMDSをv2のみに制限する

  • インスタンス一覧でインスタンスを選択し、「アクション」-「インスタンスの設定」-「インスタンスメタデータオプションの変更」を選択する

スクリーンショット 2024-06-02 17.29.20.png

  • 「IMDSv2」の欄を[Optional]から[必須]に変更する

スクリーンショット 2024-06-02 17.37.23.png

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?