はじめに
概要
リモートのWindows PCで動かしているWSL2に、SSH接続して開発をおこなおうとしたが、
色々と詰まった点があったのでまとめる。
環境
クライアント
OS: Windows 10 Home 64Bit
リモートマシン
OS: Windows 10 Home 64Bit
WSL2: Ubuntu-20.04
なぜやろうと思ったのか
新しいPCを買ったので、新PCをきれいに保つために、旧PCを開発専用機に新PCは開発用途では使用しないようにしようと考えた。
しかし、わざわざ移動したり2つのPCを操作するのが面倒だったため、新PCから開発できるようにしたくなった。
そのため、新PCをあまり汚さずに新PCから開発するという目的を達成するために、新PCから旧PCにリモート接続して開発をしようと考えた。
Windowsアプリケーションの開発経験がないかつ、サーバが専門なのでWSL2上で開発しようと考えた。
開発の際はVS CodeのRemote Development
という拡張機能を利用して開発をしようと考えたため、直接リモートマシンのWSL2にSSH接続ができるようにしたかった。
手順と詰まったとこ
ポートフォワーディングを利用する(失敗)
手順
環境構築の手順は以下の2つを参考にした。
どちらもやっていることはWSL2上でSSHサーバが起動するようにし、リモートマシンの22番ポートへの接続をWSL2に転送するために、ポートフォワーディングを起動時に設定するスクリプトをタスクスケジューラで起動時に実行しているだけである。
しかし、私の場合はこれらの手順では直接WSL2にSSH接続することができなかった。
詰まった点
どのようにSSH接続できなかったかと言うと、
リモートマシン自体へはSSH接続できるのだが、そこからWSL2へ転送されていなかった。
リモートマシンからwsl
コマンドではなく、ssh
コマンドでアクセスしようとするとアクセスできなかった。
そのため、SSHサーバが起動していないのかと考え、systemctl status ssh
を実行すると下記のようなエラー文が出た。
$ systemctl status sshd
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
システムがPID 1でブートしていないとのことだった。
調べてみると下記のようなWEBページが見つかった。
Windows 10 Home(WSL2)のUbuntuでsystemctlを利用する方法(systemdをPID1で動作させる方法)
この記事によるとgenieを導入すると解決できるとのことだったので試した。
ただし、この記事の手順ではうまくいかないため、genieのGitHubのREADME.mdを参考に導入した。
genieのインストール
まず依存パッケージであるdotnet-runtime-5.0を入れた。
上述のサイトを参考に、バージョンの部分だけ変更し実行した。
sudo apt-get install -y gpg
wget -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o microsoft.asc.gpg
sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget https://packages.microsoft.com/config/ubuntu/20.04/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update; \
sudo apt-get install -y apt-transport-https && \
sudo apt-get update && \
sudo apt-get install -y dotnet-sdk-5.0.4
続いて、GitHubのREADMEに書かれているhttps://arkane-systems.github.io/wsl-transdebian/ に従ってwsl-translinux repository
を追加した。
この際、<distro>
を下記に従って変更する。
(適当に読んで脳死で<distro
をそのままにしたり、Ubuntu-20.04
に変えて地味に詰まってたので気をつけて)
Debian 10 buster
Debian 11 bullseye
Debian 12 bookworm
Debian (testing) sid
Ubuntu focal
Ubuntu bionic
apt install apt-transport-https
wget -O /etc/apt/trusted.gpg.d/wsl-transdebian.gpg https://arkane-systems.github.io/wsl-transdebian/apt/wsl-transdebian.gpg
chmod a+r /etc/apt/trusted.gpg.d/wsl-transdebian.gpg
cat << EOF > /etc/apt/sources.list.d/wsl-transdebian.list
deb https://arkane-systems.github.io/wsl-transdebian/apt/ <distro> main
deb-src https://arkane-systems.github.io/wsl-transdebian/apt/ <distro> main
EOF
apt update
上述のサイトではpackagecloud.ioにあるスクリプトファイルを利用していたようだが、下記の通り利用できなくなっているため上記を実行する。
(The packagecloud.io repository is now deprecated. If you are still using it, please update your system to use the repository above.)
これでパッケージのリポジトリを追加できたので、下記を実行してgenieをインストールする。
sudo apt update
sudo apt install -y systemd-genie
genieのインストール後は上述のサイトに従って、
.bashrc
に下記を追加して、起動時にsystemdがPID1でない場合genie -s
を実行するようにする。
if [ "`ps -eo pid,cmd | grep systemd | grep -v grep | sort -n -k 1 | awk 'NR==1 { print $1 }'`" != "1" ]; then
genie -s
fi
結果
再度systemctl status sshd
を実行すると下記のようにsystemctl
が実行できることが確認できた。
systemctl status sshd
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Mon 2021-03-29 16:17:58 JST; 4min 5s ago
Docs: man:sshd(8)
man:sshd_config(5)
しかし、systemctlは実行できたもののポートフォワーディングがうまくいかず、WSL2まで届かずリモートマシンにつながってしまう
多段SSHで接続する(解決)
ここで、リモートサーバ上のDBをDBクライアントで確認するときのことを思い出し、多段SSHでの接続を試してみようと考えた。
いろいろ試しているうちにリモートマシン上でssh localhost
とすることでWSL2に接続することが確認できた。
そのため、これを利用して多段SHHによる接続を試みた。
これにより、新PCからリモートマシンのWSL2にSSH接続することができ、
VSCodeのRemote Developmentでも問題なく利用することができるようになった。
前述の手順で設定したポートフォワーディングが効いていたのかと思ったが、どうやらlocalhostでWSL2にアクセスできるようになってたらしい。
今までの苦労はなんぞやと……
それまでは、WSL2のIPは起動するごとに変わり、WSL2に付けられたホスト名もサポートされていなかったため、前述の手順のようなことが求められたのだと思われる。
参考: 「WSL 2」最大の課題であった“localhost”問題が解決 ~「Windows 10」Build 18945 - 窓の杜
手順
下記のようにC:\Users\{UserName}\.ssh\config
に追記する。
Host Remote
HostName {RemoteHostName}
User {RemoteUserName}
IdentityFile C:\Users\{UserName}\.ssh\id_rsa
Host WSL2
HostName localhost
User {WSL2UserName}
IdentityFile C:\Users\{UserName}\.ssh\id_rsa
ProxyCommand ssh.exe -l %r -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null {RemoteHostName} -W %h:%p
まとめ
- 以前はWSL2のIPは起動ごとに変わりホスト名解決もできず、IPをわざわざ調べるなりポートフォワーディングなど迂遠な方法をしないとSSH接続はできなかったが、現在はlocalhostでアクセスすることができる
- このlocalhostForwardingというオプションは、以前は.wslconfigで指定しないといけないようだったが、現在はデフォルトで使えるっぽい
- リモートのリソースにアクセスするときはやっぱ踏み台なんだなって思った