インストール

ここを参考にした。 以前WSL1を触った時はMicrosoftストアからイメージをDLする感じだったと記憶しているが、コマンドだけでインストールできた。 Powershellでのコマンド:

wsl --install

これだけでUbuntu20.04が自動でインストールされた。

イメージの移動

デフォルトではCドライブにインストールされる。 しかし後々ディスク容量を逼迫することが目に見えたので、別ドライブにイメージを移動させた。 ここを参考にした。 Fドライブに1TBのSSDを増設したので、基本ここの直下を使うことにした。 Powershellでのコマンド:

wsl --shutdown
wsl --export Ubuntu F:Ubuntu.tar
wsl --unregister Ubuntu
wsl --import Ubuntu F:Ubuntu D:Ubuntu.tar --version 2

これを行うことで、デフォルトユーザーがrootになってしまう問題がある。 基本vscodeのremote sshで接続する予定なのであまり問題はないが、リンクを参考にしてユーザー権限で起動するショートカットを作成した。

また、後々明らかになったのだが、デフォルトのイメージはディスク容量が256GBを最大値として作られるようだった。 容量を拡張するために、ここに従ってコマンドを実行した。

同一LANからWSLにSSHする

Ubuntu内でsshサービスを立ち上げておく必要がある。 いろいろ試行錯誤したため記憶が定かでないが、open-sshは初めからインストールされていた。 なので鍵がうまく設定されていさえすれば、同一LANの外部から接続できそうだが、問題が2つある。

  1. WSLではsystemdが動いておらず、サービスを自動で起動することができない。
  2. WSL2ではホストであるWindowsと異なるIPが使用されており、直接外部から接続することが難しい。

このうち1. はWSLを起動するときにオプションでシェルスクリプトを実行できるので、それで解決した。 具体的にはWSL内でinit-wsl.shとかの名前のスクリプトを作成しておき、WSL起動時に

wsl -d Ubuntu -u root exec /home/user/init-wsl.sh

とすればよい。init-wsl.shの中身として

#!/bin/sh
service ssh restart
service cron restart

などと、起動したいサービスの名前を書いておく。 これでsshやcronなどのコマンドを実行できる。

つぎに2. は、Windowsポート22に来たパケットをwslのポート22に転送する設定を実施した。

for /F %%i in ('wsl -d Ubuntu exec hostname -I') do set ip=%%i
netsh interface portproxy delete v4tov4 listenport=22
netsh interface portproxy add    v4tov4 listenport=22 connectaddress=%ip%

この設定はここを真似した。 これらがWindowsが起動されるたびに自動で実施するために、

wsl -d Ubuntu -u root exec /home/user/init-wsl.sh
for /F %%i in ('wsl -d Ubuntu exec hostname -I') do set ip=%%i
netsh interface portproxy delete v4tov4 listenport=22
netsh interface portproxy add    v4tov4 listenport=22 connectaddress=%ip%

とまとめたstart-wsl.batなるファイルを作成し、windowsのタスクスケジューラに設定した。

  • 全般
    • 最上位の特権で実行する: on
  • トリガー
    • タスクの開始: ログオン時
    • 遅延時間を指定する: 30秒間
  • 操作
    • 操作: プログラムの開始
    • プログラム/スクリプト: 上記のファイルを置いたパス という感じ。

別LANから接続したい

GCEの無料枠の作成

別LANから接続する際の問題は

  • グローバルIPが固定されていないこと

である。 プロバイダのオプションで固定してくれるサービスもあったが、課金制だったため、無料で行う方法を探していたら、 ここを見つけた。 つまりsshのリモートフォワードを利用して、VPSを経由した接続を実現するというもの。 VPSの調達先として、Googleが提供しているCompute Engineをうまく使えば、課金なしで踏み台用の固定IPが手に入る。 設定はここが参考になった。

