QNAPで内部向けDNSサーバ(dnsmasq)をdockerに立てる話

# はじめに
QNAPでDocker内にDNSサーバを立てる。
目的は二つ。
1. 子供たちのPC/スマホ用にアクセス先を制限したい
1. NextDNSのクエリ量を減らしたい

①だけであればNextDNSそのまま狙えばいいんだけど、②をやってみようかとDNSキャッシュサーバを立てることにした。
QNAPにdnsmasqを入れるのはQiita上にも多数存在しているが、Docker上に立てるのがなかったので記事として立ててみた。

# 条件
* SSHができること
* Dockerが動いていること

# ディレクトリ構造

```
.
├── docker-compose.yml
├── dnsmasq.d
│   ├── adblock.conf
│   ├── address.conf
│   └── my.conf
└── log
    └── dnsmasq.log
```

## 各ファイルの中身
```docker-compose.yml
version: '3'
services:
  dnsmasq:
    restart: always
    image: 4km3/dnsmasq
    container_name: dnsmasq
    ports:
      - 192.168.0.2:53:53/udp  # ポート転送設定だけConflictが出てしまったのでQNAP自体のIPを明示。自分のQNAPのIPへ変更すること
      - 192.168.0.2:53:53/tcp
    volumes:
      - "./dnsmasq.d:/etc/dnsmasq.d"
      - "./log:/var/log"                                 # ログをとるためのDIRを作る
      - "/usr/share/zoneinfo/Asia/Tokyo:/etc/localtime"  # ログ用のTimezoneを設定
    dns:
      - <上位DNS>  #私の場合はNextDNS
      - <上位DNS>
    cap_add:
      - NET_ADMIN
```

``` my.cnf
bogus-priv
expand-hosts
domain=local
log-queries
log-facility=/var/log/dnsmasq.log  # 子供たちのクエリログを見ておきたい
max-ttl=600
max-cache-ttl=600
``` 

``` address.conf
# 一応、ルートDNSだけは自分で持っておいてNextDNSへ飛ばさないようにする
address=/a.root-servers.net/198.41.0.4
address=/b.root-servers.net/199.9.14.201
address=/c.root-servers.net/192.33.4.12
address=/d.root-servers.net/199.7.91.13
address=/e.root-servers.net/192.203.230.10
address=/h.root-servers.net/198.97.190.53
address=/i.root-servers.net/192.36.148.17
address=/j.root-servers.net/192.58.128.30
address=/k.root-servers.net/193.0.14.129
address=/l.root-servers.net/199.7.83.42
address=/m.root-servers.net/202.12.27.33

# この辺もクエリ数が多いのでNextDNSへ飛ばさないように。
address=/.pixiv.net/0.0.0.0 
address=/.sch.line.me/0.0.0.0
address=/.obs.line-scdn.net/0.0.0.0
```

``` adblock.conf
# こいつもNextDNSへ飛ばさないようにするためのリスト。
# warui.intaa.netから生成する
# hosts by warui.intaa.net  2023-08-14 04:06:14
address=/0000mps.webpreview.dsl.net/0.0.0.0
address=/0001.2waky.com/0.0.0.0
~~~snip~~~
```

## adblock.confの生成
crontabでやってもいいし、あまり気にしないのであれば気が付いたときに作成してもよし。
ここでは`warui.intaa.net`のhostsを使っているけど、それ以外に280Blockerのリストなどを使ってもいいかもしれない(280Blockerはファイル名に日付が入っていて変動するのでちょっと面倒)
``` curl
curl -s https://warui.intaa.net/adhosts/hosts.txt | sed -E "s/(0.0.0.0) (.*)$/address=\/\2\/\1/" > ./dnsmasq.d/adblock.conf
```
# コンテナの起動
上記ディレクトリで以下のコマンドを実行
```
docker-compose up -d
```
うまくいけばdnsmasqが起動する。

```
$ docker ps -a
CONTAINER ID  IMAGE         COMMAND                 CREATED       STATUS      PORTS                                           NAMES
b01e5dxxxxxx  4km3/dnsmasq  "/usr/sbin/dnsmasq -k"  12 hours ago  Up 3 hours  192.168.0.2:53->53/tcp, 192.168.0.2:53->53/udp  dnsmasq
```
上記でDockerの状況確認。
qnap自体のDNSは別に向いているだろうから、クエリが正常に行われるかどうかは以下のようにして確認する。
```
$ dig @192.168.0.2 test.pixiv.net | grep "^;; ANSWER" -A 1
;; ANSWER SECTION:
test.pixiv.net.         0       IN      A       0.0.0.0
```

ログは `./log/dnsmasq.log` に出力されるので確認してみる。
```
$ cat ./log/dnsmasq.log | tail
Aug 10 10:00:00 dnsmasq[1]: query[A] test.pixiv.net from 192.168.0.3
Aug 10 10:00:00 dnsmasq[1]: config test.pixiv.net is 0.0.0.0
```
`address.conf` に記載された通り、pixiv.netのサブドメインを検索したが0.0.0.0を返していて、なおかつNextDNSでもログがない。

# おわりに
NextDNSは非常に優秀なサービスだし、課金してもそんなに大きな金額ではないため課金しようとは思っているが、単純に興味ベースでできるかどうか試してみたかった。
今後、BINDでDNSを立てたりしてみたいかな。