WSL服务器外网访问

实现的基本方法(分步骤)

一、核心原理

通过 Windows 的 netsh 工具建立端口转发规则,并配合防火墙设置,实现外部设备访问 WSL 中运行的服务。

二、操作步骤

  1. 获取 WSL IP 地址

    # 在 WSL 终端执行
    ip addr show eth0 | grep 'inet\b' | awk '{print $2}' | cut -d/ -f1
    
  2. 创建端口转发规则

    # 在 PowerShell 管理员模式执行
    $WSL_IP = "替换为WSL实际IP"
    $port = "目标端口"
    netsh interface portproxy add v4tov4 listenport=$port listenaddress=0.0.0.0 connectport=$port connectaddress=$WSL_IP
    
  3. 配置防火墙规则

    New-NetFirewallRule -DisplayName "Allow WSL Port $port" `
      -Direction Inbound -Action Allow `
      -Protocol TCP -LocalPort $port
    
  4. 验证访问

    浏览器访问 http://[Windows_IP]:[端口]

三、规则管理

  • 🔍 查看所有转发规则

    netsh interface portproxy show all
    
  • 🗑️ 删除转发规则

    netsh interface portproxy delete v4tov4 listenport=端口 listenaddress=0.0.0.0
    
  • 🔧 防火墙规则管理

    # 查看特定端口规则
    Get-NetFirewallPortFilter | Where-Object { $_.LocalPort -eq 3000 }
    
    # 启用/禁用规则
    Enable-NetFirewallRule -DisplayName "Allow WSL Port 3000"
    Disable-NetFirewallRule -DisplayName "Allow WSL Port 3000"
    

四、注意事项

  1. 需使用 管理员权限 运行 PowerShell
  2. WSL IP 可能在每次重启后变化,建议通过脚本自动获取:
$WSL_IP = wsl hostname -I
  1. 开放 0.0.0.0 监听适用于开发环境,生产环境建议更严格的地址限制
  2. 若遇到连接问题,按顺序检查:
    • 端口转发规则是否存在
    • 防火墙是否放行
    • WSL 内部服务是否正常监听

自动化脚本

一、PowerShell 主脚本 Configure-WSL-Port.ps1

注意以gb2312编码保存

<#
.SYNOPSIS
自动化配置WSL端口转发和防火墙规则

.DESCRIPTION
功能包括:
1. 自动获取WSL2 IP地址
2. 创建端口转发规则
3. 配置Windows防火墙
4. 支持多端口批量操作
5. 清理旧规则功能

.PARAMETER Ports
需要转发的端口号(支持逗号分隔多个端口)

.PARAMETER Cleanup
清理模式(删除指定端口规则)

.EXAMPLE
.\Configure-WSL-Port.ps1 -Ports 3000,8080
.\Configure-WSL-Port.ps1 -Ports 3000 -Cleanup
#>

param(
    [Parameter(Mandatory=$true)]
    [string]$Ports,
    [switch]$Cleanup
)

# 管理员权限检查
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
    Write-Host "正在请求管理员权限..." -ForegroundColor Yellow
    Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" -Ports `"$Ports`" $(if($Cleanup){'-Cleanup'})" -Verb RunAs
    exit
}

# 解析端口列表
$portArray = $Ports -split ',' | ForEach-Object { $_.Trim() }

try {
    # 获取WSL IP(自动处理多IP情况)
    $wslIP = (wsl hostname -I) -split '\s+' | Where-Object { $_ -match '\d+\.\d+\.\d+\.\d+' } | Select-Object -First 1
    
    if (-not $wslIP) {
        throw "无法获取WSL IP地址,请确认WSL正在运行"
    }

    Write-Host "`n=== WSL 配置信息 ===" -ForegroundColor Cyan
    Write-Host "检测到 WSL IP: $wslIP" -ForegroundColor Green
    Write-Host "操作模式: $(if($Cleanup){'清理'}else{'配置'})" -ForegroundColor Green
    Write-Host "目标端口: $($portArray -join ', ')`n" -ForegroundColor Green

    foreach ($port in $portArray) {
        if (-not ($port -match '^\d+$' -and [int]$port -ge 1 -and [int]$port -le 65535)) {
            Write-Host "无效端口号: $port" -ForegroundColor Red
            continue
        }

        if ($Cleanup) {
            # 清理模式
            Write-Host "`n正在清理端口 $port ..." -ForegroundColor Yellow
            
            # 删除端口转发
            netsh interface portproxy delete v4tov4 listenport=$port listenaddress=0.0.0.0 2>&1 | Out-Null
            
            # 删除防火墙规则
            $ruleName = "Allow WSL Port $port"
            if (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue) {
                Remove-NetFirewallRule -DisplayName $ruleName
                Write-Host "已删除防火墙规则: $ruleName" -ForegroundColor Magenta
            }
        } else {
            # 配置模式
            Write-Host "`n正在配置端口 $port ..." -ForegroundColor Cyan
            
            # 创建端口转发
            netsh interface portproxy add v4tov4 listenport=$port listenaddress=0.0.0.0 connectport=$port connectaddress=$wslIP
            
            # 创建防火墙规则(如果不存在)
            $ruleName = "Allow WSL Port $port"
            if (-not (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue)) {
                New-NetFirewallRule -DisplayName $ruleName `
                    -Direction Inbound -Action Allow `
                    -Protocol TCP -LocalPort $port | Out-Null
                Write-Host "已创建防火墙规则: $ruleName" -ForegroundColor Magenta
            }
        }
    }

    # 显示最终配置
    Write-Host "`n=== 当前端口转发规则 ===" -ForegroundColor Cyan
    netsh interface portproxy show v4tov4

    Write-Host "`n=== 相关防火墙规则 ===" -ForegroundColor Cyan
    Get-NetFirewallRule -DisplayName "Allow WSL Port*" | Format-Table DisplayName,Enabled,Direction,Action

} catch {
    Write-Host "`n错误发生: $_" -ForegroundColor Red
    exit 1
}

# 显示访问提示(仅配置模式)
if (-not $Cleanup) {
    $localIP = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notmatch 'Loopback' }).IPAddress | Select-Object -First 1
    Write-Host "`n=== 访问提示 ===" -ForegroundColor Cyan
    Write-Host "本地访问: http://localhost:$($portArray[0])"
    Write-Host "网络访问: http://${localIP}:$($portArray[0])" 
    Write-Host "`n请在WSL中运行以下命令验证服务状态:"
    Write-Host "wsl ./check_wsl_port.sh $($portArray[0])" -ForegroundColor Green
# 在退出提示部分可改为:
}
$countdown = 5
while ($countdown -gt 0) {
    Write-Host "`r自动退出倒计时 ${countdown} 秒 (按任意键立即退出)..." -NoNewline -ForegroundColor DarkGray
    if ([Console]::KeyAvailable) { break }
    Start-Sleep -Seconds 1
    $countdown--
}

二、使用指南

1. 保存脚本

将PowerShell脚本保存为 Configure-WSL-Port.ps1

2. 配置端口转发(PowerShell)


# 开放单个端口
.\Configure-WSL-Port.ps1 -Ports 3000

# 批量开放多个端口
.\Configure-WSL-Port.ps1 -Ports "3000, 8080, 8888"

# 清理端口配置
.\Configure-WSL-Port.ps1 -Ports 3000 -Cleanup

3. 检验是否可以连通

略,自行验证即可😁


最后修改于 2025-04-29