Docker Desktop (for macOS) で BIND (named) の SERVFAIL 応答の再現環境を構築する

# はじめに

DNSに登録されたドメイン情報の設定がおかしく、ISC BIND(named)ではSERVFAIL応答になる場合がある。

```
dig foxanthony-robert48.iresg.com mx
```

; <<>> DiG 9.18.24-0ubuntu5-Ubuntu <<>> foxanthony-robert48.iresg.com mx
;; global options: +cmd
;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: <font color="#FF0000">SERVFAIL</font>, id: 57230
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 9dea33d4ed48a45701000000669c6d8b20855d65cecad4fb (good)
;; QUESTION SECTION:
;foxanthony-robert48.iresg.com.	IN	MX

;; Query time: 488 msec
;; SERVER: 127.0.0.1#53(localhost) (UDP)
;; WHEN: Sun Jul 21 02:08:11 UTC 2024
;; MSG SIZE  rcvd: 86

エラーの原因はSOAレコードの検証に失敗しているためです。

```bash
21-Jul-2024 02:08:54.957 DNS format error from 162.159.25.175#53 resolving foxanthony-robert48.iresg.com/MX for 192.168.65.1#49280: Name com (SOA) not subdomain of zone iresg.com -- invalid response
21-Jul-2024 02:08:54.957 FORMERR resolving 'foxanthony-robert48.iresg.com/MX/IN': 162.159.25.175#53
```

Google Public DNS (8.8.8.8)ではエラーになりません。

# Docker Desktop (for macOS)で動作検証する

## 環境

macOS Sonoma 14.5
Docker Desktop 4.32.0

## Docker Desktopの動作環境

Dockerfileとnamed.conf.optionsファイル(理由は後述)を用意します。

```file:Dockerfile
FROM ubuntu/bind9:latest

RUN apt-get update -y
RUN apt-get install vim iputils-ping dnsutils net-tools -y

COPY named.conf.options /etc/bind/
```

```file:named.conf.options 
acl "access-list" {
    127.0.0.1;
    172.17.0.0/16;
    192.168.0.0/16;
};

options {
        directory "/var/cache/bind";
        allow-recursion { access-list; };
        allow-query { access-list; };
        allow-query-cache { access-list; };
        dnssec-validation auto;
        listen-on-v6 { any; };
};
```

Dockerイメージを作成します。

```bash
docker build -t bind .
```

コンテナを起動します。(コンテナ側はポート番号:53で起動し、ホスト側はポート番号:10053でListenします。)

```bash
docker run -dit -p 10053:53 -p 10053:53/udp --name bind bind:latest
```

![スクリーンショット 2024-07-21 18.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/3eaa68c8-21cd-35fc-98ec-7ff355c67e8d.png)

## コンテナ環境で動作確認

コンテナ環境へログインします。

```bash
docker exec -it bind /bin/bash
```

digコマンドを実行すると、Docker Desktopで用意したDNSが使用されます。(/etc/resolv.confにnameserver 192.168.65.7が設定されているため)

```bash
dig www.google.com
```

Docker Desktopで用意したDNSではSERVFAIL応答が再現されません。
DNSにISC BIND(named)を使用するためには、digコマンドの引数に＠localhostを指定します。

```bash
dig www.google.com @localhost
```

これでSERVFAIL応答の再現環境を構築できました。

![スクリーンショット 2024-07-21 20.24.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/eb3b3d12-60dc-4962-e0b7-00e75b8cb1f0.png)

## ホスト環境で動作確認

ホスト側から名前解決する際のDNSに、コンテナ環境のISC BIND(named)を使用するためには、digコマンドの引数に-p 10053と＠localhostを指定します。

```bash
dig www.google.com -p 10053 @localhost
```

コンテナ側では接続元のIPアドレスが192.168.65.1として認識されるため、デフォルトではDNS参照ができません。
named.conf.optionsでacl (access control list)に192.168.0.0/16を設定しているのはホスト側からDNS参照をできるようにするためです。

![スクリーンショット 2024-07-21 20.33.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c3119691-4bcd-b1b5-0179-68a406cecc2e.png)

これでホスト側からもSERVFAIL応答の再現環境を構築できました。

## (参考)

dockerdが動作しているVM環境へログインしてネットワーク環境を確認する場合、以下のコマンドを実行します。

```bash
docker run -it --rm --privileged --pid=host justincormack/nsenter1
```

https://stackoverflow.com/questions/62849480/what-is-the-docker-subnet-used-for

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/dd0daf05-22a3-34e7-9437-bcc0d97adcfa.jpeg)