FreeBSDでunbound

ちょっと試したいことがあって、unboundを調べてみました。

FreeBSD 12.1RにはOSの一部としてunboundが入っていて/usr/sbinに実行ファイルがあります。

パッケージのunboundと区別するために/usr/sbinのunboundはlocal-unboundという名前になっています。

デフォルトの設定ファイルは/var/unbound/unbound.confになります。

local-unbound-controlというプログラムで、コントロールできるのですが、local-unboundとの通信がSSLで鍵が必要になっています。

鍵はlocal-unbound-setupで作ることができるとのことなのですが、できなかったので、下記のスクリプトで作って見ました。

```sh
#!/bin/sh
# validity period for certificates
DAYS=7200

# size of keys in bits
BITS=1536

# hash algorithm
HASH=sha256

# issuer and subject name for certificates
SERVERNAME=local-unbound
CLIENTNAME=local-unbound-control

# base name for unbound server keys
SVR_BASE=unbound_server

# base name for unbound-control keys
CTL_BASE=unbound_control


openssl genrsa -out $SVR_BASE.key $BITS
openssl genrsa -out $CTL_BASE.key $BITS

cat >request.cfg <<EOF
[req]
default_bits=$BITS
default_md=$HASH
prompt=no
distinguished_name=req_distinguished_name

[req_distinguished_name]
commonName=$SERVERNAME
EOF

openssl req -key $SVR_BASE.key -config request.cfg  -new -x509 -days $DAYS -out $SVR_BASE.pem

# create trusted usage pem
openssl x509 -in $SVR_BASE.pem -addtrust serverAuth -out $SVR_BASE"_trust.pem"

cat >request.cfg <<EOF
[req]
default_bits=$BITS
default_md=$HASH
prompt=no
distinguished_name=req_distinguished_name

[req_distinguished_name]
commonName=$CLIENTNAME
EOF

openssl req -key $CTL_BASE.key -config request.cfg -new | openssl x509 -req -days $DAYS -CA $SVR_BASE"_trust.pem" -CAkey $SVR_BASE.key -CAcreateserial -$HASH -out $CTL_BASE.pem
```

これを実行してできたunbound_control.key,unbound_control.pem,unbound_server.key,unbound_server.pemを/var/unbound/に起きunbound.confに以下を追加するとlocal-unbound-controlが使えます。

```
remote-control:
        control-enable: yes
```

amd64なホストで実行してみます。

```
# /usr/sbin/local-unbound-control status
version: 1.8.1
verbosity: 1
threads: 1
modules: 2 [ validator iterator ]
uptime: 6881 seconds
options: control(ssl)
unbound (pid 1475) is running...
```

我が家ではAtheros(MIPS Bigendian)のルーターの上でunboundを動かしているのですが、同じようにしてもエラーになります。

```
# /usr/sbin/local-unbound-control status
error: SSL handshake failed
```

~~バグってるような気がします。~~

kill -HUPだとダメで、プロセスを起動しなおしたらいけました。

リモートからlocal-unbound-controlでデータと取得する方法もありますが、すでにsnmpの設定してあったので、snmp経由でクエリー数のグラフを作って見たいと思います。

snmpd.configに以下を追加します。

```
begemotSnmpdModulePath."ucd" = "/usr/local/lib/snmp_ucd.so"
%ucd
updateInterval = 500
extCheckInterval = 100
extUpdateInterval = 6000
extTimeout = 60

# Extension commands (extTable)

extNames.0 = "unbound_queries"
extCommand.0 = "/etc/un.sh total.num.queries"
```

/etc/un.shはとりあえずこんな感じです。

```sh
#!/bin/sh

/usr/sbin/local-unbound-control stats_noreset | awk 'BEGIN{FS="="}/'$1'=/{print $2}'
```

これをsnmpなホストで取得して、sqlite3に入れます。

```sh
#!/bin/sh

VAL=`bsnmpwalk -s 10.0.1.1 .1.3.6.1.4.1.2021.8.1.101 | sed 's/.* = //'`

/usr/local/bin/sqlite3 /tmp/net.db "insert into unbound_queries(num) values("${VAL}")"
```

mrubyのcgiでjsonにします。

```ruby
#!/usr/local/bin/mruby

params = {}
que = ENV['QUERY_STRING']
para = que.to_s.split('&')
para.each do |p|
  a = p.split('=')
  params[a[0]] = a[1]
end

db = SQLite3::Database.new('/tmp/net.db')

time = Array.new
val = Array.new

if params["ago"]
  ago = params["ago"].to_i
else
  ago = 0
end

tday = (Time.now - 60*60*24*ago).to_s[0, 10]

# select by JST
sel = 'select time(datetime(date, time, "localtime")), num from unbound_queries'
whe = ' where date(datetime(date, time, "localtime"))=?'

i = 0
db.execute(sel + whe, tday) do |row, fields|
  time[i] = row[0]
  val[i] = row[1]
  i = i + 1
end

print "Content-type: text/json\n\n"

j = 0
tmo = 0
print '{"date":"' + tday + '","type":"unbound_queries","data":['
while j < i do
  if j != 0
    print ","
  end
  print "["
  print "\"" + time[j] + "\"," + val[j].to_s
  print "]"
  j = j + 1
end
print ']}'
```

これをchart.jsでグラフにします。

![filename-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/732c2b13-985b-01e4-0fb5-7a8b2a33e320.png)

グラフが時々0になることがあります。

![unhup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/5dda3eb3-b995-625d-3a27-7c8202ceb2d9.png)

調べてみたところDHCPが更新されたタイミングでunboundをHUPしているためのようです。

DHCPの更新の時にDNSが変わってなければ[reloadしないように](https://qiita.com/yamori813/items/07ce0bf05208f93a729d)しました。

12.3-STABLEでソースをアップデートしたらエラーになるようになってた。

```
# /usr/sbin/local-unbound-control stats_noreset
error: SSL handshake failed
1085091840:error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:/usr/home/hiroki/freebsd-src/crypto/openssl/ssl/statem/statem_clnt.c:1921:
```

そもそもローカルしかアクセスできないので、以下にした。よい子はまねしないでね。

```
remote-control:
        control-enable: yes
        control-use-cert: no
```

unboundちょくちょく挙動変わってあんまり作りよくない。なんだかな。