Amazon CloudFrontがIPv6に対応予定なのでウォッチするページを作ってみた

2016.10.13

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。 先日CloudFrontでアップデートがあり、IPv6対応がアナウンスされました。実際にIPv6アドレスが有効になるのは数週間程度かかるとのことなので、その状況をウォッチするページを作ってみました。

CloudFrontの設定

まずは、CloudFrontでIPv6を有効にする設定を確認しておきます。新規で作成するWeb Distributionでは、既定でIPv6が有効になります。既存Distributionでは、[Distribution Settings]の[General]タブに[Enable IPv6]という設定があるので、このチェックをオンにしましょう。

cloudfront-ipv601

Route 53のエイリアスレコードをCloudFrontに設定している場合は、IPv6ホスト名に対応するAAAAレコードでエイリアスを追加します。

cloudfront-ipv602

これでOKです。

ウォッチページのアーキテクチャ

IPv6を有効にしても、日本からは本日時点でAAAAレコードは無いとエラーが返ってきます(takipone.comにはAレコードとAAAAレコードの両方にCloudFrontのエイリアスを設定済み)。

$ host takipone.com
takipone.com has address 54.192.234.164
takipone.com has address 54.192.234.80
takipone.com has address 54.192.234.71
takipone.com has address 54.192.234.216
takipone.com has address 54.192.234.197
takipone.com has address 54.192.234.76
takipone.com has address 54.192.234.213
takipone.com has address 54.192.234.167
takipone.com mail is handled by 10 inbound-smtp.us-west-2.amazonaws.com.
$ host -t aaaa takipone.com
takipone.com has no AAAA record
$

AWS側でIPv6が有効化されるとこのAAAAレコードのレスポンスが返ってくるであろう、ということでAWS Lambdaが利用できるAWSの全リージョンで1時間に1回AAAAレコードのDNS問い合わせを行い、その結果をS3にアップするLambdaを配置し、それを確認できるWebページを作りました。

cloudfront-ipv603

Not yetは、上記のレコードなしの場合の表示です。IPv6アドレスが返ってくるとDeployedと表示するようになっています。アーキテクチャを図にすると以下のような感じです。

cloudfront-ipv604

Lambdaはipv6deployedtoyouredgelocation.comのAAAAレコードを問い合わせ、レスポンスによって文字列を場合分けし、それをS3バケットipv6deployedtoyouredgelocation.comにJSONファイルとしてアップロードします。コードは以下の通りです。

var AWS = require('aws-sdk');
var dns = require('dns');
var domain = 'ipv6deployedtoyouredgelocation.com';

exports.handler = function(event, context, callback) {
	var result = {};

	// query dns AAAA record
	dns.resolve6(domain, (err, addresses) => {
		var date = new Date();

		if (err && err.code == 'ENODATA') {
			result.status = 'Not yet';
			result.timestamp = date;
		} else if (err) {
			result.status = 'Error';
			result.timestamp = date;
		} else {
			result.status = 'Deployed';
			result.addresses = addresses;
			result.timestamp = date;
		}

		var s3 = new AWS.S3();

		var index = {
			current_status: result.status,
			history_files: [],
			timestamp: date
		};

		var region = context.invokedFunctionArn.split(':')[3]
		var history_filename = 'data/' + region + '/' + date.getTime() + '.json';

		var params = {Bucket: domain, Key: 'data/' + region + '/index.json'};
		s3.getObject(params, function(err, data) {
			if (err && err.statusCode == 404) {
				// when first execution
				console.log('index file creating...');
				index.history_files = [history_filename];
			} else if (err) {
				console.error(err);
			} else {
				// add log
				current_index = JSON.parse(data.Body.toString());
				index.history_files = current_index.history_files.concat([history_filename]);
			}

			params = {
			    Bucket: domain, 
			    Key: history_filename, 
			    Body: JSON.stringify(result), 
			    ACL:'public-read',
			    ContentType: 'application/json'
			};
			s3.putObject(params, function(err, result) {
			    if(err) console.error(err);
				else    console.log(history_filename + " uploaded.");
			});
			params = {
			    Bucket: domain, 
			    Key: 'data/' + region + '/index.json', 
			    Body: JSON.stringify(index), 
			    ACL:'public-read',
			    ContentType: 'application/json'
			};
			s3.putObject(params, function(err, result) {
				if(err) console.error(err);
				else    console.log("index file uploaded.");
			});

			console.log(index);
		});
	});
	callback(null, "");
}

アップロードされたJSONファイルを同じS3バケットに配置したHTMLファイルからAjaxで読み込み、上記のような結果を表示しています *1

まとめ

CloudFrontのIPv6対応と、その状況を確認するWebページのご紹介でした。こちらの記事でも触れているAWSのIPv6対応が、また一歩進みましたね。

コードと英語がかなり適当なので、添削歓迎です!なお、ヒストリーが一覧できるように鋭意開発中です。IPv6が有効化されるまでになんとかしなければ。。。

脚注

  1. ちなみに、Webページ自体をCloudFrontでキャッシュし、ACMの証明書を用意してHTTP/2でホストするイマドキな構成です。