Last active
September 29, 2025 14:03
-
-
Save hunandy14/01fca30548ec12a6d733931c6a2083d8 to your computer and use it in GitHub Desktop.
建立 Windows 到 WSL 的端口轉發
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| 建立 Windows 到 WSL 的端口轉發 | |
| .DESCRIPTION | |
| 此函數會建立從 Windows IP 到 WSL IP 的端口轉發規則, | |
| 允許外部連線透過 Windows 主機連接到 WSL 內的服務。 | |
| .PARAMETER ListenPort | |
| Windows 端監聽的端口號 | |
| .PARAMETER ConnectPort | |
| WSL 端連接的端口號 | |
| .PARAMETER Force | |
| 跳過確認提示,直接執行 | |
| .EXAMPLE | |
| Set-WSLPortForward -ListenPort 22 -ConnectPort 22 | |
| 建立 SSH 轉發 (22 → 22) | |
| .EXAMPLE | |
| Set-WSLPortForward -ListenPort 8080 -ConnectPort 80 -Force | |
| 建立 HTTP 轉發 (8080 → 80) 並跳過確認提示 | |
| .NOTES | |
| 需要以管理員權限執行 | |
| #> | |
| function Set-WSLPortForward { | |
| [CmdletBinding()] | |
| param( | |
| [Parameter( | |
| Position = 0, | |
| HelpMessage = "Port number for Windows to listen on" | |
| )] [ValidateRange(1, 65535)] [Alias("LP", "Listen")] | |
| [int]$ListenPort, | |
| [Parameter( | |
| Position = 1, | |
| HelpMessage = "Port number to connect to in WSL" | |
| )] [ValidateRange(1, 65535)] [Alias("CP", "Connect")] | |
| [int]$ConnectPort = 22, | |
| [Parameter( | |
| HelpMessage = "Skip confirmation prompt" | |
| )] [Alias("F")] | |
| [switch]$Force | |
| ) | |
| # 取得 WSL 主機名稱和 IP 地址 | |
| $w = (wsl hostname -I).Split()[0] | |
| $e = (Get-NetIPConfiguration | Where-Object { $_.IPv4DefaultGateway -and $_.NetAdapter.Status -eq "Up" }).IPv4Address.IPAddress | Select-Object -First 1 | |
| # 如果 WSL 和 Windows 使用相同的 IP 地址,則不需要轉發 | |
| if (!$e -or $w -eq $e) { Write-Host "WSL and Windows share the same IP, no port forwarding needed" -ForegroundColor Yellow; return } | |
| # 顯示轉發規則 | |
| Write-Host "`nSetting up port forwarding:" -ForegroundColor Yellow | |
| Write-Host " External connection ${e}:${ListenPort} → Forward to WSL ${w}:${ConnectPort}" | |
| # 等待確認執行 (除非使用 -Force 參數) | |
| if ($Force -or (Read-Host "`nConfirm execution? (Y/N)") -eq 'Y') { | |
| # netsh 透明代理函數 | |
| function Invoke-Netsh { | |
| param( | |
| [Parameter(ValueFromRemainingArguments)] | |
| [string[]]$Arguments | |
| ) | |
| # 保存原始編碼 | |
| $originalEncoding = $global:OutputEncoding | |
| $originalInputEncoding = [console]::InputEncoding | |
| $originalOutputEncoding = [console]::OutputEncoding | |
| # 切換為原始編碼 | |
| $global:OutputEncoding=[console]::InputEncoding=[console]::OutputEncoding = [Text.Encoding]::UTF8 | |
| # 執行 netsh 命令 | |
| try { | |
| $result = & netsh @Arguments 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Error ($result -join "`n"); return | |
| } else { Write-Output $result } | |
| } | |
| # 恢復原始編碼 | |
| finally { | |
| $global:OutputEncoding = $originalEncoding | |
| [console]::InputEncoding = $originalInputEncoding | |
| [console]::OutputEncoding = $originalOutputEncoding | |
| } | |
| } | |
| try { | |
| # 刪除現有規則 | |
| Invoke-Netsh interface portproxy delete v4tov4 "listenaddress=$e" "listenport=$ListenPort" -ErrorAction Stop | |
| # 建立新的轉發規則 | |
| Invoke-Netsh interface portproxy add v4tov4 "listenaddress=$e" "listenport=$ListenPort" "connectaddress=$w" "connectport=$ConnectPort" -ErrorAction Stop | |
| # 顯示轉發規則 | |
| Invoke-Netsh interface portproxy show v4tov4 | |
| } catch { Write-Error $_ } | |
| } else { | |
| Write-Host "`nOperation cancelled" -ForegroundColor Yellow | |
| } | |
| } # Set-WSLPortForward -ListenPort 22 -ConnectPort 22 -Force |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment