Skip to content

DNSControl

本記事は『さくらインターネット Advent Calendar 2024』16日目の記事になります。

DNS as Codeの実装の1つであるDNSControlについて紹介します。DNS as Codeについては下記記事をご覧ください。

DNSControlとは

DNSControlはStack Exchange社が開発・保守しているDNSゾーンの保守ツールです。Stack Exchange社はStack Overflow(開発者向けのQ&Aサイト)やServer Fault(システム・ネットワーク管理者向けのQ&Aサイト)の運営元として知られています。

公式サイトは次の場所です。

DNSControlの背景や経緯は以下のとおりです。

DNSControlが行うことは設定ファイルに記述されたゾーンデータをAPIでDNSプロバイダーに反映させることです。

DNSControlの概要

複数のDNSプロバイダーにも反映できます。

複数のDNSプロバイダー

対応しているマネージドDNSサービスプロバイダーは『Providers』に記載されています。日本国内のサービスプロバイダーとしてはさくらのクラウドに対応しています。

注記)さくらのクラウド対応は筆者が個人的にコミュニティーサポートとしてコントリビュートしたものです。

対応しているその他のDNSプロバイダーとしては以下のものがあります。

プロバイダー説明
AXFR+DDNSゾーンの取得にゾーン転送を、更新にDynamic Updateを利用
BINDマスターファイルを更新
DNS-over-HTTPSNSレコードが正しいか確認するだけの機能
Microsoft DNS Server on Microsoft Windows Server
PowerDNS

設定

ここからはDNSプロバイダーとしてさくらのクラウド DNSを利用した例と共に設定方法を紹介します。

DNSControlの設定ファイルには次の2つがあります。

  • creds.json:DNSプロバイダー設定(認証情報含む)
  • dnsconfig.js:ゾーン設定

DNSプロバイダー設定(認証情報含む)

creds.jsonの例を示します。

{
"sakuracloud": {
"TYPE": "SAKURACLOUD",
"access_token": "$SAKURACLOUD_ACCESS_TOKEN",
"access_token_secret": "$SAKURACLOUD_ACCESS_TOKEN_SECRET"
}
}

ここでのsakuracloudはDNSプロバイダーを指定する任意の名前で、TYPEはDNSプロバイダーのタイプ識別子です。ここではさくらのクラウドを示すSAKUACLOUDを指定しています。他のパラメーターは認証情報やAPIに関連するもので、DNSプロバイダーにより異なります。なお、指定する値としては$で始まる文字列を記述すると環境変数として認識します。

ゾーン設定(レジストラー、DNSプロバイダー指定)

dnsconfig.jsの例を示します。

var REG_NONE = NewRegistrar("none");
var DSP_SAKURACLOUD = NewDnsProvider("sakuracloud");

ゾーンの設定はJavaScriptの記法で行います。マクロとして利用できる関数や修飾子が用意されています。この例ではNewRegistrar()にはレジストラーを指定します。なければ、noneを指定します。NewDnsProvider()にはcreds.jsonに記述したDNSプロバイダーを指定します。

ゾーン設定(ゾーンデータ)

dnsconfig.jsの例の続きです。

D("dnsbeer.com", REG_NONE, DnsProvider(DSP_SAKURACLOUD),
DefaultTTL(3600),
HTTPS("@", 1, "pale-ale.dnsbeer.com.", ""),
A("pale-ale", "192.0.2.1"),
END);

ゾーンは関数D()の引数として記述し、引数はENDで終わります。引数として、ゾーン名(“.”で終わらない)、レジストラー、DNSプロバイダーを指定します。これ以降の引数にはリソースレコードタイプごとの修飾子を使ってリソースレコードを記述します。リソースレコードタイプによってはRDATAをそのまま記述するのではなく、要素ごとに記述します。

DNSControlによるDNSプロバイダーへの反映の実行例

実行例からどういうことができるかを確認します。

変更前の状態

さくらのクラウドのコントロールパネルのDNSアプライアンスに登録したゾーンに次のリソースレコードが登録されているとします。

設定内容

次の内容のdnsconfig.jsファイルを用意します。

var REG_NONE = NewRegistrar("none");
var DSP_SAKURACLOUD = NewDnsProvider("sakuracloud");
D("dnsbeer.com", REG_NONE, DnsProvider(DSP_SAKURACLOUD),
DefaultTTL(3600),
HTTPS("@", 1, "pale-ale.dnsbeer.com.", ""),
A("pale-ale", "192.0.2.1"),
END);

