AWS でサーバーレスダイナミック DNS システムを構築する

このコンテンツはいかがでしたか?

この記事はもともと 2015 年 12 月に公開されました。このソリューションは、その費用対効果と効率を高めるために 2023 年 7 月に更新されました。この記事は更新され、Amazon API GatewayAWS Lambda 関数 URL に、Amazon Simple Storage Service (Amazon S3)Amazon DynamoDB に置き換わりました。Lambda 関数 URL を利用すると、ソリューションの全体的なコストが削減されます。この機能は、Lambda サービスを利用する場合に追加料金なしで使用でき、クライアントがインタラクションする RESTful HTTPs エンドポイントを提供します。Amazon S3 を DynamoDB に置き換えることで、ソリューションの効率が高まるとともに、データのクエリ時の全体的なレイテンシーが低減します。

アーリーステージのスタートアップ、小規模な企業、ホームネットワークでは、多くの場合、予告なく変更される可能性のある動的パブリック IP アドレスを使用しています。このようなアドレスの変更があることで、高い信頼性をもって外部からこれらのネットワーク上のシステムにアクセスすることができません。ライフサイクルのアーリーステージにあるスタートアップにとって、最初期の顧客群からの信頼を得るには、信頼性と可用性の高いサービスを提供することが重要です。

ダイナミック DNS システムは、ネットワーク内でソフトウェアエージェントを実行し、最新のパブリック IP アドレスを使用して DNS レコードを更新し続けることによって、この問題を解決します。DNS レコードが最新である限り、ネットワークを見つけることができ、顧客は高い信頼性をもってサービスにアクセスできます。

この記事では、サーバーレス AWS サービスを利用して独自のダイナミック DNS システムを構築する方法について説明します。Amazon Web Services (AWS) のサービスと数行のコードのみを使用したサーバーレスシステムの構築は、シンプルでコスト効率が高く、スケーラブルであり、基盤となるインフラストラクチャのスケールやメンテナンスについて心配することなく、スタートアップであるお客様の中核的なビジネスロジックに注力することを可能にします。

ダイナミック DNS システムで利用する AWS サービス

次のセクションでは、次の AWS サービスを利用してダイナミック DNS ソリューションを構築する方法を示します。

  • AWS Lambda サービスを利用すると、基盤となるサーバーを管理することなく、コードを実行できます。コードはいつでも実行できる状態にありますが、お支払いいただくのは 1 ミリ秒単位で課金される関数の呼び出しごとの料金のみです。Lambda サービスは、AWS SDK を通じて他の AWS サービスとインタラクションできます。
  • Lambda 関数 URL は、Lambda 関数専用の HTTPS エンドポイントを提供します。これにより、AWS SDK を使用したり、追加のプロキシサービスを介して関数を呼び出したりすることなく、クライアントアプリケーションから関数を直接呼び出すことができます。この機能は、Lambda サービスに対する追加コストなしで使用可能です。
  • Amazon Route 53 は、DNS サーバーのグローバルネットワークからドメインと DNS ゾーンを登録してホストできるマネージド DNS サービスです。すべての AWS サービスと同様に、Route 53 は API を通じて管理できます。
  • DynamoDB は、フルマネージドかつサーバーレスの Key-Value NoSQL データベースで、あらゆる規模で高性能アプリケーションを実行できるように設計されています。DynamoDB は、組み込みのセキュリティ、継続的なバックアップ、自動マルチリージョンレプリケーション、インメモリキャッシュ、データのインポートおよびエクスポートツールを提供します。

ダイナミック DNS システムの論理的なフロー

図 1 は、クライアントが Lambda 関数と、そのアタッチされた関数 URL を利用して構築されたサービスに対して API リクエストを実行することで、自身の IP アドレスを見つける方法を示しています。

図 2 に示すように、クライアントはパブリック IP を認識したので、DNS レコードを設定するために、別のリクエストをサービスに送信します。Lambda 関数は、まず DynamoDB テーブルに保存されているレコードを参照して、リクエストを検証します。チェックに合格すると、Lambda 関数は API 呼び出しを介して Route 53 で DNS エントリを設定します。これで、ネットワークの現在の IP はパブリック DNS に存在しており、標準の DNS クエリで見つけることができるようになりました。

