主页 HomePage

260816-WSL Mirrored Networking 外部端口访问:排障与运行原理

本文用于归档 Windows 11 + WSL2 networkingMode=mirrored 场景下, “WSL 内服务正常,但从局域网或其他外部主机访问 Windows 主机 IP 的某个端口失败”时的排障方法, 并解释数据包从外部主机进入 WSL 服务时的实际网络路径。

核心结论: 外部客户端访问的是 Windows 主机对外可达的 IP:Port; mirrored networking 再把适合 WSL 的入站流量引导到 WSL。 一个 WSL 服务从外部访问不通时,应依次检查: 服务监听地址 → Windows 端口冲突 → Hyper-V Firewall → Host Firewall 策略合并 → Linux Firewall。

一、适用前提

本文假设:

[wsl2]
networkingMode=mirrored
firewall=true

修改 .wslconfig 后需要让 WSL2 VM 完全重启,例如:

wsl --shutdown

二、推荐排障顺序

假设目标为:

Windows LAN IP : 192.168.1.50
WSL 服务端口   : TCP 22
外部客户端     : 192.168.1.100

客户端执行:

ssh user@192.168.1.50

如果连接失败,按以下顺序排查。

1. 确认 WSL 服务确实在正确地址监听

在 WSL 内:

ss -lntp

对于 SSH,希望看到类似:

LISTEN ... 0.0.0.0:22

或者 IPv6 listener:

LISTEN ... [::]:22

如果只有:

127.0.0.1:22

则服务只接受 WSL 本机 loopback 连接,外部主机本来就无法访问。

同时在 WSL 内进行本机验证:

curl http://127.0.0.1:PORT

或者 SSH:

ssh user@127.0.0.1
如果这一步失败,应先修复 Linux 服务本身,不需要继续检查 Windows 网络层。

2. 检查 Windows 是否已经监听同一端口

在 Windows PowerShell 中:

Get-NetTCPConnection -State Listen |
    Where-Object LocalPort -eq 22

也可以使用:

netstat -ano | findstr :22

mirrored networking 与 NAT + portproxy 不同。 外部访问通常使用 Windows 主机地址和相同端口号, 因此 Windows 侧已有服务占用该端口时应首先视为潜在冲突。

例如:

Windows OpenSSH Server :22
WSL sshd              :22

这种设计容易产生冲突。

更清晰的设计:

Windows OpenSSH Server :22
WSL sshd              :2222

外部访问:

ssh windows-user@192.168.1.50 -p 22
ssh linux-user@192.168.1.50 -p 2222
ignoredPorts 不是通用的“Windows 与 WSL 对外共享同一个端口”的方案。 它允许 Linux 在某些 Windows 已使用的端口上绑定,但微软文档明确说明, 这种能力主要用于 Linux 内部流量等特殊场景。

3. 检查 Hyper-V Firewall 的 WSL effective policy

WSL 的 VMCreatorId:

{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}

查看实际生效设置:

$WslId = '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}'

Get-NetFirewallHyperVVMSetting `
    -PolicyStore ActiveStore `
    -Name $WslId |
    Format-List

重点关注:

查看针对 WSL 的 Hyper-V Firewall 规则:

Get-NetFirewallHyperVRule -VMCreatorId $WslId

例如明确允许 SSH:

