Vinc3nt's Life

WSL 網絡互聯指南:SSH 遠程訪問的全面配置與安全實踐

2024-11-28
develop
wsl
linux
ssh
powershell
remote
security
最後更新:2025-01-26
11分鐘
2059字

在使用 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,所以使用以下指令安裝:

Terminal window
1
sudo apt install openssh-server -y

如果你也需要在 WSL 中使用 openssh-client,可以安裝組合包 sshsudo apt install ssh -y 這個包同時包含 openssh-server 和 openssh-client。

查看 SSH Server 的運作情況:

Terminal window
1
systemctl status ssh
2
###
3
ssh.service - OpenBSD Secure Shell server
4
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 ago
6
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.9M
12
CGroup: /system.slice/ssh.service
13
└─288 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
14
15
Nov 28 00:39:29 vince987 systemd[1]: Starting OpenBSD Secure Shell server...
3 collapsed lines
16
Nov 28 00:39:30 vince987 sshd[288]: Server listening on 0.0.0.0 port 22.
17
Nov 28 00:39:30 vince987 sshd[288]: Server listening on :: port 22.
18
Nov 28 00:39:30 vince987 systemd[1]: Started OpenBSD Secure Shell server.

回到 Windows host 的 PowerShell,測試 SSH 連線到 WSL:

Terminal window
1
ssh vinny987@localhost -p 22
2
###
3
Welcome 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:

Terminal window
1
ipconfig
2
###
3
[...]
4
Ethernet adapter 乙太網路:
5
6
Connection-specific DNS Suffix . :
7
Link-local IPv6 Address . . . . . : xxxx::xxxx:xxxx:xxxx:xxxx%14
8
IPv4 Address. . . . . . . . . . . : 192.168.31.6 <- here
9
Subnet Mask . . . . . . . . . . . : 255.255.255.0
10
Default Gateway . . . . . . . . . : 192.168.31.1
11
[...]

設置 Port-Forward

設置 Port-Forward (系統管理員權限):

Terminal window
1
# 將 Windows host IP 2222 Port 導向 localhost 22 Port
2
netsh interface portproxy add v4tov4 listenaddress=192.168.31.6 listenport=2222 connectaddress=127.0.0.1 connectport=22

查詢當前的 Port-Forward 設定:

Terminal window
1
netsh interface portproxy show all
2
###
3
Listen on ipv4: Connect to ipv4:
4
5
Address Port Address Port
6
--------------- ---------- --------------- ----------
7
192.168.31.6 2222 127.0.0.1 22

測試連線:

Terminal window
1
ssh vinny987@192.168.31.6 -p 2222
2
###
3
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.167.4-microsoft-standard-WSL2 x86_64)
4
[...]

設置防火牆

雖然目前只有內網可以連進 WSL,但還是要養成最小化權限的好習慣。

查詢內網網段

到 Router 後台,查詢內網使用的網段:

default

檢查防火牆狀態

Terminal window
1
netsh advfirewall show allprofiles
2
###
3
Domain Profile Settings:
4
----------------------------------------------------------------------
5
State ON
6
[...]
7
8
Private Profile Settings:
9
----------------------------------------------------------------------
10
State ON
11
[...]
12
13
Public Profile Settings:
14
----------------------------------------------------------------------
15
State ON
3 collapsed lines
16
[...]
17
18
Ok.

添加防火牆規則

添加防火牆規則 (系統管理員權限):

Terminal window
1
netsh 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)。

驗證防火牆規則:

Terminal window
1
netsh advfirewall firewall show rule name="Allow SSH 2222 for LAN"
2
3
Rule Name: Allow SSH 2222 for LAN
4
----------------------------------------------------------------------
5
Enabled: Yes
6
Direction: In
7
Profiles: Domain,Private,Public
8
Grouping:
9
LocalIP: 192.168.31.6/32
10
RemoteIP: 192.168.31.5-192.168.31.254
11
Protocol: TCP
12
LocalPort: 2222
13
RemotePort: Any
14
Edge traversal: No
15
Action: Allow

使用手機進行連線測試。

查詢裝置內網 IP:

default

使用 SSH APP,配置連線資訊:

default

建立連線,結果如下:

default

這樣防火牆就配置完成了。至此,防火牆規則已正確設置,允許 LAN 訪問。

延伸討論

由於第一次使用 netsh advfirewall 指令,所以順便測試其效果。

刪除防火牆規則

刪除防火牆規則 (系統管理員權限):

Terminal window
1
netsh advfirewall firewall delete rule name="Allow SSH 2222 for LAN"

重新建立防火牆規則,這次僅允許 192.168.31.5-192.168.31.200 的連線進來 (系統管理員權限):

Terminal window
1
netsh 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

驗證防火牆規則:

Terminal window
1
netsh advfirewall firewall show rule name="Allow SSH 2222 for LAN"
2
###
3
Rule Name: Allow SSH 2222 for LAN
4
----------------------------------------------------------------------
5
Enabled: Yes
6
Direction: In
7
Profiles: Domain,Private,Public
8
Grouping:
9
LocalIP: 192.168.31.6/32
10
RemoteIP: 192.168.31.5-192.168.31.200
11
Protocol: TCP
12
LocalPort: 2222
13
RemotePort: Any
14
Edge traversal: No
15
Action: Allow
1 collapsed line
16
Ok.

