resolvconfd と dnsmasq と libvirt と unbound と私

※忘れそうなのでメモです。

私が会社で使っている作業用サーバはUbuntuのKVM上で動いているFreeBSDです。(ホストのUbuntuも使ってるけど)
気が向いたときにホストのapt-get update/upgradeをするのですが、たまにKernelのアップデートがくると
再起動をしなくてはいけないので、仕方なく再起動をしています。

この時点で resolv.conf を手書きで書き換えていたりすると、楽しいことが起こったりします。

Ubuntu12.04では resolv.conf  の管理を resolvconfd で行っていて、デフォルトではローカルで起動している
リゾルバ(dnsmasq) を参照するように、起動のたびに 127.0.0.1 を参照するように resolv.conf を書き換えてくれるという仕様になっています。

とても親切ですね。

私が仕事で使っている環境は同ホストで unbound を起動してキャッシュリゾルバとしても使用しているので、
dnsmasq が起動されると bind しているアドレス・ポートがかぶって unbound が起動しなかったりで
一筋縄には行かないのです。(dnsmasqの存在を意識していなかった)

ということで、「dnsmasq が邪魔なら dnsmasq を起動しなければ良い!」 という安直な考えに至り、dnsmasq を stop

root@mykw:/# /etc/init.d/dnsmasq stop
* Stopping DNS forwarder and DHCP server dnsmasq
…done.
root@mykw:/#

これで、安心だろ。
と、おもって KVM の FreeBSD (ゲスト)にログインするとネットワークがつながらない・・・
libvirt で仮想マシンを管理しているので、dnsmasq を切ってしまうとどうやら外に出られなくなるみたいだ(詳しくは調べてません)

「そうしたら  dnsmasq と unbound を共存させればいいんだろ?」という安直な考えに至り、 conf を編集

root@mykw:/# vi /etc/unbound/unbound.conf

server:
interface: 192.168.10.70

(略)

 

root@mykw:/# vi /etc/dnsmasq.conf

listen-address=127.0.0.1
bind-interfaces

これでデーモンを再起動すれば dnsmasq/unbound が共存できます。

ちなみに、前置きが長くなりましたが、ここからが本編です。
resolvconfd の挙動が良く分からなかったので今回はじっくり観察してみました。

Googleなんかで “ubuntu 12.04 resolv.conf” などと検索すると、
大抵のBlog記事は /etc/resolvconf/resolv.conf.d/ 以下のファイルを編集しろと書かれています。

root@mykw:/etc/resolvconf/resolv.conf.d# ls
base  head  original

ここで引っかかりました。
いくら編集して、resolvconfd/networking/server再起動しても  resolv.conf が思ったように書き換わらないので、
Ubuntuのマニュアルをよく読んでみた。

http://manpages.ubuntu.com/manpages/precise/man8/resolvconf.8.html

/etc/network/interfaces を編集すればよいことが判明。(ちゃんと書いてあるじゃん)
オフィシャルなマニュアルをちゃんと読まないと遠回りしてしまうんですね。

ということで  /etc/network/interfaces を以下のようにしてみた

auto br0
iface br0 inet static
address 192.168.10.70
network 192.168.0.0
netmask 255.255.0.0
broadcast 192.168.255.255
gateway 192.168.0.1
dns-nameservers 192.168.10.70 192.168.0.20 8.8.8.8
dns-domain hoge.com
dns-search fuga.net foo.com
bridge_ports eth0
bridge_stp off

iface eth0 inet manual

どうやら “dns-*” な行を読み取って resolv.conf を読みよってくれるようなので、
これでネットワークをリスタートして resolv.conf を見てみましょう。

root@mykw:/# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND — YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1
search choge.com fuga.net foo.com
root@mykw:/#

nameserver が 127.0.0.1 になっていますが、心配ありません。
dnsmasq がロードしている conf を参照すると以下のようになっています。

root@mykw:/# cat /var/run/dnsmasq/resolv.conf
nameserver 192.168.10.70
nameserver 192.168.0.20
nameserver 8.8.8.8

