私は、Ubuntu TrustyマシンでKVM + Libvirtを実行して小さな仮想マシンを管理し、標準のNetworkManagerを使用して通常のネットワークに接続しています。
ホストからDNS経由で仮想マシンにアクセスできるようにしたい。
Libvirtは仮想プライベートサブネット(192.168.122.0/24)を使用します。NATを使用して、eth0のブリッジ(virbr0)を介して他の地域にアクセスします。 DnamasqはDHCP + DNSをこの仮想ネットワークに割り当てます。
これは仮想ネットワークのlibvirt設定です:
<network>
<name>default</name>
<uuid>400c59ff-c276-4154-ab73-9a8a8d1c6be3</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:f4:bd:37'/>
<domain name='kvm'/>
<dns forwardPlainNames='no'>
<forwarder addr='127.0.1.1'/>
<Host ip='192.168.122.1'>
<hostname>Host</hostname>
<hostname>Host.kvm</hostname>
</Host>
</dns>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
Libvirtは、192.168.122.1:53でリッスンするdnsmasqインスタンスを開始します。これは、.knvに対するすべての要求に応答し、他のすべての要求をホストに転送します。このdnsmasq設定はlibvirtによって自動的に生成されます:
/ var/lib/libvirt/dnsmasq/default.conf
##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
##OVERWRITTEN AND LOST. Changes to this configuration should be made using:
## virsh net-edit default
## or other application using the libvirt API.
##
## dnsmasq conf file created by libvirt
strict-order
user=libvirt-dnsmasq
no-resolv
server=127.0.1.1
domain=kvm
expand-hosts
domain-needed
local=//
pid-file=/var/run/libvirt/network/default.pid
except-interface=lo
bind-dynamic
interface=virbr0
dhcp-range=192.168.122.2,192.168.122.254
dhcp-no-override
dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases
dhcp-lease-max=253
dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
NetworkManagerには、127.0.1.1:53でリッスンするdnsmasqのインスタンスがあります。これは、ホストが外部DHCPシステムによって割り当てられたDNSサーバーに渡す前に、すべてのDNSクエリに使用します。
ホストUbuntuシステムでlibvirtのdnsmasqを使用するために、NetworkManagerのdnsmasqがドメインkvmに192.168.122.1を使用するように指定します。
/ etc/NetworkManager/dnsmasq.d/libvirt.conf
server=/kvm/192.168.122.1
そして、これはほとんどの部分で機能します...
me@Host ~ $ ps aufx
...cut...
root 11010 0.2 0.0 342084 6348 ? Ssl 10:59 0:00 NetworkManager
root 11018 0.0 0.0 10232 3732 ? S 10:59 0:00 \_ /sbin/dhclient -d -sf /usr/lib/NetworkManager/nm-dhcp-client.action -pf /run/sendsigs.omit.d/network-manager.dhclient-eth0.pid -lf /var/lib/NetworkManager/dhclient-b8043
nobody 11228 0.0 0.0 32252 1564 ? S 10:59 0:00 \_ /usr/sbin/dnsmasq --no-resolv --keep-in-foreground --no-hosts --bind-interfaces --pid-file=/run/sendsigs.omit.d/network-manager.dnsmasq.pid --listen-address=127.0.1.1 --
root 11033 1.0 0.1 513356 15160 ? Sl 10:59 0:01 /usr/sbin/libvirtd -d
libvirt+ 11085 0.0 0.0 28208 948 ? S 10:59 0:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf
me@Host ~ $ Sudo netstat -nulpd | grep dnsmasq
udp 0 0 127.0.1.1:53 0.0.0.0:* 11228/dnsmasq
udp 0 0 192.168.122.1:53 0.0.0.0:* 11085/dnsmasq
udp 0 0 0.0.0.0:67 0.0.0.0:* 11085/dnsmasq
me@Host ~ $ Host test.kvm
test.kvm has address 192.168.122.193
;; connection timed out; no servers could be reached
;; connection timed out; no servers could be reached
しかし、すべてが応答を待機している膨大な数のdnsmasq AAAAクエリを作成します。
me@Host ~ $ Sudo netstat -nulpd | grep dnsmasq
udp 0 0 0.0.0.0:39329 0.0.0.0:* 11228/dnsmasq
udp 0 0 0.0.0.0:2469 0.0.0.0:* 11085/dnsmasq
udp 0 0 0.0.0.0:14805 0.0.0.0:* 11228/dnsmasq
...cut...
udp 0 0 0.0.0.0:51569 0.0.0.0:* 11228/dnsmasq
udp 0 0 0.0.0.0:31091 0.0.0.0:* 11085/dnsmasq
udp 0 0 0.0.0.0:39305 0.0.0.0:* 11085/dnsmasq
me@Host ~ $ Sudo netstat -nulpd | grep dnsmasq | wc -l
131
そして、tcpdumpはそれらが主にAAAAリクエストであることを示しています。
me@Host ~ $ Sudo tcpdump -vni any udp port 53
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
11:04:49.453864 IP (tos 0x0, ttl 64, id 56217, offset 0, flags [none], proto UDP (17), length 55)
127.0.0.1.58535 > 127.0.1.1.53: 31275+ A? mysql.kvm. (27)
11:04:49.453948 IP (tos 0x0, ttl 64, id 20062, offset 0, flags [DF], proto UDP (17), length 55)
192.168.122.1.7098 > 192.168.122.1.53: 41491+ A? mysql.kvm. (27)
11:04:49.454013 IP (tos 0x0, ttl 64, id 20063, offset 0, flags [DF], proto UDP (17), length 71)
192.168.122.1.53 > 192.168.122.1.7098: 41491* 1/0/0 mysql.kvm. A 192.168.122.193 (43)
11:04:49.454068 IP (tos 0x0, ttl 64, id 37088, offset 0, flags [DF], proto UDP (17), length 71)
127.0.1.1.53 > 127.0.0.1.58535: 31275* 1/0/0 mysql.kvm. A 192.168.122.193 (43)
11:04:49.454321 IP (tos 0x0, ttl 64, id 56218, offset 0, flags [none], proto UDP (17), length 55)
127.0.0.1.56040 > 127.0.1.1.53: 47999+ AAAA? mysql.kvm. (27)
11:04:49.454381 IP (tos 0x0, ttl 64, id 20064, offset 0, flags [DF], proto UDP (17), length 55)
192.168.122.1.19631 > 192.168.122.1.53: 20542+ AAAA? mysql.kvm. (27)
...cut...
11:05:09.510237 IP (tos 0x0, ttl 64, id 20515, offset 0, flags [DF], proto UDP (17), length 55)
192.168.122.1.19631 > 192.168.122.1.53: 35761+ MX? mysql.kvm. (27)
11:05:09.510237 IP (tos 0x0, ttl 64, id 56674, offset 0, flags [DF], proto UDP (17), length 55)
127.0.0.1.46085 > 127.0.1.1.53: 53641+ AAAA? mysql.kvm. (27)
11:05:09.510315 IP (tos 0x0, ttl 64, id 56675, offset 0, flags [DF], proto UDP (17), length 55)
127.0.0.1.46085 > 127.0.1.1.53: 26166+ MX? mysql.kvm. (27)
11:05:09.510334 IP (tos 0x0, ttl 64, id 20516, offset 0, flags [DF], proto UDP (17), length 55)
192.168.122.1.19631 > 192.168.122.1.53: 4247+ AAAA? mysql.kvm. (27)
11:05:09.510407 IP (tos 0x0, ttl 64, id 56676, offset 0, flags [DF], proto UDP (17), length 55)
127.0.0.1.46085 > 127.0.1.1.53: 49331+ AAAA? mysql.kvm. (27)
11:05:09.510433 IP (tos 0x0, ttl 64, id 20517, offset 0, flags [DF], proto UDP (17), length 55)
192.168.122.1.19631 > 192.168.122.1.53: 63294+ MX? mysql.kvm. (27)
^C
934 packets captured
1857 packets received by filter
0 packets dropped by kernel
/ etc/gai.confでAAAAレコードの優先度を下げてみました
precedence ::ffff:0:0/96 100
IPv6を完全に無効にしてみても/ etc/sysctl.conf:
# Disable IPv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
しかし、AAAA要求はまだ送信されており、名前解決は耐えられないほど遅くなります。
LibvirtまたはNetworkManagerがこれらのリクエストを無視または否定的に応答する方法はあるので、すでに受信したAレコードを使用する前にすべてのリクエストがタイムアウトするのを待つ必要はありませんか?
フォワーダーが構成されている場合、dnsmasqは、明示的なデータがないすべてのDNSクエリを転送します。これには、アクティブなリースを持たない構成済みの静的DHCPクライアントのレコード、IPv6アドレスが明示的に定義されていない限りAAAAレコードなどが含まれます。
これを回避するには、いくつかの方法があります。
ネットワーク定義のフォワーダーエントリを省略してください。仮想ネットワークが本当に分離されていない限り、おそらく望ましくありません。これはlibvirtが現在(2014年12月)AFAIKをサポートしている唯一の可能性です。
Dnsmasqでドメインを「ローカル」として構成します。
domain=local.net,192.168.10.0/24
local=/local.net/
local=/10.168.192.in-addr.arpa/
理論的には、これはdomain=local.net,192.168.10.0/24,local
と省略できますが、 最近修正されたdnsmasqのバグ は失敗します。
libvirtはこれをサポートしていません。この構成を使用するには、OSでブリッジを手動でセットアップし、次のようにlibvirtネットワークを構成する必要があります。
<network>
<name>local</name>
<forward mode='bridge'/>
<bridge name='br0'/>
</network>
この構成でlibvirt仮想ネットワークを作成する必要はありません。VM定義ファイルで<interface 'type=bridge'>
を使用するだけです。
auth-zone
パラメータには、local
と同様の効果があります。しかし、それは私が完全に理解すると主張していない他の含意を持っています。仮想ネットワーク内の名前が外部から解決されることになっている場合は、この構成が望ましいと思います。
domain=local.net
auth-zone=local.net
このセットアップはlibvirtでもサポートされていないため、ブリッジのセットアップと同じ手順を上記と同様に適用する必要があります。