LoginSignup
1
0

More than 1 year has passed since last update.

QEMU+NetBSDではipv6addrctlで接続ポリシーを設定しよう

Last updated at Posted at 2021-11-30

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 と設定方法が異なることもあり、備忘録も兼ねて記事を作成してみました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0