在 Windows 11 上搭建开机即连的 WSL + SSH 服务
目标:在 Windows 11 上安装 WSL2 + Ubuntu,将发行版磁盘放到 D 盘,配置 SSH 密钥登录,
并实现开机自动启动、空闲不退出、局域网内随时可远程连接。
- 环境:Windows 11 、WSL 、Ubuntu 26
- 网络模式:mirrored(镜像模式,WSL 与主机共享 IP)
- 认证方式:仅 SSH 密钥(禁用密码登录)
- 数据位置:
D:\xxxxx\
1. 启用 WSL 相关 Windows 功能
wsl --install 在部分网络环境下会因下载渠道(GitHub API)被拦截而报错 403,因此改为分步操作。
以管理员身份执行:
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All -NoRestart
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All -NoRestart
两项功能启用后必须重启系统才生效。
踩坑:
wsl --install报已终止(403),原因是其内部通过api.github.com解析最新版本被拒。
后续改用 winget 的固定 URL 即可绕过。
2. 安装 WSL 应用(绕过 403)
重启后,用 winget 安装 WSL 应用包(MSIX 需要管理员权限,会报 0x80073d28,提权执行即可):
# 管理员 PowerShell
winget install --id Microsoft.WSL --source winget --accept-package-agreements --accept-source-agreements
验证:
wsl --version
wsl --status # 默认版本应为 2
3. 安装 Ubuntu 并迁移到 D 盘
wsl --install -d Ubuntu --no-launch
默认安装在 C 盘用户目录,随后整体迁移(WSL 2.5+ 支持 --move):
wsl --shutdown # 必须先彻底关闭,否则报 ERROR_SHARING_VIOLATION
wsl --manage Ubuntu --move D:\xxxxx\Ubuntu
迁移后发行版磁盘为 D:\xxxxx\Ubuntu\ext4.vhdx,C 盘不再增长。
4. 首次初始化:创建用户与 wsl.conf
全新安装的发行版还没有普通用户,以 root 身份进入并创建:
# 注意:Ubuntu 26.04 中已存在名为 admin 的组,
# 直接 useradd admin 会报 "group admin exists",需用 -g 指定现有组
useradd -m -s /bin/bash -g admin -G sudo,adm admin
echo 'admin:<你的密码>' | chpasswd
cat > /etc/wsl.conf <<'EOF'
[user]
default=admin
[boot]
systemd=true
EOF
要点:
[user] default=admin:wsl启动时默认以此用户登录;[boot] systemd=true:启用 systemd 作为 PID 1,SSH 等服务才能以 systemd 服务方式自启;- 修改后需
wsl --terminate Ubuntu重启发行版生效。
5. 安装并配置 openssh-server
apt-get update
apt-get install -y openssh-server
注意:Ubuntu 26.04 的 sshd 采用 socket 激活(
ssh.socket),安装时会自动创建
ssh.socket/ssh.service的 systemd 链接,监听由 systemd 托管,无需手动service ssh start。
启用并确认:
systemctl enable ssh.socket ssh.service
systemctl restart ssh.socket ssh.service
ss -tlnp | grep ':22' # 应监听 0.0.0.0:22
配置仅密钥登录(drop-in 文件,优先级最高):
cat > /etc/ssh/sshd_config.d/99-wsl.conf <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
EOF
sshd -t # 校验语法
Ubuntu 的
/etc/ssh/sshd_config顶部有Include /etc/ssh/sshd_config.d/*.conf,
因此 drop-in 文件中的设置会覆盖主配置;99-前缀保证最后加载、优先级最高。
6. SSH 密钥登录
在 WSL 内生成密钥对(私钥留在本机用于分发到其他电脑,公钥写入 authorized_keys):
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N '' -C 'wsl-admin'
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
若把私钥导出到 NTFS 分区(如 D 盘)供其他电脑使用,需收紧 ACL,否则 Windows 的 ssh 客户端
会报 UNPROTECTED PRIVATE KEY FILE:
icacls D:\xxxxx\ssh-keys\admin_ed25519 /inheritance:r /grant:r "<你的用户名>:(R)"
在其他电脑上使用:Linux/macOS 需 chmod 600,然后
ssh admin@<主机IP>
7. mirrored 网络模式(关键配置)
Windows 11 22H2+ 支持镜像网络模式,WSL 直接共享主机 IP,重启后地址不变,无需端口转发。
C:\Users\<用户>\.wslconfig:
[wsl2]
networkingMode=mirrored
vmIdleTimeout=-1
[general]
instanceIdleTimeout=-1
[experimental]
hostAddressLoopback=true
| 配置项 | 作用 |
|---|---|
networkingMode=mirrored |
WSL 与主机共享网络接口/IP,局域网可直接访问 |
instanceIdleTimeout=-1 |
关键:禁用发行版空闲自动关闭(默认约 15s 无会话即终止) |
vmIdleTimeout=-1 |
禁用 WSL2 虚拟机空闲关闭 |
hostAddressLoopback=true |
允许主机通过自身 IP 访问 WSL 服务(仅 IPv4) |
踩坑:即使启用了 systemd,WSL 2.6+ 仍会在最后一个会话结束后约 15 秒终止发行版实例,
systemd 服务不能阻止该行为。必须设置instanceIdleTimeout=-1才能常驻。
8. 防火墙放行 22 端口
mirrored 模式下有两层防火墙,两层都要放行:
# 1) Windows 防火墙
New-NetFirewallRule -DisplayName 'WSL Ubuntu SSH (TCP 22)' -Direction Inbound `
-Protocol TCP -LocalPort 22 -Action Allow -Profile Any
# 2) Hyper-V 防火墙(WSL 虚拟机的默认入站策略是 Block,只默认放行 ICMP/mDNS)
New-NetFirewallHyperVRule -Name 'WSL SSH 22' -DisplayName 'WSL SSH 22' `
-Direction Inbound -VMCreatorId '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' `
-Protocol TCP -LocalPorts 22 -Action Allow
踩坑:只加 Windows 防火墙规则仍会连接超时,因为 Hyper-V 防火墙的
DefaultInboundAction为Block,需要单独创建 Hyper-V 防火墙规则。
9. 开机自启(计划任务)
创建开机自动拉起 WSL的计划任务,使远程连接无需等待本地用户登录:
$action = New-ScheduledTaskAction -Execute 'C:\Program Files\WSL\wsl.exe' `
-Argument '-d Ubuntu --exec /bin/true'
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries -ExecutionTimeLimit ([TimeSpan]::Zero) `
-RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -MultipleInstances IgnoreNew
$principal = New-ScheduledTaskPrincipal -UserId "$env:COMPUTERNAME\$env:USERNAME" `
-LogonType S4U -RunLevel Highest
Register-ScheduledTask -TaskName 'WSL Ubuntu Boot' -Action $action -Trigger $trigger `
-Settings $settings -Principal $principal -Force
要点:
-AtStartup+LogonType S4U:开机即运行,且无需用户登录、无需存储账户密码;- 动作只是
wsl -d Ubuntu --exec /bin/true,执行后即退出,发行版由 systemd 持续运行; - 配合
instanceIdleTimeout=-1,发行版从此常驻。
10. 验证
# 模拟重启:关闭后手动触发任务
wsl --shutdown
Start-ScheduledTask -TaskName 'WSL Ubuntu Boot'
wsl -l -v # 状态应为 Running
# 端口与登录
Test-NetConnection <主机IP> -Port 22
ssh -i <私钥> admin@<主机IP> 'whoami; hostname'
# 确认密码登录已被拒绝(应返回 Permission denied (publickey))
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no admin@<主机IP> true
11. 最终结构
Windows 侧
├─ C:\Users\<用户>\.wslconfig # 全局:mirrored 网络、空闲不关闭、hostAddressLoopback
├─ D:\xxxxx\
│ ├─ Ubuntu\ext4.vhdx # Ubuntu 发行版磁盘(不再占用 C 盘)
│ └─ ssh-keys\ # 导出的密钥对(需收紧 ACL)
├─ 防火墙规则:WSL Ubuntu SSH (TCP 22) # Windows 防火墙
├─ Hyper-V 防火墙规则:WSL SSH 22 # Hyper-V 防火墙
└─ 计划任务:WSL Ubuntu Boot # 开机自启(AtStartup + S4U)
WSL 侧(Ubuntu)
├─ /etc/wsl.conf # default 用户 + systemd
├─ /etc/ssh/sshd_config.d/99-wsl.conf # 仅密钥登录、禁 root
└─ ~/.ssh/authorized_keys # 公钥
12. 踩坑速查表
| 现象 | 原因 | 解决 |
|---|---|---|
wsl --install 报 403 |
内部走 api.github.com 被拦截 |
改用 winget 安装 WSL 应用 |
winget 安装报 0x80073d28 |
MSIX 需要管理员权限 | 提权执行 winget |
--move 报 ERROR_SHARING_VIOLATION |
WSL 未彻底关闭 | 先 wsl --shutdown 再移动 |
useradd admin 报组已存在 |
Ubuntu 26.04 自带 admin 组 |
用 -g admin 指定现有组 |
| 空闲约 15s 后发行版停止 | WSL 实例空闲自动终止 | .wslconfig 中 instanceIdleTimeout=-1 |
| 主机用自身 IP 连不上 | mirrored 模式默认不回环主机 IP | [experimental] hostAddressLoopback=true |
| 局域网连接超时 | Hyper-V 防火墙默认入站 Block | 添加 New-NetFirewallHyperVRule 规则 |
| 私钥在 NTFS 上被 ssh 拒绝 | NTFS 默认权限过宽 | icacls 收紧或 chmod 600 |
13. 备注
- mirrored 模式下 WSL 与主机共享 IP,IP 由路由器 DHCP 分配,建议在路由器中为
主机绑定静态 IP(或 DHCP 保留),避免地址变化; - 若需修改 WSL 内用户密码:
passwd; - 如需取消常驻,将
.wslconfig中的instanceIdleTimeout删除并删除计划任务即可。