由於手機內網的 IP 是 192.168.31.225,理論上應該無法連線:

default

防火牆默認行為通常是丟棄(Drop),也就是說不會告訴客戶端連線被阻止,而是直接忽略請求。客戶端會繼續等待,直到超時(timeout)。

設置金鑰,安全的登入

從 Windows host 之外的裝置進行登入,需要通過密碼驗證。我們可以使用公鑰私鑰來加強安全性,減少登入的驗證麻煩。使用公鑰私鑰可以避免密碼被竊取的風險,並提高身份驗證的安全性。

產生金鑰 (Windows)

以下我會簡略地講解執行步驟,想要了解更多可以參考 在 Azure 中建立和管理對 Linux VM 進行驗證所需的 SSH 金鑰

使用 ssh-keygen 指令產生公鑰私鑰:

Terminal window
1
ssh-keygen -m PEM -t ed25519

題外話: 都 2024 年了,讓我們使用更安全的金鑰 - ref

跟著引導走,結果如下:

default

產生的金鑰檔案預設儲存在 %UserProfile%\.ssh 目錄下,id_ed25519 是私鑰檔案,務必妥善保管,避免遺失或遭竊,因為私鑰一旦外流,我們的身份將可能被冒用;id_ed25519.pub 則是公鑰,可以公開分享給需要驗證我們身份的對象。

放置公鑰 (WSL)

~/.ssh/authorized_keys 檔案中的 SSH 公鑰允許 SSH 伺服器驗證具有對應私鑰的客戶端。啟用 SSH 金鑰驗證後,Linux 系統通常會停用密碼驗證,僅允許 SSH 金鑰驗證,提升系統安全性,無需手動編輯 sshd_config 檔案停用密碼驗證。

首先,進入 WSL 終端。

驗證 .ssh 和 .ssh/authorized_keys 是否存在,若不存在,建立它們並設置合適的權限:

Terminal window
1
mkdir -p /home/vinny987/.ssh
2
touch /home/vinny987/.ssh/authorized_keys
3
chmod 700 /home/vinny987/.ssh
4
chmod 600 /home/vinny987/.ssh/authorized_keys

將公鑰內容添加到 WSL 系統的 ~/.ssh/authorized_keys 檔案中:

Terminal window
1
# 使用公鑰內容將其追加到 authorized_keys 中
2
cat /mnt/c/Users/v2266/.ssh/id_ed25519.pub >> /home/vinny987/.ssh/authorized_keys # 此處隱去具體路徑

查看 authorized_keys 文件的內容,確認結果:

Terminal window
1
cat /home/vinny987/.ssh/authorized_keys
2
###
3
ssh-ed25519 AAAAC3N************ v2266@vince987

延伸討論

如果想要避免重複追加,可以使用以下指令:

Terminal window
1
grep -q -f /mnt/c/Users/v2266/.ssh/id_ed25519.pub /home/vinny987/.ssh/authorized_keys || \
2
cat /mnt/c/Users/v2266/.ssh/id_ed25519.pub >> /home/vinny987/.ssh/authorized_keys

說明:

  • grep -q:檢查 authorized_keys 中是否已包含該公鑰。
  • ||:如果未找到(即退出狀態非零),則執行 cat 命令追加。

最後,回到 Windows host,測試連線:

Terminal window
1
ssh -i ~/.ssh/id_ed25519 vinny987@192.168.31.6 -p 2222
2
###
3
Welcome 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 目錄是否存在:

Terminal window
1
dir $env:USERPROFILE\.ssh
2
# 不存在的話,使用指令建立目錄
3
mkdir $env:USERPROFILE\.ssh

創建或編輯 config 文件:

Terminal window
1
notepad $env:USERPROFILE\.ssh\config

添加以下內容後儲存:

1
Host mywsl
2
HostName 192.168.36.6
3
User vinny987
4
Port 2222
5
IdentityFile ~/.ssh/id_ed25519

說明:

配置項含義範例
Host配置的別名,用於簡化 SSH 命令。myserver
HostName遠端伺服器的地址(IP 或域名)。192.168.1.100
User登錄使用者名稱。myuser
PortSSH 服務埠(默認為 22)。2222
IdentityFile私鑰文件的路徑,用於身份驗證。~/.ssh/id_ed25519

最後,測試使用組態檔連線:

Terminal window
1
ssh mywsl
2
###
3
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.167.4-microsoft-standard-WSL2 x86_64)
4
[...]

到此,所有的設置就完成了。

測試 VS Code 的 SSH Remote

讓我們來測試看看,我們一開始的問題能否被解決:

default

雖然我們成功進行了 SSH remote,不過 Cascade 還是有些問題,但這就不屬於本章的範疇了。

清除設置

Windows host (系統管理員權限):

Terminal window
1
# 刪除 Port-Forward 規則 (根據 listenaddress 和 listenport 決定刪除哪一條)
2
netsh interface portproxy delete v4tov4 listenaddress=192.168.31.6 listenport=2222
3
# 刪除防火牆規則
4
netsh advfirewall firewall delete rule name="Allow SSH 2222 for LAN"

參考

本文標題:WSL 網絡互聯指南:SSH 遠程訪問的全面配置與安全實踐
文章作者:Vincent Lin
發布時間:2024-11-28