Lambda と Route 53 を利用したダイナミック DNS の利点

サーバーレスダイナミック DNS システムを実行することで得られる利点をいくつか示します。

  • 簡単な設定。すべてのコード、設定、およびこれを自分の AWS アカウントで設定するための手順を含むサンプルクライアントを使用できます。
  • クライアント側での作業がほとんど、またはまったく不要。 3 つのコマンドで API を更新できます。独自のクライアントをほとんどの言語で作成し、Windows、Linux、macOS、Raspberry Pi、Chrome OS、DD-WRT/Tomato USB ルーターファームウェアなどのプラットフォームで実行できます。
  • 任意の数のクライアント、ホスト名、ドメインのサポート。Route 53 サービスの制限とクォータは、「Route 53 デベロッパーガイド」の「クォータ」セクションで確認できます。
  • 高い費用対効果 – 1~2 USD/月Route 53 ゾーンのコストはそれぞれ 0.50 USD/月、1,000,000 件の DNS クエリのコストは 0.40 USD、DNS 更新のための 10,000 件の Lambda 関数リクエストのコストは 0.01 USD 未満です。
  • サーバーレスアーキテクチャ。サーバーレステクノロジーは、自動スケーリング、組み込みの高可用性、従量制料金の請求モデルを特徴としており、俊敏性を高め、コストを最適化します。
  • 詳細な許可により、認可されたクライアントのみが自身のホスト名を更新できます。クライアントは、DNS に追加されているアドレスからのみシステムを更新できます。
  • 現在の DNS 設定に対して必要な変更が軽微。現在の DNS プロバイダーのプライマリ .com ゾーンをそのままにして、AWS でセカンダリ dynamic.example.com ゾーンゾーンを使用できます。Route 53 でのホストゾーンの作成の詳細については、「Route 53 デベロッパーガイド」の「パブリックホストゾーンの作成を参照してください。

前提条件

このソリューションを構築するには、次の 2 つが必要です。

  1. AWS アカウント新規アカウントは、AWS 無料利用枠の対象となります。
  2. Route 53 または別のプロバイダーでホストされている、所有するドメイン。必要に応じて、わずか 3.00 USD から、Route 53 を通じてドメインを登録できます。詳細な料金体系については、「Amazon Route 53 Pricing for Domain Registration」を参照してください。

アカウントでダイナミック DNS システムを構築する方法

ここまでで、システムの独自コピーの構築を開始するための情報はすべてお伝えしました。仕組みの詳細を知りたい場合は、続きをお読みください。

構築を開始したい場合、Lambda を利用した Route 53 ダイナミック DNS を GitHub で入手できます。図解付きの手順と、必要なすべてのコードと設定が提供されます。

新しいシステムの仕組み

まず、クライアントはネットワークに割り当てられているパブリック IP を見つける必要があります。ネットワークからインターネット上のサービスに対してリクエストを実行すると、そのサービスは外部 IP アドレスからのリクエストを認識します。

その後、クライアントは、リクエスト本文が {"execution_mode":"get"} である Lambda 関数 URL に対して HTTP POST リクエストを実行し、現在のパブリック IP アドレスを含む応答を取得します:

HTTP POST
> https://.....lambda-url.eu-west-1.on.aws

{“return_message”:
“176.32.100.36”, “return_status”: “success”}

このプロセス中、Lambda 関数 URL は、すべてのリクエストパラメータを含む HTTP リクエストを JSON に変換し、リクエスタのソース IP アドレスを Python Lambda 関数に渡します。その後、Lambda 関数は IP を含む JSON 応答をクライアントに送り返します。

図 3 は、パブリック IP を取得するリクエストを示しています。

クライアントは、HTTP POST リクエストから返されたパブリック IP アドレス、DNS ホスト名、共有シークレットをリンクすることでリクエストトークンを構築します。例えば、IP アドレスが 176.32.100.36、ホスト名が host1.dyn.example.com、共有シークレットが shared_secret_1 である場合、リンクされた文字列は次のようになります:

176.32.100.36host1.dyn.example.comshared_secret_1

