LoginSignup
1
1

WSL2をIPv6ネットワークにND Proxyで接続する/Hyper-Vで???

Last updated at Posted at 2021-10-11

2023.11.12追記
現在の最新WSLではブリッジモードやミラーモードというネットワークモードが追加されているのでIPv6を使いたい場合にはそちらをご利用ください。

WSL2をIPv6ネットワークに接続するでは4回に分けて上流からDHCPv6-PDでプレフィクス委譲をうけてIPv6ネットワークに接続する方法を解説しました。国内家庭用回線ではフレッツ光がかなりの割合を占めるので在宅時にはこの方法で接続可能な方もそれなりにおられるかと思います。しかし、企業内、学内ネットワークがいちクライアントPCに対してプレフィクス委譲してくれることはまれなので、別の方法が必要になります。WSL仮想スイッチを外部接続にするのが一番よさそうな気はするのですが、HCS系のAPIで管理されていて詳細がつかめないものを無理に触るのはどうしても怖くなります。

直接接続できないとなると、次の手法としてはND Proxyを使うことになると思います。

ND Proxyをどうやって実現するか?

一番望ましいのはND Proxyを行うWindows用のプログラムを作る、あるいは探してくるということなのですが残念ながら手が出ませんでした。身近な無線ルーターなどではND Proxyが当たり前のように搭載されていますが、比較的Linuxベースのものが多いですよね?ということはLinuxを使えば実現できそうです。

Windows上でLinuxを使う方法としてWSLが非常にお手軽なツールなのですが、Hyper-VにインストールすればWindowsホストと同じネットワークに簡単に接続できます。今回はたまたまHyper-Vにインストールされていた Rocky Linux を使って検証してみます。

必要なもの

  1. Hyper-V (Windows10 Pro以上)
  2. ndppd
  3. radvd

IPv6スタックはLinuxに標準搭載されているので、neighbor discovery を中継するndppdと、RAを送出するためのradvdの二つがあれば実現できそうです。ndppd, radvdは当該OSのパッケージシステムでインストールしておいてください。

Hyper-V での設定

Rocky Linuxがインストールされている状態から話を進めます。Hyper-VにLinuxディストリが無い場合にはまずインストールしてください。

Hyper-Vマネージャーで仮想スイッチを一つ作成します。仮想スイッチマネージャーから「外部」を選択して仮想スイッチを作成します。名前は「External」とでもしておいてください。

次に、Rocky に接続するネットワークを変更します。
通常はDefault Switchになっていると思いますが、これを先ほどのExternalに変更します。

次に「ハードウェアの追加」から、ネットワークアダプターを追加します。追加するスイッチはWSLです。

これで、eth0がExternal, eth0がWSLに接続されます。起動すると、RockyはIPv4, IPv6ともにWindowsホストと同じネットワークに接続されます。

。。。。。

これでいいじゃん、と思われた方はWSLではなくHyper-VインスタンスのLinuxを使いましょう。その場合WSL仮想スイッチに接続する必要はありません。

しかし、WSLにはHyper-Vインスタンスにはない利便性があるのでこれはこれで使いたいものです。そう思われた方は次へと進みましょう。

radvdで経路を広告する

RockyがWindowsホスト同様の物理ネットワークに接続され、さらにWSL仮想ネットワークにも接続された状態となったので彼に中継させればWSLインスタンスも外部へと出ていけるようになりました。しかし、WSLはまだそのことを知らないのでradvdを使って、上流から受け取ったプレフィクスをそのまま下流(=WSL仮想ネットワーク)へと広告してあげましょう。

/etc/radvd.conf に以下のように記述します。サンプルそのままですが、RAを流す対象は eth1 (のはず)です。間違って、eth0に流すとネットワーク管理者から叱責されることになるので気を付けてください。念のため、上流からprefixを受け取っているインタフェースを確認するようにしてください。

/etc/radvd.conf
interface eth1
{
       AdvSendAdvert on;
       prefix ::/64
       {
               AdvOnLink on;
               AdvAutonomous on;
               AdvRouterAddr off;
       };
};

