久しぶりにKVMで遊ぶ
March 25, 2022
機材 #
- ECS LIVA
- Debian 11 (bullseye)を最小構成でインストール
準備 #
# apt install sudo
# usermod -aG sudo (俺)
$ echo 'Apt::Install-Recommends "false";' | sudo tee -a /etc/apt/apt.conf.d/99local
$ echo 'Apt::Install-Suggests "false";' | sudo tee -a /etc/apt/apt.conf.d/99local
$ sudo apt install qemu-system qemu-utils libvirt-clients libvirt-daemon-system virtinst
$ sudo usermod -aG libvirt (俺)
$ sudo apt install bridge-utils
ブリッジを作る #
auto br0
iface br0 inet static
bridge_ports enp3s0
bridge_stp off
bridge_waitport 0
bridge_fd 0
address 192.168.xxx.xxx
netmask 255.255.255.0
gateway 192.168.xxx.xxx
nameserver 192.168.xxx.xxx
KVMでOPNsenseを動かす #
参考: Installing OPNsense firewall on KVM
$ bunzip2 OPNsense-22.1.2-OpenSSL-nano-amd64.img.bz2
$ qemu-img convert -f raw -O qcow2 OPNsense-22.1.2-OpenSSL-nano-amd64.img opnsense.qcow2
$ qemu-img resize opnsense.qcow2 8G
$ sudo mv opnsense.qcow2 /var/lib/libvirt/images/
opnsense.xmlを作成
<domain type='kvm'>
<name>opnsense</name>
<memory unit='MiB'>1024</memory>
<currentMemory unit='MiB'>1024</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64'>hvm</type>
<boot dev='hd'/>
</os>
<features><acpi/><apic/><pae/></features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type='pci' index='0' model='pci-root'/>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none'/>
<source file='/var/lib/libvirt/images/opnsense.qcow2'/>
<target dev='vda' bus='virtio'/>
</disk>
<interface type='bridge'>
<source bridge='br0'/>
<model type='virtio'/>
<target dev='vnet0'/>
<alias name='net0'/>
</interface>
<serial type='pty'><target port='0'/></serial>
<console type='pty'><target port='0'/></console>
<memballoon model='none'></memballoon>
</devices>
</domain>
$ sudo virsh define opnsense.xml
$ sudo virsh list --all
$ sudo virsh start opnsense
$ sudo virsh console opnsense
$ sudo virsh autostart opnsense
ゲストから外部へのIPv6の通信が通らない? #
症状 #
アップデートしようとすると下記のようになる
***GOT REQUEST TO CHECK FOR UPDATES***
Currently running OPNsense 22.1.4 (amd64/OpenSSL) at Thu Mar 24 22:57:56 JST 2022
Fetching changelog information, please wait... fetch: transfer timed out
fetch: /usr/local/opnsense/changelog/changelog.txz appears to be truncated: 0/244144 bytes
Updating OPNsense repository catalogue...
ゲストからDNSサーバにdrillしようとすると固まる
# drill @2001:240::13
Error: error sending query: Could not send or receive, because of network error
ホストを再起動してからしばらくは繋がっている(pingやdrillに返事がある)ように見える
-
networking - IPv6 connectivity lost on KVM guest after 20 minutes - Server Fault
- IPv6のゲートウェイがリンクローカルアドレスになっている環境だとNG?
- うちの環境は ER-Xでndppdを動かしている
ブリッジのかわりにmacvtapを使ってみる #
macvtapを使うとゲスト~ホスト間で通信できないので、内部ネットワークを作る
DHCPサーバは無効にしている(でもdnsmasqは要るみたい)
<network>
<name>host-to-guest-manual</name>
<ip address='192.168.254.1' netmask='255.255.255.0'>
</ip>
</network>
$ sudo apt install dnsmasq
$ sudo virsh net-define host-to-guest-manual.xml
$ sudo virsh net-autostart host-to-guest-manual
$ sudo virsh net-start host-to-guest-manual
$ sudo virsh edit opnsense
下記を追加
<interface type='network'>
<source network='host-to-guest-manual'/>
<model type='virtio'/>
</interface>
ゲストを一旦シャットダウンしてから起動
$ sudo virsh shutdown opnsense
$ sudo virsh start opnsense
ゲスト側で固定アドレスを振る(192.168.254.x)
ゲスト起動後、IPv6で外部にアクセスできるようになるまで数分かかる
なんか遅い気がする #
$ sudo virsh edit opnsense
CPUの割り当てを増やしてみる
<vcpu placement='static'>2</vcpu>
CPUをqemu64からhost-passthroughに変えてみる
<cpu mode='host-passthrough'/>
WireGuardのスループットが20Mbpsぐらいだったのが70Mbpsぐらいまで上がったのでたぶんどちらかが効いてる
Dockerでpi-holeを動かす #
KVM関係ないけども
$ sudo apt install curl gnupg
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io docker-compose
$ sudo usermod -aG docker (俺)
$ exit
macvtapのために入れたdnsmasqは自動起動しないようにしておく(53/udp,53/tcpを使うので)
$ sudo systemctl stop dnsmasq.service
$ sudo systemctl disable dnsmasq.service
GitHub - pi-hole/docker-pi-hole: Pi-hole in a docker container
$ mkdir ~/pihole
$ cd ~/pihole
$ wget https://raw.githubusercontent.com/pi-hole/docker-pi-hole/master/docker-compose.yml.example -O docker-compose.yml
docker-compose.yml
を編集
- 53/tcp, 53/udpのホスト側アドレスを指定(ホストの別のアドレスでdnsmasqが動いているので0.0.0.0:53にはbindできないため)
- 67/udpをコメントアウト(DHCPサーバとしては使用しないため)
ports:
- "192.168.xxx.xxx:53:53/tcp"
- "192.168.xxx.xxx:53:53/udp"
# - "67:67/udp"
- "80:80/tcp"
$ docker-compose up -d
$ docker logs pihole | grep random
Assigning random password: XXXXXXXX
ブラウザでhttp://192.168.xxx.xxx/admin/
にアクセスし、上記パスワードでログイン
OPNsenseのVMと通信させるのが面倒なので、こいつもVMにしてその中でDockerを動かすことにする
物理NIC(enp3s0)を元にしたmacvlanインターフェースを生やしてやるとよさそう
auto macvlan0
iface macvlan0 inet static
address 192.168.***.***
netmask 255.255.255.0
gateway 192.168.***.***
nameserver 192.168.***.***
pre-up ip link set enp3s0 up
pre-up ip link add dev $IFACE link enp3s0 type macvlan mode bridge
post-down ip link delete dev $IFACE type macvlan
iface macvlan0 inet6 auto
privext 2
VMでWireGuardを動かす #
参考: WireGuard VPN Road Warrior Setup – EmanuelDuss.ch
WireGuardで接続したクライアントはこのマシンのアドレスにNAT(masquerade)して外に出て行く寸法
#!/usr/bin/env bash
VPNIF="wg0"
LANIF="enp1s0"
nft add table ip filter
nft add chain ip filter FORWARD { type filter hook forward priority 0 \; policy drop \; }
nft insert rule ip filter FORWARD iifname "$VPNIF" oifname "$LANIF" accept
nft insert rule ip filter FORWARD iifname "$LANIF" oifname "$VPNIF" ct state related,established accept
nft add table ip6 filter
nft add chain ip6 filter FORWARD { type filter hook forward priority 0 \; policy drop \; }
nft insert rule ip6 filter FORWARD iifname "$VPNIF" oifname "$LANIF" accept
nft insert rule ip6 filter FORWARD iifname "$LANIF" oifname "$VPNIF" ct state related,established accept
nft add table ip wireguard-nat
nft -- add chain ip wireguard-nat prerouting { type nat hook prerouting priority -100 \; }
nft add chain ip wireguard-nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule ip wireguard-nat postrouting oifname "$LANIF" masquerade
nft add table ip6 wireguard-nat
nft -- add chain ip6 wireguard-nat prerouting { type nat hook prerouting priority -100 \; }
nft add chain ip6 wireguard-nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule ip6 wireguard-nat postrouting oifname "$LANIF" masquerade
#!/usr/bin/env bash
VPNIF="wg0"
LANIF="enp1s0"
nft --handle list chain ip filter FORWARD | grep "iifname.*$VPNIF" | awk '{ print $NF }' | while read handle
do
nft delete rule ip filter FORWARD handle "$handle"
done
nft --handle list chain ip6 filter FORWARD | grep "iifname.*$VPNIF" | awk '{ print $NF }' | while read handle
do
nft delete rule ip6 filter FORWARD handle "$handle"
done
nft delete chain ip6 filter FORWARD
nft delete table ip wireguard-nat
nft delete table ip6 wireguard-nat
/etc/network/interfacesでprivext 2にするとVPNクライアントからIPv6でインターネットに出られなくなる #
- scope global temporary dynamicなipv6アドレスに外からpingが通らない
- 前述の通りmacvtapを使っている環境
- Flying Penguin Technologies: IPv6 with macvtap and libvirt
-
linux - How to configure macvtap to let it pass multicast packet correctly? - Super User
- デフォルトだとマルチキャストがゲストまで届かない?
- そうするとneighbor solicitationが届かないのでは
<interface>
にtrustGuestRxFilters='yes'
を付けてあげる- VMをシャットダウンしてから起動
- デフォルトだとマルチキャストがゲストまで届かない?