はじめに
2023.11.12追記
現在の最新WSLではブリッジモードやミラーモードというネットワークモードが追加されているのでIPv6を使いたい場合にはそちらをご利用ください。
この手法は旧来のネットワークモードやWindowsサンドボックスでの活用方法もありますが、基本的にはもはや必要のない方法です。
前編ではWSL2はIPv6に接続できないという事実確認と何が解決すれば通信できるのかということを見てきましたが、具体的にWindowsの機能でどこまでできるのかというのをもう少し見ていきたいと思います。
本稿の構成は以下のような構成を考えています。
前編 WSL2がIPv6通信できない理由
中編 現時点のWindows標準機能だけでRAを広告する <-- イマココ
後編 DHCPv6-PDでプレフィクス委譲を受ける
番外 改良スクリプトをタスクスケジューラに登録する
現時点のWindows標準機能だけでRAを広告する
Windowsの標準コマンドラインインタフェースはcmd.exe(古くはcommand.com)ですが、これに置き換わるものとしてPowerShellが登場してからもう随分と時間がたちます。PowerShellにはコマンドレットが用意されていて、これらを駆使することで様々な操作が行えます。筆者はWSLを使い始めてからPowerShellを触るようになったのですが、WSLとWindowsを連携させようと思うとPowerShellがおのずと必要になってきます。
最近のマイクロソフトはドキュメントを数多く提供してくれるのでこれを見ればできることはおおむね把握できます。
NetTCPIP Module | Microsoft Docs
このマニュアルとにらめっこしながら使えそうなものを選んでいきます。
Set-NetIPInterface
New-NetIPAddress
Set-NetRoute
このあたりが使えそうな気がします。
意外にも充実していて、これIPv6使えるようにできるんじゃない?と期待を持たせる内容です。IPv6アドレスの設定やルーティングだけでなく、RA on/off等もこれらのコマンドレットを使えば実現できそうです。RAを広告出来るということは、Windows側のインタフェースに設定を加えればWSL2側は自動設定が出来そうです。
IPv6アドレスを設定する
ひとまず仮のIPv6アドレスで動作を確認していきます。
WSL2を一度起動させて、タスクマネージャなどでvEthernet (WS) が生成されたことを確認してください。
※pro以上のWindowsを使われている方は後ほどWindows Sandbox を使うので予め有効にしておくと手間が省けます。
New-NetIPAddress -IPAddress 2001:db8::1 -PrefixLength 64 -InterfaceAlias 'vEthernet (WSL)' -SkipAsSource $True -PolicyStore ActiveStore;
結果が表示されて設定されたことがわかるかと思います。
オプションのSkipAsSource
は このアドレスをソースルートには使わないというものです。PolicyStore
はこのアドレスの状態でActiveStore
は起動時に有効な情報です。PersistentStore
を指定すると再起動後も有効な情報になります。
ルーター広告を設定する
次にRAを広告してみましょう
Set-NetIPInterface -InterfaceAlias 'vEthernet (WSL)' -AddressFamily IPv6 -Advertising Enabled -AdvertiseDefaultRoute Enabled -Forwarding Enabled;
Advertising
, AdvertiseDefaultRoute
というオプションがあるので両方 Enabledにしてみます。Forwarding
はこのインタフェースがパケットを中継するかどうかなのでホストを跨いで外部やDefault Switchとやり取りするためには Enabled にする必要があります。
設定してみましたが、この時点ではまだ WSL2 を確認してもIPv6アドレスが付けられていません。
Set-NetRoute
にPublish
というオプションがあり、これがNo
の状態だと広告されないとのことなのでYes
にしてみます。
Set-NetRoute -InterfaceAlias 'vEthernet (WSL)' -AddressFamily IPv6 -Publish Yes;
$ ip -6 a show dev eth0
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1280 qdisc mq state UP group default qlen 1000
inet6 2001:db8::215:5dff:fe75:d314/64 scope global dynamic mngtmpaddr
valid_lft forever preferred_lft forever
vEthernet (WSL) に設定した 2001:db8::/64 のアドレスが設定されました。
経路情報も確認してみます。
$ ip -6 route
2001:db8::/64 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
multicast ff00::/8 dev eth0 proto kernel metric 256 pref medium
default via fe80::6da5:25ef:7bf4:e4d2 dev eth0 proto ra metric 1024 expires 1632sec pref medium
デフォルト経路にfe80::6da5:25ef:7bf4:e4d2
(IPv6アドレスは環境ごとに異なります)が設定されています。このアドレスは、ipconfig で確認すると、vEthernet (WSL) につけられたリンクローカルアドレスです。
PS> ipconfig
イーサネット アダプター vEthernet (WSL):
接続固有の DNS サフィックス . . . . .:
IPv6 アドレス . . . . . . . . . . . .: 2001:db8::6da5:25ef:7bf4:e4d2
IPv6 アドレス . . . . . . . . . . . .: 2001:db8::1
一時 IPv6 アドレス. . . . . . . . . .: 2001:db8::3cd2:35b0:3191:bead
リンクローカル IPv6 アドレス. . . . .: fe80::191a:25cf:6053:999%24
リンクローカル IPv6 アドレス. . . . .: fe80::3cd2:35b0:3191:bead%24
リンクローカル IPv6 アドレス. . . . .: fe80::6da5:25ef:7bf4:e4d2%24 <--- default と同じアドレス
リンクローカル IPv6 アドレス. . . . .: fe80::c5a7:ad45:94d8:b7d0%24
IPv4 アドレス . . . . . . . . . . . .: 172.28.0.1
サブネット マスク . . . . . . . . . .: 255.255.240.0
デフォルト ゲートウェイ . . . . . . .:
つまり、WSL2のデフォルトゲートウェイにWindowsホストが指定できています。これでWSL2にIPv6アドレスが設定され、デフォルトゲートウェイも設定されました。しかし、リンクローカルアドレスが4つもありますね。どうやらSet-NetRoute
した際に対象の経路を指定しなかったのでリンクローカルアドレスまで広告してしまっているようです。オプションに-DestinationPrefix
を指定した方がよさそうです。
これでWSL2からのパケットが外へ出ていけるようになりました。逆方向にパケットが流入できるようになると通信が可能になります。もう一息ですね。
Windows SandboxとIPv6で通信してみる
いきなりWindowsの外部と通信するのはハードル高いので、まずは仮想マシン同士で通信させてみましょう。(といっても、WSL2以外の仮想マシンを起動できるのはWindowsの品目がPro以上に限られるので Home の方は申し訳ありませんが雰囲気だけ味わってください。次回後編ではPCの外部との通信を試みます。)Hyper-Vインスタンスでも構いませんが、手軽なところでWindows Sandboxを使います。Windowsサンドボックスを有効にしていない場合はWindowsの機能の有効化または無効化
から有効にしてください。
Sandboxを起動すると vEthernet (Default Switch) ができるので一度起動させてipconfig等で仮想インタフェースが作成されていることを確認してください。vEthernet (Default Switch)が有効になったら、先ほどの vEthernet (WSL) と同じ設定を行います。IPv6アドレスは 2001:db8:0:1::/64
にして、一つずらします。
New-NetIPAddress -IPAddress 2001:db8:0:1::1 -PrefixLength 64 -InterfaceAlias 'vEthernet (Default Switch)' -SkipAsSource $True -PolicyStore ActiveStore;
Set-NetIPInterface -InterfaceAlias 'vEthernet (Default Switch)' -AddressFamily IPv6 -Advertising Enabled -AdvertiseDefaultRoute Enabled -Forwarding Enabled -PassThru;
Set-NetRoute -InterfaceAlias 'vEthernet (Default Switch)' -AddressFamily IPv6 -Publish yes;
-PassThru というのは処理結果を標準出力に出力するオプションです。PowerShellのコマンドレットは基本非同期処理なので、このオプションをつけていないと処理が終わる前に次の処理へとど んどんすすんで行ってしまいます。この場合インタフェースの広告設定が完了してからNetRouteのpublish指定をしたいので追記しています。
これで、SandboxにもWSL2同様にIPv6アドレスがつきました。WSL2はip -6 a
, Sandboxはipconfig
でお互いのアドレスを調べて通信してみましょう。
$ ping 2001:db8:0:1:b1c8:1c83:9ca5:1a42
PING 2001:db8:0:1:b1c8:1c83:9ca5:1a42(2001:db8:0:1:b1c8:1c83:9ca5:1a42) 56 データ長(byte)
64 バイト応答 送信元 2001:db8:0:1:b1c8:1c83:9ca5:1a42: icmp_seq=1 ttl=127 時間=3.34ミリ秒
64 バイト応答 送信元 2001:db8:0:1:b1c8:1c83:9ca5:1a42: icmp_seq=2 ttl=127 時間=3.82ミリ秒
64 バイト応答 送信元 2001:db8:0:1:b1c8:1c83:9ca5:1a42: icmp_seq=3 ttl=127 時間=1.75ミリ秒
64 バイト応答 送信元 2001:db8:0:1:b1c8:1c83:9ca5:1a42: icmp_seq=4 ttl=127 時間=5.46ミリ秒
> ping 2001:db8::215:5dff:feac:a075
Pinging 2001:db8::215:5dff:feac:a075 with 32 bytes of data:
Reply from 2001:db8::215:5dff:feac:a075: time=6ms
Reply from 2001:db8::215:5dff:feac:a075: time=2ms
Reply from 2001:db8::215:5dff:feac:a075: time=1ms
Reply from 2001:db8::215:5dff:feac:a075: time=2ms
双方から通信できているようですね。
おわりに
Hyper-Vスイッチの各インタフェースにIPv6
アドレスをつけてRAを広告することで、WSL2を含む各仮想インスタンスに対してIPv6アドレスとデフォルトゲートを設定することが出来ました。ただ、これだけでは仮想インスタンス同士とWindowsホストとの間で通信しているだけです。この先外部との通信を実現していかないといけません。
一つの方法はWindowsホストが接続されているルータが、IPv6アドレスの経路を自由に書けるような機材(cisco や allied, yamaha, nec等)であればWindows以下に委譲するプレフィクスを決めてルータに設定すれば使えるようになります。そういう環境の方であればここまでの説明であとはなんとか出来ると思います。
次のステップとしては、上流ルータから DHCPv6-PD でプレフィクス委譲を受けて仮想スイッチに分配してみたいと思います。