Bindで管理ドメインの存在しないレコードに対する問い合わせに、再帰問い合わせの結果を応答させる

##概要
表題の通り

2015/8/22)
iptablesで落としていたルールが NXDOMAINだったらDROPではなく
レコードがなかったらDROPであったため修正しました。

## テスト環境
|Private DNSサーバ|管理ドメイン|
|---|---|
|192.168.7.129|example.net|

### テスト内容
|No|問い合わせ|Private DNSサーバへのRecode存在有無|外部権威DNSへのRecode存在有無|期待する結果|
|---|---|---|---|---|
|1|private.example.net|有|無|Private DNS が 192.168.7.129 を返す|
|2|www.example.net|無|有|外部権威DNS が 93.184.216.34 を返す|

# bindの設定
example.net を bind の view で 127.0.0.1 に forward し、そこを権威として設定する

```named.conf
view local {
	match-clients { 127.0.0.1;}; 
	recursion no;

	zone "example.net." {
		type master;
		file "zone/example.net.zone";
	};

};

view public {
	match-clients { any;}; 
	recursion yes;

	zone "." {
		type hint;
		file "conf/named.ca";
	};

	zone "example.net." {
		type forward;
		forwarders { 127.0.0.1; };
		forward first ;
	};

};

```

```zone/example.net.zone
$TTL 5
@	IN	SOA	example.net. root.example.net. (
			2015080101	; Serial
			3600		; Refresh
			300		; Retry
			3600000		; Expire
			3600		; Minimum
			)
@			IN	NS	ns.example.net.
@			IN	A	192.168.7.129
ns			IN	A	192.168.7.129
private		IN	A	192.168.0.1
```

※ dnssec関連の設定は無効にすること

#テスト

```test1:test1
$ dig @192.168.7.129 private.example.net
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27575
private.example.net.	5	IN	A	192.168.0.1

成功!!
```

```test2:test2
$ dig @192.168.7.129 www.example.net
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 3048

失敗!!

forwarderからNXDOMAINが返って来ても、再帰問い合わせはしてくれない。
forward first はforward先からの応答が返ってこない場合に再帰問い合わせをするので
NXDOMAINのパケットがforwarderから返って来たら捨てることにする
```

#iptablesの設定

iptablesに 127.0.0.1 からの応答クエリかつ、NXDOMAINのクエリだった場合、DROPするルール
(NOERRORは DROPしない)

```iptables:/etc/sysconfig/iptables
# 応答クエリの判定
-A INPUT -p udp -s 127.0.0.1 --sport 53 -m string --hex-string "|8503|" --algo bm --from 30 --to 32 -m comment --comment "check dns reply" -j DROP
```

#テスト

```test1:test1
# iptables -L -nxv | grep ALGO
       0        0 NXDROP     udp  --  *      *       127.0.0.1            0.0.0.0/0           udp spt:53 STRING match "|85|" ALGO name bm FROM 30 TO 31 /* check dns reply */ 
       0        0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           STRING match "|0000|" ALGO name bm FROM 34 TO 36 /* drop nxdomain query */

# dig @192.168.7.129 private.example.net
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64385
private.example.net.	5	IN	A	192.168.0.1

# iptables -L -nxv | grep ALGO
       1      125 NXDROP     udp  --  *      *       127.0.0.1            0.0.0.0/0           udp spt:53 STRING match "|85|" ALGO name bm FROM 30 TO 31 /* check dns reply */ 
       0        0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           STRING match "|0000|" ALGO name bm FROM 34 TO 36 /* drop nxdomain query */ 
=> NXDOMAINではないので捨てていない
```

```test2:test2
# iptables -L -nxv | grep ALGO
       0        0 NXDROP     udp  --  *      *       127.0.0.1            0.0.0.0/0           udp spt:53 STRING match "|85|" ALGO name bm FROM 30 TO 31 /* check dns reply */ 
       0        0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           STRING match "|0000|" ALGO name bm FROM 34 TO 36 /* drop nxdomain query */ 

# dig @192.168.7.129 www.example.net
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2848
www.example.net.	5	IN	A	93.184.216.34

成功!!

# iptables -L -nxv | grep ALGO
       2      226 NXDROP     udp  --  *      *       127.0.0.1            0.0.0.0/0           udp spt:53 STRING match "|85|" ALGO name bm FROM 30 TO 31 /* check dns reply */ 
       2      226 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           STRING match "|0000|" ALGO name bm FROM 34 TO 36 /* drop nxdomain query */ 
=> NXDOMAINだったので捨てている
```
#結果
この手法では、cacheに載っていない問い合わせについて数秒応答にかかってしまう。
unboundだったら簡単にできるのでzone転送をしなくてもよい単独DNSであればunboundで素直に構築するのがいいと思います。