ほりひログ

所属組織の製品 (Azure とか) に関連する内容が多めだけど、個人の見解であって、所属組織を代表する公式情報ではないです。

Azure Virtual Network には DNS フォワーダーがあった方がいい

ドキュメントにも書かれているので、知っている人は当然のように知っていることかもしれないですが、自分は最近知ったのでメモがてらに。

docs.microsoft.com

DNS フォワーダー?

DNS リクエストを受け付けて、受け付けた DNS のリクエストを上位の DNS サーバーに転送(フォワード)してくれるものです。

なぜあるといいの?

VNET 内の プライベート IP アドレスの名前解決に Azure Private DNS Zone でレコード管理するのが楽なんですが、この Azure Private DNS Zone が使えるのは、VNET 内のリソースからの名前解決リクエストに限られます (ということを、最近知った次第)。
つまりオンプレから ExpressRoute で接続、または、ローカル PC から直接 P2S VPN で VNET に接続した時、VNET に接続した端末からの名前解決に Azure Private DNS Zone を使うことができません。

この制限を回避するために、一旦 VNET 内の DNS フォワーダーでリクエストを受けて、そのリクエストを DNS フォワーダーから Azure DNS へ転送する、という形を取る、というのが冒頭のドキュメントに書いてあることです。
そうすることで、VNET 内のリソースからのリクエスト、という形になるので、ExpressRoute/VPN 経由のリクエストでも Azure Private DNS Zone が使えるようになります。

DNS フォワーダー用コンテナー

というわけで、お手軽に VNET 内に DNS フォワーダーを立てられるよう、専用コンテナー イメージを作りました。
VNET 内の Azure Container Instances (ACI) で動作確認済みです。

github.com

dnsmasqDNS クエリーをフォワードするだけの、チョーシンプルな distroless ベースの Docker コンテナー イメージです。

ついでに勉強がてら、v~~~ という tag で Release を作るたびに、GitHub Container Registry に push する GitHub Actions を書いてみました。
これh便利。

使い方

Docker コンテナーなので多分 VM とかでも動くんでしょうが、上に書いたとおり、Azure VNET の中の ACI で動かすために作ったので、ACI での使い方を。

まずは ACI をデプロイするところから。

  1. イメージ名に ghcr.io/horihiro/simple-dns-forwarder:<tagName> と入れてください。
    <tagName>latestv0.0.1-alpha1 です (2021/10/02 現在) 。
    https://user-images.githubusercontent.com/4566555/135413167-94e03e07-18f8-4ec6-8391-eafc33442000.png
    特に意味はないけど、GitHub の Container Registry にしてみました。
    github.com
  2. Networking Type を Private にして、配置先の VNET とサブネットを指定してください。
    DNS なので、ポートは 53UDP になります。
    https://user-images.githubusercontent.com/4566555/135404958-d4f3eff2-a4bd-4728-8a6b-b3a9d88058ce.png
  3. 起動コマンドには、
     
    ["dnsmasq", "--no-daemon", "--server", "168.63.129.16"]
     
    と入れてください。 https://user-images.githubusercontent.com/4566555/135405110-d4bae919-94d1-4f11-b9c9-cfe172fbfbb9.png
    最後に指定した IP アドレスが、DNS クエリーのフォワード先です。
    168.63.129.16 は Azure で使われる DNS サーバー用 IP アドレスです。詳しくはこちら。
    docs.microsoft.com
  4. デプロイが完了したら、ACI の [概要] ブレードからプライベート IP アドレスを確認して控えておいてください。この後使います。
    https://user-images.githubusercontent.com/4566555/135694859-6de8ccc5-bc38-4965-99a0-d6e590d8e4e4.png
  5. ACI をデプロイした VNET の DNS サーバー設定で、上で控えたプライベート IP アドレスを設定してください。
    https://user-images.githubusercontent.com/4566555/135694798-b96aa88c-aa2d-483a-b3bd-cdcb4b80559c.png

以下、余談

職業柄、普段から Azure のいろんなサービスをデプロイして検証することが多いです。
その中で、VNET 内に閉じたサービスの動作検証もするのですが、当初は同じ VNET の中にパブリック IP アドレスを持った Windows VM を立てて、使う時だけ起動してリモート デスクトップ経由で VNET 内のリソースにアクセスしていました。

f:id:horihiro:20211002091553p:plain

ただパブリック IP アドレスを持つ VM の管理も手間だし、都度 VM の起動完了を待つ、というのも億劫になったので、いつの頃からか P2S VPN でローカル PC を VNET に直接繋げるようにしています。

docs.microsoft.com

この時、冒頭に書いた Azure Private DNS Zone の制限のため、VPN でつなげたローカル PC からの名前解決に使えませんでした。

特に Private Endpoint 経由で PaaS にアクセスする場合、多くのサービスでは FQDN を使ってアクセスする必要があるので Private DNS Zone に管理してもらうのが楽です。
Private DNS Zone が使えないとパブリック IP アドレスで名前解決されてしまうので、Private Endpoint が有効な PaaS へのアクセス拒否されてしまいます。

f:id:horihiro:20211002091628p:plain

最近まで DNS フォワーダーを使う方法を知らなかったので、ローカル PC の hosts ファイルをいじることで凌いでいましたが、当然 hosts ファイルは Private DNS Zone と連携しないので、二重管理になるだけです。
違う FQDN のリソースが VNET 内に増えるたびに追記していくのもつらいし、使わなくなった時に消すのを忘れて肥大化してしまうので、あまりいいやり方ではないでしょう。

というわけで、今回 DNS フォワーダーを ACI で立てて、VNET に接続する時だけサクッと起動し、用が済んだら終了という構成を試しています。

f:id:horihiro:20211002091650p:plain

コンテナーの起動が割と早いので、ストレスなくいい感じです。

似たような環境を使っている方はお試しを。