一点、GCEで作成するイメージとして、無料枠のマシンの名前が、2021年7月まではf1-microだったのが、8月以降e2-microに変わっている。 古い記事だけを参考にすると、誤って課金されてしまうので注意。 こことかに変更のあらましが述べられている。

もう一点、GCEのアドレスは外部に公開されるため、ssh用のポートは変更しておくことが望ましい。 これも確か上の記事の中でやり方が書かれていたはずなので説明割愛。

リモートフォワード設定

GCEのsshのポートは11111とする。 Windowsマシンのsshのポートは22とする。 このとき、WSL側で実行するコマンドは

autossh -f -N gce -p 11111 -R 22222:localhost:22

となる。 22222は別に空いていればなんでもよい。 接続先のgceの部分はWSL側の.ssh/configで良しなに設定されているとする。 sshでなくautosshとしているのは、接続が切れたとき再接続してほしいからである(aptでインストール可能)。 -f -Nなどのオプションは検索されたい。 -Rがリモートフォワードを指定するオプションで、gceマシンの22222ポートをlocalhost、つまりwslの22番ポートにリモートフォワードしている。

つぎに外部PC(ここではmacbookとする)で実行するコマンドは

ssh gce -p 11111 -L 33333:localhost:22222

ssh localhost -p 33333

となる。 もちろんmacbook側からも、gce./ssh/configで設定しておく必要がある。 ポート33333も、空いていればなんでもよい。 また、1行目と2行目は、それぞれ別ターミナルから実行することに注意。 1行目でmacbookの33333ポートをgceマシンのlocalhost:22222にローカルフォワードしている。 この状態でmacbookのlocalhostの33333にsshでログインすると、macbook->gceマシン->wslというログインが可能になる。

もちろん、それぞれのsshコマンドでは、鍵が良しなに設定されていなければならない。

WSLでのssh自動実行

これでリモートで作業する環境が整ったのだが、

autossh -f -N gce -p 11111 -R 22222:localhost:22

のコマンドは、できればwsl開始時に自動で起動させたい。 ここでふたたび問題になるのが、WSLでsystemdが動いていない問題である。 さきほどのinit-wsl.shの下のほうにコマンドを追記しても、うまく動かなかった。 また、どうやら最近導入されたWSLのバージョンで、/etc/wsl.confの中で起動時に実行するコマンドを指定できるようになったらしいのだが、自分の環境ではうまく動かなかった。

いろいろ調べると、genieなるソフトを使えばsystemdを強制的に動かすこともできると書かれていたが、CPU使用率を上げてしまうという情報もあったので、避けることにした。

そこで、多少強引だがcronを使うことにした。 具体的には、上記のautosshのコマンド1行からなるtunnel_to_gce.shという名前のスクリプトを作成し、crontabに下記を追記した。

*/1 * * * * user pidof -x tunnel_to_gce.sh >/dev/null || /home/user/tunnel_to_gce.sh

1分ごとに実行されるので、かなり冗長だが、一応前半のpidof -x tunnel_to_gce.sh >/dev/null ||あたりの記述で、重複実行は避けられるらしい(シェルスクリプトよくわかってない…)

余談

とりあえず以上で

windowsが起動->wsl起動->ssh, cronサービス起動->autosshでgceにリモートフォワード

まで自動化できた。 したがってwindowsマシンが起動さえすれば、いつでも外部からssh可能になった。

あとはWake on LANまでできたら最高だが、Switchbotのスイッチが使えるという情報をみつけ、確かにそうだなと思ったので、早速ぽちった。 今日届いてPCの電源ボタンにつけてみたが、簡単に使えた。 いざという時の強制再起動に役立てられそう。

最後に、時にはGUI環境でWindowsに接続したい時もある。 これは普通にWindowsのRDP機能を使えばよい。 …のだが、なんとRDPサーバーの機能はWindows Proでなければ使えないことがわかった。

このため先ほどMicrosoft Storeから泣く泣くProライセンスを購入したところ。 狡い商売しやがって、Microsoft許さん

以上です。 研究頑張ります。