pikesaku’s blog

個人的なプログラム勉強メモです。記載内容について一切の責任は持ちません。

libvirtのネットワーク管理

libvirtは構成定義ファイルに従い、仮想ネットワークを作成する。
KVMインストールデフォルトの状態では、defaultネットワークが設定される。
これを手動で設定することで、どのようなに実現されているか理解する。
 
 
インストールデフォルトの状態
 

仮想ネットワーク構成定義
# virsh net-dumpxml default
<network>
  <name>default</name>
  <uuid>74b8baf4-6ebb-41d3-8cea-5b42efad0b89</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='virbr0' stp='on' delay='0'/>
  <mac address='52:54:00:d0:13:d6'/>
  <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>
# 

/etc/libvirt/qemu/networks/default.xml ファイルの中身と同じ。
libvirtは、これをインプットとし仮想ネットワークを生成している。

ネットワークデバイス
# ip -d link ※-dオプションをつけるとタイプ(tun/bridge/)も表示される。
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0 addrgenmode eui64 
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 08:00:27:db:6e:6a brd ff:ff:ff:ff:ff:ff promiscuity 0 addrgenmode eui64 
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT qlen 1000
    link/ether 52:54:00:d0:13:d6 brd ff:ff:ff:ff:ff:ff promiscuity 0 
    bridge forward_delay 200 hello_time 200 max_age 2000 addrgenmode eui64 
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT qlen 1000
    link/ether 52:54:00:d0:13:d6 brd ff:ff:ff:ff:ff:ff promiscuity 1 
    tun 
    bridge_slave addrgenmode eui64 
# ip -d a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0 
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:db:6e:6a brd ff:ff:ff:ff:ff:ff promiscuity 0 
    inet 192.168.43.197/24 brd 192.168.43.255 scope global dynamic enp0s3
       valid_lft 3229sec preferred_lft 3229sec
    inet6 fe80::a00:27ff:fedb:6e6a/64 scope link 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
    link/ether 52:54:00:d0:13:d6 brd ff:ff:ff:ff:ff:ff promiscuity 0 
    bridge forward_delay 200 hello_time 200 max_age 2000 
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 1000
    link/ether 52:54:00:d0:13:d6 brd ff:ff:ff:ff:ff:ff promiscuity 1 
    tun 
    bridge_slave 
# 

ネットワークデバイスにはTypeがあり。
virbr0はTypeがbridge
virbr0-nicはTypeがtun

tunについては、以下URL参照。
iproute2 cheat sheet
type tunはユーザースペースのプログラムが使える仮想ネットワークデバイスファイル。
仮想マシンのネットワーク通信に利用。ソケットのようなもの。
ソケットはtcp/udpポート番号指定。tun/tapは、より低レイヤーの通信を扱える。
type tunは更にtapとtunに分かれる。
tapはL2フレームの送受信をするデバイスファイル
tunはIPパケットの送受信をするデバイスファイル