コレに気づかず30分ぐらい時間を無駄にしました。

ちなみに、 dnsmasq や unbound などのデーモンが起動していない(起動しない)環境では /etc/resolv.conf の
nameserver  は 127.0.0.1 ではなく、 /etc/networl/interfaces に書かれている dns-nameservers の値が明示的に入るようです。

親切というか、なんと言うか、今までの掟的なものが頭から離れないとハマること間違いなしですね。

お家でUnboundつかってISPのDNSポイズニングから逃れてみる

数年前の話題だが、児童ポルノ法の施工に伴って、ISPのDNSキャッシュ汚染が常習的に行われるようになったのですが、
そんな自由を侵すようなリゾルバは使ってられないということ(嘘)で自宅にもUnboundを導入してみました。

※本当は自宅サービスサーバのユーザが増えてきたので、何となくLAN内でリゾルバを持ちたくなっただけ。

0. 運用環境

OS : Ubuntu 10.04 LTS
HW : HP Proliant MicroServer

1. apt-get で インストール

ゆとり世代なのでapt-getでインストール。
apt 簡単でいいね。

micro# apt-get install unbound

2. ルートヒントファイルをダウンロードしておく

これがないと、どこに聞きに行くのかわからない。はず。(なくても名前解決できたけどね。)

micro# cd /etc/unbound && wget ftp://FTP.INTERNIC.NET/domain/named.cache

3. confを目的・環境に合わせて書き換える

自分の場合は自宅内のローカルからのみ名前解決できるようするのが目的だったので、
以下の箇所を書き換えた。ちなみにIPv6を使わない場合はv6系の項目は無視しておk

micro# diff -u unbound.conf.def unbound.conf
— unbound.conf.def    2012-04-14 16:33:20.268064334 +0900
+++ unbound.conf        2012-04-14 16:47:19.748193075 +0900
@@ -34,7 +34,10 @@
# specify 0.0.0.0 and ::0 to bind to all available interfaces.
# specify every interface[@port] on a new ‘interface:’ labelled line.
# The listen interfaces are not changed on reload, only on restart.
–       # interface: 192.0.2.153
+       interface: 127.0.0.1
+       interface: 192.168.0.128
+       interface: ::1
+       interface: 240f:1:33f2:1::cafe
# interface: 192.0.2.154
# interface: 192.0.2.154@5003
# interface: 2001:DB8::5
@@ -44,7 +47,7 @@
# interface-automatic: no

# port to answer queries from
–       # port: 53
+       port: 53

# specify the interfaces to send outgoing queries to authoritative
# server from by ip-address. If none, the default (all) interface
@@ -116,7 +119,7 @@

# the time to live (TTL) value cap for RRsets and messages in the
# cache. Items are not cached for longer. In seconds.
–       # cache-max-ttl: 86400
+       cache-max-ttl: 86400

# the time to live (TTL) value for cached roundtrip times and
# EDNS version information for hosts. In seconds.
@@ -137,16 +140,16 @@
# infra-cache-lame-size: 10k

# Enable IPv4, “yes” or “no”.
–       # do-ip4: yes
+       do-ip4: yes

# Enable IPv6, “yes” or “no”.
–       # do-ip6: yes
+       do-ip6: yes

# Enable UDP, “yes” or “no”.
–       # do-udp: yes
+       do-udp: yes

# Enable TCP, “yes” or “no”.
–       # do-tcp: yes
+       do-tcp: yes

# Detach from the terminal, run in background, “yes” or “no”.
# do-daemonize: yes
@@ -157,9 +160,11 @@
# Choose deny (drop message), refuse (polite error reply),
# allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
# access-control: 0.0.0.0/0 refuse
–       # access-control: 127.0.0.0/8 allow
+       access-control: 127.0.0.0/8 allow
+       access-control: 192.168.0.0/24 allow
# access-control: ::0/0 refuse
–       # access-control: ::1 allow
+       access-control: ::1 allow
+       access-control: 240f:1:33f2:1::0/64 allow
# access-control: ::ffff:127.0.0.1 allow

