雑記帳

整理しない情報集

更新情報

Docker+WireGuardにDNSを構築する

公開日:

カテゴリ: ネットワーク

Dockerで構築したWireGuardに内部用のDNSを構築してみます。

今回作成する構成

  • あくまで内部用の補助的なDNSとして位置付け
    • VPNで接続しているときだけ使用する
    • VPNを使用しない接続(同一LANに接続しているだけ)では使用しない
      • このパターンで名前解決が必要な場合はDNSサーバを別途立てる
  • 特定のサブドメインの名前解決を、特定のDockerネットワークに流す

LinuxServer.ioのWireGuardイメージ

LinuxServer.ioで構築されたWireGuardのDockerイメージ(以降、linuxserver/wireguard)ではCoreDNSが併用されており、デフォルトのDNSサーバとして動作しています。

デフォルトの設定では、そのままresolv.confを参照しに行きます。Dockerコンテナのresolv.confには127.0.0.11がバインドされているため、そのままホストのDockerの内部DNSへと渡っていきます。

CoreDNSの設定

linuxserver/wireguardを起動すると、設定ファイルの保存先にcorednsというディレクトリと、その中にCorefileというファイル(/config/coredns/Corefile)が生成されます。WireGuardの設定でDNSサーバを変更していない場合、このCorefileを編集することでDNSの様々な制御が行えます。

/configディレクトリはボリュームとしてマウントしているはずですので、Corefileはホスト側から直接編集可能です。

. {
	loop
	errors
	health
	forward . /etc/resolv.conf
}

デフォルト設定は前述の通りresolv.confにフォワードするだけですが、CoreDNSではtemplateプラグイン(標準機能)を使用することで、正規表現のパターンマッチングでDNSの応答を行うことができます。

. {
    loop
	errors
    health
    template IN ANY myhost.example.com {
        match "^([^\.]+)\.myhost\.example\.com\.$"
        answer "{{ index .Match 1 }}.myhost.example.com. IN CNAME {{ index .Match 1 }}."
        fallthrough
    }
    forward . /etc/resolv.conf
}

上記の例ではmyhost.example.comの第4レベルのサブドメインをそのままCNAMEとして応答します。例えばaaa.myhost.example.comのDNS問い合わせがあった場合、aaaと返されます。同一Dockerネットワーク内にaaaという名前のコンテナもしくはホストでサーバが立っていればaaa.myhost.example.comでアクセスできます。

もちろん、Dockerネットワーク名を指定することもできます。以下の例ではmynetworkというDockerネットワークに向けた(mynetworkをTLDとした)応答をします。

# aaa.myhost.example.com -> aaa.mynetwork
answer "{{ index .Match 1 }}.myhost.example.com. IN CNAME {{ index .Match 1 }}.mynetwork."

設定後、コンテナを立ち上げなおすと適用されます。VPNで接続しているときだけ使用するだけであれば、ここまでの手順で完了です。

おまけ

DNSサーバへのフォワード

Docker内部DNSを使用したくない場合は、パブリックDNSを指定してフォワードすることもできます。

#forward . /etc/resolv.conf
forward . 1.1.1.1

DNSブロッキング

応用すればVPN接続時だけDNSブロッキングも可能です。

template IN ANY example.jp {
    rcode NXDOMAIN
}

templateプラグインのrcodeでレスポンスコードを指定できるので、NXDOMAINNODATAを指定することで名前解決できなくなります。

カテゴリ: ネットワーク