元のゾーンの状態に対して次の変更を行います。

  • HTTPSレコードの追加
  • pilsnerのAレコードの削除
  • TTLをデフォルト値に変更

プレビュー

次のコマンドを実行してプレビューを行います。

Terminal window
dnscontrol preview

出力結果は次のようになりました。

dnscontrol preview

プレビューでは作成、更新、削除されるリソースレコードが出力されます。さらに、構文チェックやMX/CNAMEの絶対ドメイン名チェックも行われます。

DNSプロバイダーへの反映

次のコマンドを実行して、dnsconfig.jsに記述した内容をDNSプロバイダーのゾーンに反映させます。

Terminal window
dnscontrol push

出力結果は次のようになりました。

dnscontrol push

このとき、作成、更新、削除されるリソースレコードが表示され、DNSプロバイダーに反映されます。

反映したことの確認

次のようにDNSプロバイダーに反映されたことを確認できます。

ゾーンデータの取得(マスターファイル形式)

次のコマンドを実行すると、DNSプロバイダーに登録されているゾーンデータをマスターファイル形式で取得できます。

Terminal window
dnscontrol get-zones --format=zone DNSプロバイダー - ゾーン

出力結果は次のようになりました。

dnscontrol get-zones

ゾーンデータの取得(DNSControlの形式)

次のコマンドを実行すると、DNSプロバイダーに登録されているゾーンデータをdnsconfig.jsの形式で取得できます。

Terminal window
dnscontrol get-zones --format=js DNSプロバイダー - ゾーン

出力結果は次のようになりました。

dnscontrol get-zonews

DNSControlの新規利用開始時にこのコマンドを使うとよいです。

JavaScript DSL

JavaScriptのDSLであるため、変数や演算やマクロ関数が利用できます。

公式サイトの例から引用します。

var addrA = IP("1.2.3.4")
var DSP_R53 = NewDnsProvider("route53_user1");
D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_R53),
A("@", addrA), // 1.2.3.4
A("www", addrA + 1), // 1.2.3.5
END);

この他にも便利なマクロ関数が多く用意されています。

プロバイダーの開発

DNSControlではプロバイダーを開発するためのドキュメントが用意されています。

そのため、APIが利用できるDNSプロバイダーであればDNSControlのプロバイダーを開発できます。

実際に筆者はさくらのクラウドに対応するプロバイダーを開発しました。 次のPull Requestは筆者が作成したものです。

注意点

最後に注意点を紹介します。

リソースレコードタイプに関する補足

リソースレコードタイプに関して以下の補足があります。

  • SOA:ほとんどの場合はDNSプロバイダー側で管理しているため、記述不要
  • NS:変更できないDNSプロバイダーの場合は記述不要
  • ALIAS:疑似リソースレコードタイプはDNSプロバイダーが対応していれば利用できる
  • TXT:SPFやDMARCを利用するときにはSPF_BUILDER()DMARC_BUILDER()を利用できる
  • CAA:CAA_BUILDER()を利用できる

ここでSPF_BUILDER()はSPF用のTXTレコードを生成してくれます。10 DNS lookupsのチェックもあるため、便利です。公式サイトの例から抜粋します。

SPF_BUILDER({
label: "@",
parts: [
"v=spf1",
"ip4:198.252.206.0/24", // ny-mail*
"ip4:192.111.0.0/24", // co-mail*
"include:_spf.google.com", // GSuite
"~all"
]
}),

フォーマッターに関する注意点

PrettierやBiomeなどのフォーマッターを利用していると次のように整形されることがあります。 DNSControlにおいては最後の引数の末尾のカンマは許容されないので、Trailing Commasの設定をes5にします。

D(
"example.com",
REG_MY_PROVIDER,
DnsProvider(DSP_MY_PROVIDER),
A("@", "192.0.2.1"),
A("foo", "192.0.2.2"),
END, ←このカンマは許容されない
);

Prettier (.prettier)の設定例を示します。

{
"trailingComma": "es5"
}

Biome (biome.json)の設定例を示します。

{
"javascript": {
"formatter": { "trailingCommas": "es5" }
}
}