在使用 Windsurf 時遇到 Cascade 在 WSL 環境中無法正常執行指令的問題。我認為 SSH 連線是一個可能的解決方案,因此開始研究 如何從 Windows host 透過 SSH 連線到 WSL 實體。本章記錄了其中的執行步驟、研究跟思考,可以作為以後的快速引導。
操作環境
- Windows host: Windows 11 Pro 23H2
- User: v2266
- WSL Instance: Ubuntu 22.04.5 LTS
- User: vinny987
Windows 10 和 Windows 11 內建了 OpenSSH Client,不需要額外配置 SSH。
安裝並執行 SSH Server
首先,進入 WSL 中。 由於 Ubuntu 預設未安裝 SSH Server,所以使用以下指令安裝:
1sudo apt install openssh-server -y
如果你也需要在 WSL 中使用 openssh-client,可以安裝組合包
ssh
:sudo apt install ssh -y
這個包同時包含 openssh-server 和 openssh-client。
查看 SSH Server 的運作情況:
1systemctl status ssh2###3● ssh.service - OpenBSD Secure Shell server4 Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)5 Active: active (running) since Thu 2024-11-28 00:39:30 CST; 8min ago6 Docs: man:sshd(8)7 man:sshd_config(5)8 Process: 256 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)9 Main PID: 288 (sshd)10 Tasks: 1 (limit: 38465)11 Memory: 4.9M12 CGroup: /system.slice/ssh.service13 └─288 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"14
15Nov 28 00:39:29 vince987 systemd[1]: Starting OpenBSD Secure Shell server...3 collapsed lines
16Nov 28 00:39:30 vince987 sshd[288]: Server listening on 0.0.0.0 port 22.17Nov 28 00:39:30 vince987 sshd[288]: Server listening on :: port 22.18Nov 28 00:39:30 vince987 systemd[1]: Started OpenBSD Secure Shell server.
回到 Windows host 的 PowerShell,測試 SSH 連線到 WSL:
1ssh vinny987@localhost -p 222###3Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.167.4-microsoft-standard-WSL2 x86_64)4[...]
連線成功了,我們可以進一步優化連線設置,提高可用性和安全性。
設置 Port-Forward
在 WSL 啟動後,SSH 服務會將流量直接映射到 Windows 的 127.0.0.1:22。這種行為是由 WSL 的 NAT 和網絡配置機制實現的,允許 Windows 與 WSL 無縫通信。
為了讓同網段其他裝置可以連線到 Windows host 內的 WSL,我們需要 監聽 Windows host IP 的 2222 Port,將其 TCP 連線導向 127.0.0.1 的 22 Port
。
Windows 系統中有 Port-Forward 指令 - netsh interface portproxy
。
查詢 Windows host IP
到 Windows host 的終端,查詢 Windows host IP:
1ipconfig2###3[...]4Ethernet adapter 乙太網路:5
6 Connection-specific DNS Suffix . :7 Link-local IPv6 Address . . . . . : xxxx::xxxx:xxxx:xxxx:xxxx%148 IPv4 Address. . . . . . . . . . . : 192.168.31.6 <- here9 Subnet Mask . . . . . . . . . . . : 255.255.255.010 Default Gateway . . . . . . . . . : 192.168.31.111[...]
設置 Port-Forward
設置 Port-Forward (系統管理員權限):
1# 將 Windows host IP 2222 Port 導向 localhost 22 Port2netsh interface portproxy add v4tov4 listenaddress=192.168.31.6 listenport=2222 connectaddress=127.0.0.1 connectport=22
查詢當前的 Port-Forward 設定:
1netsh interface portproxy show all2###3Listen on ipv4: Connect to ipv4:4
5Address Port Address Port6--------------- ---------- --------------- ----------7192.168.31.6 2222 127.0.0.1 22
測試連線:
1ssh vinny987@192.168.31.6 -p 22222###3Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.167.4-microsoft-standard-WSL2 x86_64)4[...]
設置防火牆
雖然目前只有內網可以連進 WSL,但還是要養成最小化權限的好習慣。
查詢內網網段
到 Router 後台,查詢內網使用的網段:
檢查防火牆狀態
1netsh advfirewall show allprofiles2###3Domain Profile Settings:4----------------------------------------------------------------------5State ON6[...]7
8Private Profile Settings:9----------------------------------------------------------------------10State ON11[...]12
13Public Profile Settings:14----------------------------------------------------------------------15State ON3 collapsed lines
16[...]17
18Ok.
添加防火牆規則
添加防火牆規則 (系統管理員權限):
1netsh advfirewall firewall add rule name="Allow SSH 2222 for LAN" `2 dir=in action=allow protocol=TCP `3 localip=192.168.31.6 localport=2222 `4 remoteip=192.168.31.5-192.168.31.254
說明:
name="Allow SSH 2222 for LAN"
:設定防火牆規則的名稱。dir=in
:指定為入站流量規則,限制外部訪問主機的請求。action=allow
:允許符合條件的流量通過防火牆。protocol=TCP
:限制流量的協議為 TCP(適用於 SSH)。localip=192.168.31.6
:僅適用於該主機的私人 IP 地址。localport=2222
:僅針對目標埠 2222 的流量。remoteip=192.168.31.5-192.168.31.254
:
- 僅允許來自指定來源 IP 範圍的流量。
- 格式支持單個 IP、IP 範圍(
-
)或 CIDR(如192.168.31.0/24
)。
驗證防火牆規則:
1netsh advfirewall firewall show rule name="Allow SSH 2222 for LAN"2
3Rule Name: Allow SSH 2222 for LAN4----------------------------------------------------------------------5Enabled: Yes6Direction: In7Profiles: Domain,Private,Public8Grouping:9LocalIP: 192.168.31.6/3210RemoteIP: 192.168.31.5-192.168.31.25411Protocol: TCP12LocalPort: 222213RemotePort: Any14Edge traversal: No15Action: Allow
使用手機進行連線測試。
查詢裝置內網 IP:
使用 SSH APP,配置連線資訊:
建立連線,結果如下:
這樣防火牆就配置完成了。至此,防火牆規則已正確設置,允許 LAN 訪問。
延伸討論
由於第一次使用 netsh advfirewall
指令,所以順便測試其效果。
刪除防火牆規則
刪除防火牆規則 (系統管理員權限):
1netsh advfirewall firewall delete rule name="Allow SSH 2222 for LAN"
重新建立防火牆規則,這次僅允許 192.168.31.5-192.168.31.200
的連線進來 (系統管理員權限):
1netsh advfirewall firewall add rule name="Allow SSH 2222 for LAN" `2 dir=in action=allow protocol=TCP `3 localip=192.168.31.6 localport=2222 `4 remoteip=192.168.31.5-192.168.31.200
驗證防火牆規則:
1netsh advfirewall firewall show rule name="Allow SSH 2222 for LAN"2###3Rule Name: Allow SSH 2222 for LAN4----------------------------------------------------------------------5Enabled: Yes6Direction: In7Profiles: Domain,Private,Public8Grouping:9LocalIP: 192.168.31.6/3210RemoteIP: 192.168.31.5-192.168.31.20011Protocol: TCP12LocalPort: 222213RemotePort: Any14Edge traversal: No15Action: Allow1 collapsed line
16Ok.
由於手機內網的 IP 是 192.168.31.225,理論上應該無法連線:
防火牆默認行為通常是丟棄(Drop),也就是說不會告訴客戶端連線被阻止,而是直接忽略請求。客戶端會繼續等待,直到超時(timeout)。
設置金鑰,安全的登入
從 Windows host 之外的裝置進行登入,需要通過密碼驗證。我們可以使用公鑰私鑰來加強安全性,減少登入的驗證麻煩。使用公鑰私鑰可以避免密碼被竊取的風險,並提高身份驗證的安全性。
產生金鑰 (Windows)
以下我會簡略地講解執行步驟,想要了解更多可以參考 在 Azure 中建立和管理對 Linux VM 進行驗證所需的 SSH 金鑰。
使用 ssh-keygen
指令產生公鑰私鑰:
1ssh-keygen -m PEM -t ed25519
題外話: 都 2024 年了,讓我們使用更安全的金鑰 - ref
跟著引導走,結果如下:
產生的金鑰檔案預設儲存在
%UserProfile%\.ssh
目錄下,id_ed25519
是私鑰檔案,務必妥善保管,避免遺失或遭竊,因為私鑰一旦外流,我們的身份將可能被冒用;id_ed25519.pub
則是公鑰,可以公開分享給需要驗證我們身份的對象。
放置公鑰 (WSL)
~/.ssh/authorized_keys
檔案中的 SSH 公鑰允許 SSH 伺服器驗證具有對應私鑰的客戶端。啟用 SSH 金鑰驗證後,Linux 系統通常會停用密碼驗證,僅允許 SSH 金鑰驗證,提升系統安全性,無需手動編輯 sshd_config
檔案停用密碼驗證。
首先,進入 WSL 終端。
驗證 .ssh 和 .ssh/authorized_keys 是否存在,若不存在,建立它們並設置合適的權限:
1mkdir -p /home/vinny987/.ssh2touch /home/vinny987/.ssh/authorized_keys3chmod 700 /home/vinny987/.ssh4chmod 600 /home/vinny987/.ssh/authorized_keys
將公鑰內容添加到 WSL 系統的 ~/.ssh/authorized_keys
檔案中:
1# 使用公鑰內容將其追加到 authorized_keys 中2cat /mnt/c/Users/v2266/.ssh/id_ed25519.pub >> /home/vinny987/.ssh/authorized_keys # 此處隱去具體路徑
查看 authorized_keys 文件的內容,確認結果:
1cat /home/vinny987/.ssh/authorized_keys2###3ssh-ed25519 AAAAC3N************ v2266@vince987
延伸討論
如果想要避免重複追加,可以使用以下指令:
1grep -q -f /mnt/c/Users/v2266/.ssh/id_ed25519.pub /home/vinny987/.ssh/authorized_keys || \2cat /mnt/c/Users/v2266/.ssh/id_ed25519.pub >> /home/vinny987/.ssh/authorized_keys
說明:
grep -q
:檢查 authorized_keys 中是否已包含該公鑰。||
:如果未找到(即退出狀態非零),則執行 cat 命令追加。
最後,回到 Windows host,測試連線:
1ssh -i ~/.ssh/id_ed25519 vinny987@192.168.31.6 -p 22222###3Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.167.4-microsoft-standard-WSL2 x86_64)
建立和設定 SSH 組態檔
我們可以建立及設定 SSH 組態檔 (~/.ssh/config
) 以加速登入,並最佳化我們的 SSH 用戶端行為。
Windows 的做法
在 Windows host 中,開啟 PowerShell。
確認 .ssh
目錄是否存在:
1dir $env:USERPROFILE\.ssh2# 不存在的話,使用指令建立目錄3mkdir $env:USERPROFILE\.ssh
創建或編輯 config
文件:
1notepad $env:USERPROFILE\.ssh\config
添加以下內容後儲存:
1Host mywsl2 HostName 192.168.36.63 User vinny9874 Port 22225 IdentityFile ~/.ssh/id_ed25519
說明:
配置項 含義 範例 Host
配置的別名,用於簡化 SSH 命令。 myserver
HostName
遠端伺服器的地址(IP 或域名)。 192.168.1.100
User
登錄使用者名稱。 myuser
Port
SSH 服務埠(默認為 22
)。2222
IdentityFile
私鑰文件的路徑,用於身份驗證。 ~/.ssh/id_ed25519
最後,測試使用組態檔連線:
1ssh mywsl2###3Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.167.4-microsoft-standard-WSL2 x86_64)4[...]
到此,所有的設置就完成了。
測試 VS Code 的 SSH Remote
讓我們來測試看看,我們一開始的問題能否被解決:
雖然我們成功進行了 SSH remote,不過 Cascade 還是有些問題,但這就不屬於本章的範疇了。
清除設置
Windows host (系統管理員權限):
1# 刪除 Port-Forward 規則 (根據 listenaddress 和 listenport 決定刪除哪一條)2netsh interface portproxy delete v4tov4 listenaddress=192.168.31.6 listenport=22223# 刪除防火牆規則4netsh advfirewall firewall delete rule name="Allow SSH 2222 for LAN"
參考
- https://learn.microsoft.com/zh-tw/azure/virtual-machines/linux/create-ssh-keys-detailed
- https://dev.to/govindsb/set-up-ssh-for-wsl-to-use-windsurf-ide-before-official-wsl-support-aj8
- https://blog.darkthread.net/blog/remote-ssh-wsl
- https://medium.com/@wuzhenquan/windows-and-wsl-2-setup-for-ssh-remote-access-013955b2f421