New-NetFirewallHyperVRule `
    -Name 'WSL-SSH' `
    -DisplayName 'WSL SSH' `
    -Direction Inbound `
    -VMCreatorId $WslId `
    -Protocol TCP `
    -LocalPorts 22 `
    -Action Allow

如果只希望局域网访问,可进一步限制来源:

New-NetFirewallHyperVRule `
    -Name 'WSL-SSH-LAN' `
    -DisplayName 'WSL SSH from LAN' `
    -Direction Inbound `
    -VMCreatorId $WslId `
    -Protocol TCP `
    -LocalPorts 22 `
    -RemoteAddresses '192.168.1.0/24' `
    -Action Allow

4. 检查 Windows Firewall 策略是否被合并到 Hyper-V policy

如果 WSL 的 Hyper-V Firewall 设置中:

AllowHostPolicyMerge = True

则符合条件的 Windows Host Firewall 策略可以参与 WSL 的 Hyper-V effective policy。 这不应理解成“数据包一定先经过一次 Windows Firewall,再经过一次 Hyper-V Firewall”, 而应理解成: Windows Host Firewall 的部分策略可以被合并进 Hyper-V Firewall 的最终判定策略。

因此应检查 Windows Firewall 中是否存在与目标端口、协议、网络 Profile、来源地址相关的显式阻断规则。

可以先查看当前 Windows 网络 Profile:

Get-NetConnectionProfile

特别留意当前网络是 Public、Private 还是 DomainAuthenticated。 某些规则只在指定 Profile 下生效。

查询 Windows 防火墙中与本地 TCP 22 端口相关的规则,可以使用:

Get-NetFirewallRule -Enabled True |
    Get-NetFirewallPortFilter |
    Where-Object {
        $_.Protocol -eq 'TCP' -and
        ($_.LocalPort -eq '22' -or $_.LocalPort -eq 'Any')
    }
Host Policy Merge 的重点是“策略来源合并”,而不是把 Windows Firewall 想象成 WSL 流量前面必然串联的一台独立防火墙。

5. 检查 WSL 内部 Linux Firewall

Ubuntu 使用 UFW 时:

sudo ufw status verbose

如果需要允许 SSH:

sudo ufw allow 22/tcp

查看 nftables:

sudo nft list ruleset

仍使用 iptables 的系统:

sudo iptables -L -n -v

即使 Hyper-V Firewall 已经允许数据包进入 WSL, Linux 自己的 nftables / UFW / iptables 仍然可以再次丢弃该连接。

三、完整排障检查表

顺序 检查对象 典型问题 主要命令
1 WSL 服务监听 服务未启动;只监听 127.0.0.1;端口错误 ss -lntp
2 Windows 端口占用 Windows 自己的程序已监听同一端口 Get-NetTCPConnection
3 Hyper-V Firewall 默认入站 Block;没有 Allow rule;存在 Block rule Get-NetFirewallHyperVVMSetting
Get-NetFirewallHyperVRule
4 Host Policy Merge Windows Firewall 中可合并的规则阻断流量 AllowHostPolicyMerge
Get-NetFirewallRule
5 Linux Firewall UFW / nftables / iptables 阻断 ufw status
nft list ruleset
6 外部网络 路由、VLAN、AP isolation、上游防火墙等 Test-NetConnection / nc / ssh -v

四、mirrored networking 的网络运行原理

1. NAT 模式与 mirrored 模式的根本区别

传统 WSL2 NAT 模式可抽象为:

LAN
 │
 ▼
Windows
192.168.1.50
 │
 │ NAT
 ▼
WSL 私有虚拟网络
172.x.x.x
 │
 ▼
Linux 服务

WSL 位于 Windows 后方的私有 NAT 网络中。 LAN 主机通常不能直接访问 WSL 私有地址,因此经常需要端口转发。

mirrored networking 则更接近:

Windows 上的 Wi-Fi / Ethernet / VPN / IPv6 网络环境
                     │
                     │ mirror / traffic steering
                     ▼
                WSL2 networking
                     │
                     ▼
                Linux application

Windows 网络接口环境被镜像到 Linux, 并由 Windows / WSL / Hyper-V 网络基础设施负责将适当的流量引导给 WSL。 它不是传统意义上的桥接虚拟机,也不是简单 NAT。

2. 外部主机访问的是谁的 IP?

假设:

Windows IP = 192.168.1.50
WSL sshd   = TCP 22

外部客户端发送:

dst = 192.168.1.50:22

因此从外部网络的视角, 访问的始终是Windows 主机对外可达的地址。

但该流量到达 Windows 后,如果属于可以被 mirrored networking 导向 WSL 的流量,则:

外部客户端
192.168.1.100
     │
     │ TCP 192.168.1.50:22
     ▼
Windows 物理/无线网卡
     │
     ▼
WSL mirrored traffic steering
     │
     ▼
Hyper-V Firewall effective policy
     │
     ▼
WSL Linux 网络栈
     │
     ▼
Linux firewall
     │
     ▼
sshd :22

因此“外部访问 Windows_IP:22”与“最终由 WSL sshd 接收该连接”并不矛盾。

3. 为什么 Windows 与 WSL 端口冲突需要单独检查?

因为外部客户端只有一个目标:

Windows_IP:Port

如果 Windows 主机自身已经有一个服务占用了相同端口, 则这个端口已经存在明确的 Windows endpoint。 mirrored networking 并不是设计用来让两个互相独立的对外服务无条件共享同一个 IP:Port。

因此最清晰的设计是:

Windows 服务 → 使用自己的端口
WSL 服务     → 使用不同的端口

4. Hyper-V Firewall 在哪里工作?

Hyper-V Firewall 用于过滤 Windows 托管虚拟化环境或容器的网络流量, WSL2 属于它的适用对象。

对于进入 WSL 的连接,可概念化为:

mirrored traffic
      │
      ▼
Hyper-V Firewall
      │
      ├─ Hyper-V-specific rules
      ├─ DefaultInboundAction
      └─ 可合并的 Host Firewall policy
      │
      ├─ Block → DROP
      └─ Allow
           │
           ▼
        WSL Linux

这就是为什么 WSL 内服务正常、Linux firewall 也允许, 但 Hyper-V Firewall 没放行时,外部仍然连接不上。

5. Windows Firewall 与 Hyper-V Firewall 不是简单串联关系

不应简单画成:

packet
  ↓
Windows Firewall
  ↓
Hyper-V Firewall
  ↓
WSL

更准确的是:

Hyper-V 专用策略 ──────────┐
                           │
可适用的 Windows Host FW ──┼──→ Hyper-V effective policy
                           │
GPO / MDM 等策略 ──────────┘
                                  │
                                  ▼
                              WSL traffic

当 AllowHostPolicyMerge=True 时, Windows Host Firewall 中符合条件的策略可以被合并进 Hyper-V Firewall 的 effective policy。 因此排障时必须同时考虑两类规则来源。

6. Linux Firewall 是最后一道独立的 Linux 网络过滤

数据包通过 Windows / Hyper-V 层后,进入的是正常 Linux 网络栈:

Hyper-V Firewall
      │
      ▼
Linux IP/TCP stack
      │
      ▼
nftables / UFW / iptables
      │
      ▼
socket
      │
      ▼
application

因此 Linux 防火墙与 Hyper-V Firewall 是两个真正不同的过滤域。 前者属于 WSL 内 Linux,后者属于 Windows/Hyper-V 虚拟化网络基础设施。

7. 最终应记住的端到端模型

外部主机
   │
   │  Windows_IP:Port
   ▼
Windows 网卡
   │
   ├─ Windows 本机 endpoint?
   │
   └─ mirrored WSL traffic?
             │
             ▼
      Hyper-V Firewall
             │
             ├─ Hyper-V rules
             ├─ Default policy
             └─ merged Host Firewall policy
             │
             ▼
       WSL Linux 网络栈
             │
             ▼
      nftables / UFW
             │
             ▼
       Linux application

五、SSH 示例

推荐配置:

# %UserProfile%\.wslconfig

[wsl2]
networkingMode=mirrored
firewall=true

WSL:

sudo systemctl enable ssh
sudo systemctl start ssh

ss -lntp | grep ':22'

Windows 管理员 PowerShell:

$WslId = '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}'

New-NetFirewallHyperVRule `
    -Name 'WSL-SSH-LAN' `
    -DisplayName 'WSL SSH from LAN' `
    -Direction Inbound `
    -VMCreatorId $WslId `
    -Protocol TCP `
    -LocalPorts 22 `
    -RemoteAddresses '192.168.1.0/24' `
    -Action Allow

外部客户端:

ssh user@192.168.1.50

六、故障定位的最短记忆法

WSL 端口从外部访问不通:
① 服务是否监听 0.0.0.0 / 合适的 IPv6 地址
② Windows 是否占用该端口
③ Hyper-V Firewall 是否允许
④ Windows Host Firewall 是否有被 merge 的阻断策略
⑤ Linux UFW / nftables / iptables 是否允许
⑥ 再检查 LAN、VLAN、路由器、上游防火墙

七、官方参考资料

本文针对 mirrored networking 场景。WSL、Windows Firewall 与 Hyper-V Firewall 的实现和默认行为可能随 Windows / WSL 版本更新, 归档长期使用时应优先以 Microsoft Learn 当前文档为准。