🔓

WSL2 に wsl-vpnkit を導入して、VPN を張ってもネットワークが切れないようにする

2023/10/05に公開

tl; dr

WSL2 で VPN を張るとルーティングや名前解決が問題が出るので、それを解決するために wsl-vpnkit を入れる

やっていく

作業環境

  • Windows 10 22H2 (OSビルド 19045.3448)
  • WSL バージョン: 1.2.5.0
  • Ubuntu 22.04

ホスト OS (Windows) 側

  1. 最新の wsl-vpnkit.tar.gz を GitHub の Releases ページからダウンロードする
    • この記事を書いている時点では最新は v0.4.1
    • この後に PowerShell から利用するので、PowerShell のホームフォルダに保存しておくとよい
      • 通常は USERPROFILE (C:\Users\<username>)
  2. PowerShell を起動する (管理者権限は不要)
  3. PowerShell に下記のコマンドを入力する
> wsl --import wsl-vpnkit --version 2 $env:USERPROFILE\wsl-vpnkit wsl-vpnkit.tar.gz

これで WSL2 に普段使っている環境とは別に wsl-vpnkit がインストールされます。

$ wsl.exe -l
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu-22.04 (既定)
wsl-vpnkit

ゲスト OS (WSL2 / Ubuntu) 側

wsl-vpnkit を動かす方法としては大きく3つの方法があります。

  1. ホスト OS 側から wsl-vpnkit の WSL 環境を実行する
  2. ゲスト OS 側から wsl-vpnkit の WSL 環境を実行する
    1. 都度スクリプトを実行する
    2. systemd でゲスト OS 起動時に実行する

今回は方法 2-2、つまり systemd で wsl-vpnkit を起動する方法を選択しました。

  1. /etc/wsl.conf に下記のように記載し、systemd を有効にする
[boot]
systemd=true

なお、WSL 環境で systemd を動作させるためには下記の条件を満たしている必要があります。

  • ゲスト OS が WSL2 で、systemd をサポートしたディストリビューションであること
    • Ubuntu 22.04 は systemd をサポートしている
  • WSL が 0.67.6 以降であること
> wsl.exe -v
WSL バージョン: 1.2.5.0
カーネル バージョン: 5.15.90.1
WSLg バージョン: 1.0.51
MSRDC バージョン: 1.2.3770
Direct3D バージョン: 1.608.2-61064218
DXCore バージョン: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows バージョン: 10.0.19045.3448
  1. systemd 用の service ファイルを wsl-vpnkit 環境からゲスト OS にコピーする
$ wsl.exe -d wsl-vpnkit --cd /app cat /app/wsl-vpnkit.service | sudo tee /etc/systemd/system/wsl-vpnkit.service
$ sudo cp ./wsl-vpnkit.service /etc/systemd/system/
  1. systemd を有効にするために WSL2 環境を完全に停止する
> wsl.exe -l
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu-22.04 (既定)
wsl-vpnkit
> wsl.exe -t Ubuntu-22.04
  1. WSL を起動し、systemd 経由で wsl-vpnkit が起動することを確認する

ログなどから正常に ping/nslookup/wget が動作していれば問題ない。

$ sudo systemctl start wsl-vpnkit
$ systemctl status wsl-vpnkit -n 100
● wsl-vpnkit.service - wsl-vpnkit
     Loaded: loaded (/etc/systemd/system/wsl-vpnkit.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2023-10-05 10:46:52 JST; 3h 29min ago
   Main PID: 226 (wsl.exe)
      Tasks: 1 (limit: 19006)
     Memory: 172.0K
     CGroup: /system.slice/wsl-vpnkit.service
             └─226 /init /mnt/c/Windows/system32/wsl.exe /mnt/c/Windows/system32/wsl.exe -d wsl-vpnkit --cd /app wsl-vpnkit

Oct 05 10:46:52 YOURMACHINENAME systemd[1]: Started wsl-vpnkit.
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + VPNKIT_GATEWAY_IP=192.168.127.1
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + VPNKIT_HOST_IP=192.168.127.254
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + VPNKIT_LOCAL_IP=192.168.127.2
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + TAP_MAC_ADDR=sa:mp:le:ma:ca:dd
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + VMEXEC_PATH=/app/wsl-vm
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + GVPROXY_PATH=/app/wsl-gvproxy.exe
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + TAP_NAME=wsltap
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + CHECK_HOST=example.com
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + CHECK_DNS=1.1.1.1
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + DEBUG=0
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + set +x
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + WSL2_TAP_NAME=eth0
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + WSL2_GATEWAY_IP=172.17.80.1
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + '[' 0 -eq 0 ]
Oct 05 10:46:52 YOURMACHINENAME wsl.exe[226]: + set +x
Oct 05 10:46:53 YOURMACHINENAME wsl.exe[226]: starting vm and gvproxy...
Oct 05 10:46:53 YOURMACHINENAME wsl.exe[226]: time="2023-10-05T01:46:53Z" level=info msg="waiting for packets..."
Oct 05 10:46:54 YOURMACHINENAME wsl.exe[226]: started vm and gvproxy
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: time="2023-10-05T10:46:54+09:00" level=info msg="waiting for clients..."
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: time="2023-10-05T10:46:55+09:00" level=info msg="new connection from remote to 15096"
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ ping success to IPv4 WSL 2 gateway / Windows host (172.17.80.1)
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ ping success to IPv4 Windows host (192.168.127.254)
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ ping success to IPv4 gateway (192.168.127.1)
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ nslookup success for example.com A using 192.168.127.1
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ nslookup success for example.com A using 172.17.80.1
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ nslookup success for example.com A using 1.1.1.1
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ ping success to IPv4 external host domain (example.com)
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ ping success to IPv4 external host IP (1.1.1.1)
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ nslookup success for example.com AAAA using 192.168.127.1
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ nslookup success for example.com AAAA using 172.17.80.1
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ nslookup success for example.com AAAA using 1.1.1.1
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: ping: bad address 'example.com'
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ➖ ping fail to IPv6 external host (example.com)
Oct 05 10:46:55 YOURMACHINENAME wsl.exe[226]: check: ✔️ wget success for http://example.com
Oct 05 10:46:56 YOURMACHINENAME wsl.exe[226]: check: ✔️ wget success for https://example.com
  1. 次回以降、ゲスト OS の起動の際に wsl-vpnkit を起動するように設定する
$ sudo systemctl enable wsl-vpnkit

これ以降、WSL2 を起動した状態 (=wsl-vpnkit が起動した状態) で VPN を張ると、自動的にルーティングや DNS Proxy の設定が行われて、VPN 接続後も問題なく通信ができるようになる。

Discussion