次に、クライアントは文字列から SHA-256 ハッシュ関数を生成します:

echo -n 176.32.100.36host1.dyn.example.comshared_secret_1 | shasum -a 256

ハッシュ: 96772404892f24ada64bbc4b92a0949b25ccc703270b1f6a51602a1059815535

その後、クライアントは 2 件目の HTTP POST リクエストを実行して DNS 更新をリクエストします。リクエスト本文内のプレーンテキストのホスト名をキーとして渡し、ハッシュ関数を認証トークンとして渡します:

HTTP POST > https://....lambda-url.eu-west-1.on.aws

{“execution_mode”:”set”, “ddns_hostname”:”host1.dyn.example.com”, “validation_hash”:”96772404892f24ada64bbc4b92a0949b25ccc703270b1f6a51602a1059815535”}

その後、Lambda 関数 URL はリクエストパラメータを Lambda 関数に返します。

その後、Lambda 関数は、AWS SDK for Python (Boto3) を使用して、DynamoDB から JSON 設定レコードをクエリします。このシステムでは、Lambda サービス、DynamoDB、Route 53 の間のインタラクションには、Lambda サービスのランタイム環境に事前に組み込まれている Boto3 が使用されます。

Lambda 関数が DynamoDB から設定レコードをクエリすると、次のレコード例のように、ホスト名をキーとして使用して、共有シークレットと、そのレコードに関連付けられた他の設定を見つけます。

{
"host1.dyn.example.com.": {
"aws_region": "us-west-2",
"route_53_zone_id": "MY_ZONE_ID",
"route_53_record_ttl": 60,
"route_53_record_type": "A",
"shared_secret": "SHARED_SECRET_1"
},
"host2.dyn.example.com.": {.....

クライアントはキーとして host1.dyn.example.com を渡したので、Lambda 関数は SHARED_SECRET_1 を設定から読み取り、ホスト名、リクエスタの IP アドレス、共有シークレットを使用してハッシュ関数トークンを再構築します。Lambda 関数によって計算されたハッシュ関数と、クライアントから受信したハッシュ関数が一致する場合、リクエストは有効とみなされます。

リクエストが検証されると、Lambda 関数は設定の情報を使用して Route 53 に対して API コールを実行し、DNS ホスト名が既にクライアント IP で設定されているかどうかを確認します。変更が必要ない場合、Lambda 関数はクライアントに応答して終了します:

{“return_message”: “Your IP address matches the current Route53 DNS record.”,
 “return_status”: “success”}

レコードがない場合、または現在のレコードとクライアント IP が一致しない場合、Lambda 関数は Route 53 に対して API コールを実行してレコードを設定し、クライアントに応答して終了します:

{“return_message”: “Your hostname record host1.dyn.example.com. has been set to 176.32.100.36”,
 “return_status”: “success”}

図 4 は、ホスト名を設定するリクエストを示しています。

このシステムはどのように保護されるのでしょうか?

  • Lambda 関数 URL を使用するすべての通信は暗号化されます。
  • 共有シークレットがインターネット上に送信されることはありません。
  • クライアントのリクエストレートは、Lambda サービスの予約された同時実行機能を使用してスロットリングできます。
  • クライアントは共有シークレット (「クライアントが持っているもの」) と自身のパブリック IP アドレス (「クライアント自体」) を提示するため、認証メカニズムは多要素です。
  • 設定ファイルは、DynamoDB のサーバー側の暗号化を介して保管中に暗号化できます。
  • AWS の認証情報は使用されないため、漏えいすることはありません。

まとめ

この記事で説明したダイナミック DNS システムは、AWS 上で独自のサーバーレスソリューションを作成して現実の問題を解決する方法を示しています。DNS は変わりやすいため、ユーザーは気付かない可能性があります。

このソリューションを利用すると、AWS で独自のダイナミック DNS を実行できます。あるいは、これを例として使用して、AWS サービスを利用して任意の規模で独自のサーバーレスソリューションを作成する方法を学習できます。

コード、設定、デプロイ方法の手順の完全なセットについては、GitHub の Lambda を利用した Route 53 ダイナミック DNS リポジトリにアクセスしてください。

このコンテンツはいかがでしたか?