# if given, a chroot(2) is done to the given directory.
@@ -214,7 +219,7 @@

# file to read root hints from.
# get one from ftp://FTP.INTERNIC.NET/domain/named.cache
–       # root-hints: “”
+       root-hints: “/etc/unbound/named.cache”

# enable to not answer id.server and hostname.bind queries.
# hide-identity: no
@@ -437,27 +442,27 @@
remote-control:
# Enable remote control with unbound-control(8) here.
# set up the keys and certificates with unbound-control-setup.
–       # control-enable: no
+       control-enable: yes

# what interfaces are listened to for remote control.
# give 0.0.0.0 and ::0 to listen to all interfaces.
–       # control-interface: 127.0.0.1
–       # control-interface: ::1
+       control-interface: 127.0.0.1
+       control-interface: ::1

# port number for remote control operations.
–       # control-port: 953
+       control-port: 953

# unbound server key file.
–       # server-key-file: “/etc/unbound/unbound_server.key”
+       server-key-file: “/etc/unbound/unbound_server.key”

# unbound server certificate file.
–       # server-cert-file: “/etc/unbound/unbound_server.pem”
+       server-cert-file: “/etc/unbound/unbound_server.pem”

# unbound-control key file.
–       # control-key-file: “/etc/unbound/unbound_control.key”
+       control-key-file: “/etc/unbound/unbound_control.key”

# unbound-control certificate file.
–       # control-cert-file: “/etc/unbound/unbound_control.pem”
+       control-cert-file: “/etc/unbound/unbound_control.pem”

# Stub zones.
# Create entries like below, to make all queries for ‘example.com’ and
micro#

4. リモートコントロールできるようにする

unbound-control を使えるようにするために秘密鍵、公開鍵を生成。
unbound-control は BIND でいうところの rndc ですね。

# unbound-control-setup
setup in directory /etc/unbound
generating unbound_server.key
Generating RSA private key, 1024 bit long modulus
………………..++++++
………………………….++++++
e is 65537 (0x10001)
generating unbound_control.key
Generating RSA private key, 1024 bit long modulus
……….++++++
..++++++
e is 65537 (0x10001)
create unbound_server.pem (self signed certificate)
create unbound_control.pem (signed client certificate)
Signature ok
subject=/CN=unbound-control
Getting CA Private Key
Setup success. Certificates created. Enable in unbound.conf file to use
micro#

5. Unboundを再起動する

micro# /etc/init.d/unbound restart
* Restarting recursive DNS server unbound                                                                       [ OK ]
micro#

6. 名前解決ができるか確認

とりあえずローカルホストから確認。
LAN内のほかのホストからも確認した方が良い。

micro# dig @localhost mykw.jp

; <<>> DiG 9.7.0-P1 <<>> @localhost mykw.jp
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13101
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 4

;; QUESTION SECTION:
;mykw.jp.                       IN      A

;; ANSWER SECTION:
mykw.jp.                180     IN      A       180.222.80.63

;; AUTHORITY SECTION:
mykw.jp.                180     IN      NS      ns0.mykw.jp.
mykw.jp.                180     IN      NS      ns1.mykw.jp.

;; ADDITIONAL SECTION:
ns0.mykw.jp.            180     IN      A       49.212.22.200
ns0.mykw.jp.            180     IN      AAAA    2001:e41:31d4:16c8::1
ns1.mykw.jp.            180     IN      A       183.181.172.61
ns1.mykw.jp.            180     IN      AAAA    2001:2e8:603:0:2:1:0:3d

;; Query time: 15 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sat Apr 14 17:00:02 2012
;; MSG SIZE  rcvd: 165

micro#

7. リモートコントロールの動作確認

ステータスが取れれば成功

micro# unbound-control status
version: 1.4.1
verbosity: 1
threads: 1
modules: 2 [ validator iterator ]
uptime: 4 seconds
unbound (pid 5050) is running…
micro#

 

これでISPのDNSポイズニングから抜け出せますね。

めでたしめでたし

 

参考資料・サイト

日本Unboundユーザ会 http://unbound.jp/

 

dnsperf で DNS DoS(違) ベンチマーク

大先生に教わりながら仕事で使ったので忘備録

 

0. 検証環境

筐体:IBM System X3550M2
OS:Ubuntu Server 11.10

 

1. 必要そうなパッケージを入れる

mykw# apt-get install bind9utils libbind-dev libkrb5-dev libssl-dev libcap-dev libxml2-dev gnuplot

GNU Plotは resperf-report するときに使うのかな。

2. ソースを拾って展開して make

mykw# wget ftp://ftp.nominum.com/pub/nominum/dnsperf/1.0.1.0/dnsperf-src-1.0.1.0-1.tar.gz

mykw# tar xzf dnsperf-src-1.0.1.0-1.tar.gz && cd dnsperf-src-1.0.1.0-1

mykw# ./configure prefix=/usr/local

mykw# make && make install

 

3. 実行してみる

初めに以下のようなリストを作る

mykw# cat domainlist

http://www.wktk.so A
yutarommx.com A

 

クエリー飛ばす先と、リストファイル名、実行時間を引数に入れて実行。

mykw# dnsperf -s ${DIST}  -d ${domainlist} -l ${exectime}

mykw# dnsperf -s 192.168.10.139  -d domainlist -l 60

 

ほかにもいろいろオプションがある模様。

mykw# dnsperf –help

DNS Performance Testing Tool

Nominum Version 1.0.1.0

dnsperf: invalid option — ‘-‘

Usage: dnsperf [-d datafile] [-s server_addr] [-p port]
               [-b bufsize] [-f family] [-e] [-D]
               [-y name:secret] [-v] [-A] [-h]
               [-q num_queries] [-t timeout] [-Q max_qps] [-1] [-l limit]
               [-c] [-H histogram_buckets] [-T histogram_seconds] [-u]
  -d specifies the input data file (default: stdin)
  -s sets the server to query (default: 127.0.0.1)
  -p sets the port on which to query the server (default: 53)
  -b set socket send/receive buffer size in kilobytes (default: 32 k)
  -f specify address family of DNS transport, inet or inet6 (default: any)
  -e enable EDNS 0
  -D set the DNSSEC OK bit (implies EDNS)
  -y specifies the TSIG name and secret (no default)
  -A report command-line arguments
  -h print this usage
  -q specifies the maximum number of queries outstanding (default: 20)
  -t specifies the timeout for query completion in seconds (default: 5)
  -Q limit the number of queries per second (no default)
  -1 run through input only once (default: multiple iff limit given)
  -l specifies how a limit for how long to run tests in seconds (no default)
  -c print the number of packets with each rcode
  -H print a response latency histogram with this many buckets
  -T include latencies up to this many seconds in histogram (use with -H)
  -u send dynamic updates instead of queries
  -v verbose: report the RCODE of each response on stdout

 

 5. 実行結果

mykw# dnsperf -s dti.mykw.jp -d domainlist -l 30

DNS Performance Testing Tool

Nominum Version 1.0.1.0

[Status] Processing input data
[Status] Sending queries (to 2001:2e8:603:0:2:1:0:3d)
[Status] Testing complete

Statistics:

Parse input file:     multiple times
Run time limit:       30 seconds
Ran through file:     12836 times

Queries sent:         25672 queries
Queries completed:    25672 queries
Queries lost:         0 queries

Avg request size:     28 bytes
Avg response size:    175 bytes

Percentage completed: 100.00%
Percentage lost:        0.00%

Started at:           Thu Mar 15 02:04:21 2012
Finished at:          Thu Mar 15 02:04:51 2012
Ran for:              30.113407 seconds

Queries per second:   852.510644 qps

mykw#

 

ちなみに、マルチコアな筐体で動かく場合はコア分並行して実行しないと全力投球できない模様。
そのような場合は screen を使うか、シェルスクリプト等で対応する形になるもよう。