NetBSD Advent Calendar 2021 1日目の記事です。今年もNetBSDの記事を増やして行きましょう!
今日のお話は少し前に私がハマった、IPv6/IPv6の接続優先度の話をしようと思います。
QEMU+NetBSDではIPv6接続が優先される?
QEMU環境上にNetBSD-9をインストールして動かしていた時の話です。 pkg_add
でパッケージをインストールしようとすると、妙に時間がかかる現象に遭遇してしまいました。
# echo $PKG_PATH
http://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/x86_64/9.2/All
# pkg_add -v bash
...
Running install with POST-INSTALL for bash-5.1.8nb3.
bash-5.1.8nb3: adding /usr/pkg/bin/bash to /etc/shells
Package bash-5.1.8nb3 registered in /usr/pkg/pkgdb/bash-5.1.8nb3
1877.82s real 3.01s user 4.52s system
約14分くらいかかっているようです…。
# # 1秒だとrealは2.14sくらい。
# time sleep 1
2.14s real 0.08s user 0.00s system
#
# bc
1877.82 / 2.14
877
877 / 60
14
tcpdump
で確認してみると、どうやらIPv6での接続を試したのち、IPv4接続にフォールバックされるという動作になっていました。
# tcpdump -i wm0 port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wm0, link-type EN10MB (Ethernet), capture size 262144 bytes
02:16:55.924838 IP6 fec0::1a6b:e5d8:a4b4:2bb7.65532 > 2a04:4e42::262.http: Flags [S], seq 2490812735, win 32768, options [mss 1440,nop,wscale 3,sackOK,TS val 1 ecr 0], length 0
...
IPv4での接続を優先するよう設定する
VirtualBox等の他の仮想化環境ではIPv6が優先される現象に遭遇していないため、慌てて設定方法を調査する感じになりました。
Linuxではgetaddrinfo(3)でIPv4/IPv6のどちらを優先して接続を試すかを設定できるため、NetBSDでも同等の方法だろうと予想していました。が、BSD系だとip6addrctl(8)でIPv4/IPv6の優先ポリシーを設定する手順となっていました。
私が今まで設定していなかっただけで、かなり前から提供されているツールのようです。
設定内容はシンプルで、以下の内容を /etc/rc.conf
に追加+再起動でOKです。
ip6addrctl=YES
ip6addrctl_policy=ipv4_prefer
IPv4が優先して利用される
ip6addrctl
の設定投入後、改めて pkg_add
を試してみます。
今度はサクッとパッケージがインストールされています。
# time pkg_add -v bash
...
Running install with POST-INSTALL for bash-5.1.8nb3.
bash-5.1.8nb3: adding /usr/pkg/bin/bash to /etc/shells
Package bash-5.1.8nb3 registered in /usr/pkg/pkgdb/bash-5.1.8nb3
12.39s real 3.16s user 4.32s system
念のため tcpdump
で確認すると、IPv4で接続されていることが分かります。
# tcpdump port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wm0, link-type EN10MB (Ethernet), capture size 262144 bytes
04:20:41.475156 IP 10.0.2.15.65535 > 151.101.1.6.http: Flags [S], seq 1157240960, win 32768, options [mss 1460,nop,wscale 3,sackOK,TS val 1 ecr 0], le
ngth 0
NetBSD/FreeBSDでip6addrctlのデフォルト設定を比較してみる
ここまでで一連の対応手順を調べてみたのですが、どうやらBSD系では ip6addrctl
というツールでIPv4/IPv6の接続優先ポリシーを設定するようです。
(Linux(というか glibc
)では /etc/gai.conf
で設定するようですね)
ふと「これQEMU+FreeBSDでも同じ挙動になるのだろうか?」と思い確認してみました。
すると、FreeBSDでは特に何もしなくてもIPv4での接続が優先されているような挙動になっています。
これは何が違うのだろう?と思い、 ip6addrctl show
の結果を比較すると以下のようになっていました。
NetBSD,FreeBSD共に、 fecd::/64
というサイトローカルアドレス(※)が振られています。
※: /10
ではないけどサイトローカルアドレスなはず…。
$ # FreeBSD環境での確認結果。
$ uname -a
FreeBSD fbsdvm01 13.0-RELEASE FreeBSD 13.0-RELEASE #0 releng/13.0-n244733-ea31abc261f: Fri Apr 9 04:24:09 UTC 2021 root@releng1.nyi.freebsd.org:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64
$
$ ifconfig em0 | egrep 'em0|inet'
em0: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
inet6 fe80::5054:ff:fe12:3456%em0 prefixlen 64 scopeid 0x1
inet6 fec0::5054:ff:fe12:3456 prefixlen 64 autoconf
inet 10.0.2.15 netmask 0xffffff00 broadcast 10.0.2.255
$
$ ip6addrctl show
Prefix Prec Label Use
::1/128 50 0 0
::/0 40 1 3
::ffff:0.0.0.0/96 35 4 0
2002::/16 30 2 0
2001::/32 5 5 0
fc00::/7 3 13 0
::/96 1 3 0
fec0::/10 1 11 2
3ffe::/16 1 12 0
$ # NetBSDでの確認結果。
$ uname -a
NetBSD nbsdvm01 9.2 NetBSD 9.2 (GENERIC) #0: Wed May 12 13:15:55 UTC 2021 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/amd64/compile/GENERIC amd64
$
$ ifconfig wm0 | egrep 'wm0|inet'
wm0: flags=0x8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 10.0.2.15/24 broadcast 10.0.2.255 flags 0x0
inet6 fe80::88e4:be83:7b9e:c844%wm0/64 flags 0x0 scopeid 0x1
inet6 fec0::f911:3fa9:73e:3cf7/64 flags 0x0
$
$ ip6addrctl show
no source-address-selection policy is installed
以下のように、FreeBSDでの ip6addrctl show
ではデフォルトでIPv4/IPv6優先ポリシーが設定されています。
ほっといたらIPv4運用に影響するIPv6の話というPDFのスライド20枚目の解説を基に設定内容を読み解くと、 ::ffff:0.0.0.0/96 35 4 0
でIPv4接続のポリシーが追加されています。
この設定ポリシーでは、IPv4の接続がIPv6( fec0::/10
)よりも優先されていることが分かります。
$ ip6addrctl show
Prefix Prec Label Use
::1/128 50 0 0
::/0 40 1 3
::ffff:0.0.0.0/96 35 4 0
2002::/16 30 2 0
2001::/32 5 5 0
fc00::/7 3 13 0
::/96 1 3 0
fec0::/10 1 11 2
3ffe::/16 1 12 0
これに対し、NetBSDでは ipv6addrctl show
では特に接続優先ポリシーは設定されていないため、この部分の差異が振る舞いの違いとして現れるということですね。
$ ip6addrctl show
no source-address-selection policy is installed
QEMU側で設定する方法
もう一つの対応方法として、QEMU側でIPv4を優先する(というか、IPv6を無効化しておく)という方法もあります。
QEMUの起動オプションで -net user,ipv6=off
とすることで、QEMU側でIPv6を無効化することができます。
(でもできれば ip6addrctl
で接続ポリシーを設定する方法を採りたいところではありますね…)
$ qemu-system-x86_64 \
-m 256M \
-boot order=c \
-net nic \
-net user,hostfwd=tcp::2222-:22 \
-hdd disk/nbsd.img
│
│-net userオプションを以下のように変更する。
↓
$ qemu-system-x86_64 \
-m 256M \
-boot order=c \
-net nic \
-net user,ipv6=off,hostfwd=tcp::2222-:22 \
-hdd disk/nbsd.img
まとめ
NetBSDでip6addrctl(8)によりIPv4/IPv6の優先設定を変更する方法を紹介しました。Linuxの /etc/gai.conf
と設定方法が異なることもあり、備忘録も兼ねて記事を作成してみました。