把云主机挂成本地盘:WSL + Windows 双端实战

sshfs + systemd 自愈、rclone + WinFsp 挂 Z: 盘,以及那个让 Explorer 看不见盘符的登录会话隔离坑

博客和代理跑在同一台 Azure 小机器上,改文件只能 ssh + vim。于是把它的家目录挂成本地盘:WSL 里是普通路径,Windows 里是盘符。

最终效果:资源管理器里的 Z: 盘

场景方案
终端 / VS CodeWSL:~/remote/vm(sshfs + systemd,断线自愈)
资源管理器Windows:Z: 盘(rclone + WinFsp)

前提:这台机器直连不通——TCP 握手能通,SSH 立刻被 reset,所有流量必须走本机 clash 代理(127.0.0.1:7890)。

架构

WSL 侧:sshfs + systemd 自愈

sshfs 协议成熟、支持断线重连,用起来和本地路径没差别。先让 SSH 走代理:

Host proxy-vm
    HostName 20.48.50.55
    User azureuser
    IdentityFile ~/.ssh/id_rsa
    ProxyCommand nc -X connect -x 127.0.0.1:7890 %h %p

再交给 systemd user 服务托管,断线自动重挂:

# ~/.config/systemd/user/azure-proxy-vm-mount.service
[Unit]
Description=Mount Azure proxy-vm home via SSHFS
StartLimitIntervalSec=0

[Service]
Type=simple
ExecStartPre=-/usr/bin/fusermount3 -uz %h/remote/vm            # 清掉残留挂载
ExecStart=/usr/bin/sshfs proxy-vm:/home/azureuser %h/remote/vm -f \
  -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3
ExecStop=/usr/bin/fusermount3 -u %h/remote/vm
Restart=always
RestartSec=10

[Install]
WantedBy=default.target
systemctl --user enable --now azure-proxy-vm-mount
sudo loginctl enable-linger $USER    # 不登录也保活

实测:kill -9 后 10 秒内自动恢复。

Windows 侧:为什么最后选了 rclone

目标:资源管理器里出现一个盘符。

先试了 SSHFS-Win(WinFsp 上的 sshfs 移植),挂载直接报 read: Connection reset by peer:它不支持 SOCKS 代理,Windows 上也没有 connect / ncat 这类跳板工具,直连又会被 reset。

换成 rclone:自带 SSH 客户端,一行 socks_proxy 就能走 clash,私钥、known_hosts 校验都支持:

# %APPDATA%\rclone\rclone.conf
[azure]
type = sftp
host = 20.48.50.55
user = azureuser
key_file = C:/Users/<用户名>/.ssh/id_rsa
socks_proxy = 127.0.0.1:7890
known_hosts_file = C:/Users/<用户名>/.ssh/known_hosts
rclone mount azure:/home/azureuser Z: --vfs-cache-mode full

盘符出现,Z:\ 也能列目录,但资源管理器里没有。

最大的坑:盘符按登录会话隔离

结论:Windows 的盘符按登录会话隔离。

量一下进程令牌里的 AuthenticationId(登录会话 ID):

会话隔离验证

WSL 的 interop 进程也在同一个 Windows 会话里,但令牌属于另一个登录会话——从那儿挂载的 Z:,Explorer 看不见。

(小坑:GetTokenInformation 的 TokenStatistics 类号是 10,不是 12——12 是 TokenSessionId;AuthenticationId 在结构体偏移 8 字节。)

解法:挂载必须从交互会话启动。两个入口:

  • 计划任务:登录时自动跑(隐藏窗口)
  • azure-vm-remount.cmd:需要手动重挂时双击一下

至此,Z: 可见、可用、可自启。

另一个问题:\\wsl.localhost 看不到 FUSE 挂载

WSL 里挂好了,但从 \\wsl.localhost\Ubuntu\... 访问是空的。

原因:这个入口由 WSL 的 9p 文件服务器提供,只导出 ext4 根文件系统与 /mnt/c 这类 drvfs;FUSE 挂载(sshfs / rclone / NFS / CIFS)一概不导出。这是 WSL 的架构限制,没有开关。

所以 Windows 端要自己挂一份,不能借 WSL 的挂载。

日常使用

systemctl --user restart azure-proxy-vm-mount   # WSL 挂载卡住时
Z:\                                             # Windows 直接访问
C:\Users\<用户名>\bin\azure-vm-remount.cmd      # 重挂
C:\Users\<用户名>\bin\azure-vm-umount.cmd       # 卸载

小结

  • 直连不通就全线走代理:sshfs 用 ProxyCommand,rclone 用 socks_proxy
  • 挂载要有自愈:systemd 的 Restart=always、rclone 的 --vfs-cache-mode
  • 盘符是登录会话级的:务必从交互会话启动挂载,否则 Explorer 看不见
  • \\wsl.localhost 不导出 FUSE 挂载:Windows 端直接另挂一份