prefix の部分には広告するネットワークを書かないといけないのですが、動的に生成するのでひとまずこの形にしておいてください。
/proc/net/if_inet6 に IPv6 のアドレス情報があるので、そこからグローバルユニークアドレス(2::/3)に該当するアドレスを探して、フォーマットを加工します。その文字列を/etc/radvd.conf に当てはめるのですが、方法はこういう感じです。

GUAを/etc/radvd.confに反映する
prefix=$(sed -rn 's/^([23]...)(....)(....)(....).*$/\1:\2:\3:\4/p' /proc/net/if_inet6|head -n1)
sed -ri "s|^(\s+)prefix\s.*$|\1prefix $prefix::/64|g" /etc/radvd.conf

これで完成です。先のスクリプトで加工したコンフィグレーションで radvd を起動すると、WSL2インスタンスにも IPv6 アドレスが割り当てられるのですが、eth1側のリンクローカルアドレスが消えてうまく動かないかもしれません。

OSのIPv6パラメータを少し調整しておきます。

sudo sysctl net.ipv6.conf.eth1.autoconf=0
sudo sysctl net.ipv6.conf.all.forwarding=1

この調整でうまく機能するようになっていると思います。

NDを中継する

次に、neighbor discoveryを中継させるのですが、これはndppdが担当してくれます。
/etc/ndppd.conf に以下のように書いておきます。

ndppd.conf
proxy eth0 {
   router no
   autowire yes
   rule ::/0 {
      iface eth1
   }
}
proxy eth1 {
   rule ::/0 {
      iface eth0
   }
}

これでsudo ndppd -d として起動させればよいのですが、うまく動かないかもしれません。
うまく動かない場合、理由はip -6 rで確認できるのですが、

2xxx:xxxx:xxxx:xxxx::/64 dev eth0 proto ra metric 100 pref medium
2xxx:xxxx:xxxx:xxxx::/64 dev eth1 proto ra metric 101 pref medium

このように上流から受け取ったプレフィクスへの経路がが eth0, eth1 の両方に付けられています。そして、metricで優先順位をつけられています。この場合、ND proxyで近隣の宛先は交換されている(ip neighで確認できる)のですが、経路設定の方が優先されて実際には通信できません。

Rocky(というかRedHat)のパッケージにはndppd 0.2.5が用意されているのですが、正式リリース版の0.2.5はずいぶん前のものです。その後、autowireというオプションが導入されているようです。これは中継したneighborへの経路を設定してくれるオプションです。

githubのndppdリポジトリからソース一式を取ってきてコンパイルすればautowireが使えるようになります。autowire が使えない場合にはWSLインスタンスに割り当てられたIPv6アドレスに対して経路をつけるようにしても代替できます。

ip -6 add dev eth1 2xxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx

metricをいじって優先度を変えれば通信できるようになるのですが、今度は同一プレフィックスの物理ノードとの通信に支障をきたすのでおススメではありません。

実際に使うとなると

実際に使うとなると、これだけの作業のためにわざわざ Hyper-V上のLinuxインスタンスを動かすというのはメモリもディスクスペースも無駄が多いです。なにより普通に Hyper-VでLinux使えばいいじゃんになってしまいます。
なので、できるだけ小さいディストリを探して/あるいは削り落として一連の流れを起動時スクリプトで処理してしまえば起動すればND proxyを開始してホストがシャットダウンする時には自動停止するようにしておくのがよさそうです。
開始タイミングはWSL2より先に起動してしまうとWSL仮想スイッチが存在しない為にエラーになるので、以下のような感じで起動させればよいと思います。

ndproxyインスタンスの起動(シェルスクリプト前提)
wsl.exe echo
powershell.exe Start-Process powershell.exe -WindowStyle Hidden -Verb Runas "Start-VM -Name 'VM名'"

まとめ

Hyper-Vインスタンスのndppdを使ってND Proxyを実現すれば簡単に中継できると思ったのですが、ndppdのバージョンやそもそもHyper-Vでいいじゃん問題を露見させてしまい、今一つまとまりのない感じになってしまいました。
コンパクトなディストリというよりもルーターOSのVyOSいれれば良いような気がしてきたので次はそちらを検証してみます。

1
1
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
1