仮想ブリッジ
# brctl show
bridge name	bridge id		STP enabled	interfaces
virbr0		8000.525400d013d6	yes		virbr0-nic
# 
iptables
# iptables -L -n -v
Chain INPUT (policy ACCEPT 1617 packets, 998K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:67
    0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:67

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      virbr0  0.0.0.0/0            192.168.122.0/24     ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  virbr0 *       192.168.122.0/24     0.0.0.0/0           
    0     0 ACCEPT     all  --  virbr0 virbr0  0.0.0.0/0            0.0.0.0/0           
    0     0 REJECT     all  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
    0     0 REJECT     all  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT 780 packets, 966K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     udp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            udp dpt:68
# iptables -L -n -t nat -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  *      *       192.168.122.0/24     224.0.0.0/24        
    0     0 RETURN     all  --  *      *       192.168.122.0/24     255.255.255.255     
    0     0 MASQUERADE  tcp  --  *      *       192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
    0     0 MASQUERADE  udp  --  *      *       192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
    0     0 MASQUERADE  all  --  *      *       192.168.122.0/24    !192.168.122.0/24    
dnsmasq
# ps -C dnsmasq -o command
COMMAND
/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
# 

 
 
defaultネットワークを無効化した状態
 
以下コマンドでefaultネットワークを無効化

# virsh net-destroy default
Network default destroyed
ネットワークデバイス
# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 08:00:27:db:6e:6a brd ff:ff:ff:ff:ff:ff
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
	       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:db:6e:6a brd ff:ff:ff:ff:ff:ff
    inet 192.168.43.197/24 brd 192.168.43.255 scope global dynamic enp0s3
       valid_lft 3387sec preferred_lft 3387sec
    inet6 fe80::a00:27ff:fedb:6e6a/64 scope link 
       valid_lft forever preferred_lft forever
# 
仮想ブリッジ
# brctl show
bridge name	bridge id		STP enabled	interfaces
#
iptables
# iptables -L -n -v
Chain INPUT (policy ACCEPT 49 packets, 3336 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 26 packets, 3624 bytes)
 pkts bytes target     prot opt in     out     source               destination         
# iptables -L -n -t nat -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
# 
dnsmasq
# ps -C dnsmasq -o command
COMMAND
# 

 
 
手動設定
 

仮想ブリッジ(virbr0)作成

brctlコマンドで作るかと思いきや、brctlコマンドではMACアドレスが指定できないっぽい。ipコマンドで作っていると想定される。

# ip link add virbr0 type bridge
# ip link set dev virbr0 address 52:54:00:d0:13:d6
# ip addr add 192.168.122.1/24 brd 192.168.122.255 dev virbr0
# brctl setfd virbr0 2

→STP関連設定?
http://www.tldp.org/HOWTO/BRIDGE-STP-HOWTO/set-up-the-bridge.html
Sets the forwarding delay time. The forwarding delay time is the time spent in each of the Listening and Learning states before the Forwarding state is entered.

これでdefaultのvirbr0とip -d link・ip -d aコマンドの結果が同じになる。

# ip -d link show virbr0
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT qlen 1000
    link/ether 52:54:00:d0:13:d6 brd ff:ff:ff:ff:ff:ff promiscuity 0 
    bridge forward_delay 200 hello_time 200 max_age 2000 addrgenmode eui64 
# ip -d a show virbr0
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
    link/ether 52:54:00:d0:13:d6 brd ff:ff:ff:ff:ff:ff promiscuity 0 
    bridge forward_delay 200 hello_time 200 max_age 2000 
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
#
TUN/TAPデバイスv(irb0-nic)生成

次にvirb0-nicを作る。typeはtun(tun/tap)。
http://baturin.org/docs/iproute2/#Tun%20and%20Tap%20devices

以下で作成

# ip tuntap add dev virbr0-nic mode tap
# ip link set dev virbr0-nic address 52:54:00:d0:13:d6 master virbr0
# ip link set virbr0 up
# ip link set virbr0-nic up

※tapを指定する。tunで作ると、ip -d aコマンドの結果が異なった。(POINTOPOINTがついた)

# ip -d a show virbr0-nic
13: virbr0-nic: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 500
    link/none  promiscuity 0 
    tun 

※削除する時は、以下の様にmodeも指定する必要あり。

ip tuntap add dev virbr0-nic mode tap

これでdefaultのvirbr0とip -d link・ip -d aコマンドの結果が同じになる。

# ip -d link show dev virbr0-nic
6: virbr0-nic: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT qlen 1000
    link/ether 52:54:00:d0:13:d6 brd ff:ff:ff:ff:ff:ff promiscuity 1 
    tun 
    bridge_slave addrgenmode eui64 
# ip -d a show dev virbr0-nic
6: virbr0-nic: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 1000
    link/ether 52:54:00:d0:13:d6 brd ff:ff:ff:ff:ff:ff promiscuity 1 
    tun 
    bridge_slave 
# 

※IFをupしないと、virbr0-nicのqdiscのパラメタがnoopになった。以下URLを参考にしたが、分からず。IFをupしたら、pfifo_fastになった。
 http://inokara.hateblo.jp/entry/2016/02/14/191853

※NO-CARRIERでが異なるが、以下URLを見るとケーブルがつながってない状態を示すよう。これは問題なし。
 http://blog.goo.ne.jp/takuminews/e/3ada9ac4a3bfaf6d9f35b284a9b6eb58

dnsmasq構成

そもそもdnsmasqとは

dnsmasqで始めるプライベートDNSサーバ - GeekFactory
→手軽なDNS/DHCPサーバ
→hostsファイルをゾーンファイルにできる。
→管理外ドメインのクエリを受け付け、OSリゾルバ設定に従い代理応答する。

dnsmasqでDNSおよびDHCPサービスを強化する | OSDN Magazine
dhcpを有効にするには、dhcp-range=にレンジ記載する。
→DGWをDHCPクライアントに提供するには、dhcp-option=3,DGWのIP。3がDGWを意味するオプション
→同一ホストに常に同じ名前/IPを割り当てたい時。dchp-host=MACアドレス,IPアドレス,名前

kvmによるdnsmasqの起動状態は

# systemctl list-unit-files | egrep dnsmasq
dnsmasq.service                        disabled
# ps -C dnsmasq -o command=
/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
# 

自動起動は無効。libvirtが起動してるとよう。
NWごとに起動される。設定ファイルは/var/lib/libvirt/dnsmasq/NW名.conf
起動オプションの意味は以下の通り。

・--conf-file
コンフィグファイルの指定。デフォルトは/etc/dnsmasq.conf
・--leasefile-ro
リースファイルは使わない。dhcp-scriptで指定されたスクリプトでリース状況を管理する場合などに指定されるオプション
・--dhcp-script
DHCPリース・破棄するスクリプト

コンフィグファイルとスクリプトが重要そう。
内容を確認する。

conf-fileの内容
# cat /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
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-lease-max=253
dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
# 

・コメント部分
libvirtが自動生成したファイルだから変更するな!変更する時は、net-edit使え。
・strict-order
resolv.confの順番をしっかり守れ。守らないと意図しないサーバが応答してしまうケースを想定?
・except-interface=lo
ループバックデバイスではlistenしない。
・bind-dynamic
動的に生成されたインターフェースでもlistenする。libvirtが作るインターフェースでlistenするってことでしょう。
・interface
ここで指定されたインターフェースだけでlistenする。(loは自動的に追加される?)。
基本的に内部NW以外では動作させないってことでしょう。(ホストサーバの外部ホストと通信するIFではlistenさせない。)
dhcp-range
DHCPレンジ
dhcp-no-override
よく分からない。pxebootで使うDHCPサーバとfilenameの情報の扱いを制御
dhcp-lease-max
dhcpリースの上限する。デフォルトは1000
dhcp-hostsfile
dhcp-hostsオプションのファイル保存版。
ファイル変更でDHCP割り当て変更可能にする。(dnsmasqの再起動不要・SIGHUPシグナル受信時に再読み込み)
仮想マシン作成時は以下となった。
・addn-hosts
追加の名前解決用ファイル
※上記はmanより調査

スクリプトの内容
# file /usr/libexec/libvirt_leaseshelper 
/usr/libexec/libvirt_leaseshelper: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=7c1aff42497cf9a60d3db90e8a6391c4b7f30626, stripped
# 

バイナリファイルだった。。。

残り調査項目

★virbr0-nicとdnsmasqの関係性有無について調査
iptablesによるNAT実装
★実際に仮想マシンを接続して通信確認
★dnsmasqを活用したPXEBoot