1. 为什么要在WSL里折腾SSH?
如果你和我一样,日常工作离不开Windows,但开发、运维的“主战场”又在Linux,那么Windows Subsystem for Linux(WSL)绝对是个神器。它让你能在Windows里无缝运行一个完整的Linux发行版,文件系统互通,性能损耗极低,用起来比虚拟机爽快得多。但不知道你有没有遇到过这样的场景:你正在WSL的Ubuntu里调试一个Web服务,或者跑着一个数据库,突然需要从另一台机器(比如公司的测试服务器、家里的另一台电脑,甚至是你自己的手机)去访问这个服务。或者,你希望用更专业的终端工具(比如MobaXterm、Xshell)来连接WSL,以获得比Windows Terminal更强大的会话管理、SFTP文件传输、端口转发等功能。
这时候,一个最直接的想法就是:能不能像连接一台远程Linux服务器一样,用SSH连接到我的WSL?答案是肯定的,而且配置起来并不复杂。但这个过程里藏着不少“坑”,比如WSL2独特的网络架构、SSH服务自启动问题、密钥配置的细节,还有如何优雅地处理动态IP。今天,我就结合自己多次配置的经验,手把手带你走通从零配置WSL SSH服务,到用各种主流工具(MobaXterm, Xshell, VSCode Remote)稳定连接的完整流程,并分享几个提升体验的关键技巧。
2. 环境准备与SSH服务端安装
在开始之前,我们需要一个运行中的WSL环境。如果你还没有安装,最推荐的方式是打开Windows PowerShell(管理员),直接运行wsl --install。这个命令默认会安装Ubuntu发行版。如果速度慢,可以参考网络上的教程更换安装源。安装完成后,启动你的WSL发行版(比如Ubuntu),我们就进入了Linux环境。
2.1 更新系统与安装OpenSSH服务端
进入WSL终端后,第一件事是更新软件包列表并升级现有软件,确保我们在一个稳定的基础上操作。
sudo apt update && sudo apt upgrade -y接下来,安装OpenSSH的服务端组件。在Ubuntu中,这个包通常叫openssh-server。
sudo apt install openssh-server -y安装完成后,SSH服务(sshd)并不会自动启动。我们需要先启动它,并设置为开机自启。但在WSL里,“开机自启”有点特殊,我们稍后再讨论。
2.2 关键配置文件解析与修改
SSH服务器的行为主要由/etc/ssh/sshd_config文件控制。在修改前,我强烈建议先备份原文件。
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup现在用nano或vim编辑配置文件:
sudo nano /etc/ssh/sshd_config我们需要关注并修改以下几个关键参数,它们直接关系到连接的成功与安全:
Port: 默认是22。在WSL里,22端口通常没有被占用,可以保留。但如果你Windows主机上跑了其他SSH服务(比如Git for Windows的SSH),可能会冲突,可以改为其他端口,如2222。ListenAddress: 默认是0.0.0.0,表示监听所有网络接口。这很重要,确保SSH服务能接受来自Windows主机(以及网络内其他机器)的连接。PasswordAuthentication: 默认是yes。为了安全,后期我们配置好密钥后,可以将其改为no,禁用密码登录。但初次配置时,建议先保持yes,方便测试。PermitRootLogin: 默认是prohibit-password。这允许root用户使用密钥登录,但禁止密码登录。对于WSL个人开发环境,这个设置比较合适。绝对不要设为yes。PubkeyAuthentication: 确保是yes。这是启用密钥认证的关键。
一个针对WSL环境优化后的配置片段示例如下:
Port 22 ListenAddress 0.0.0.0 PasswordAuthentication yes # 测试阶段打开,密钥配置好后可关闭 PermitRootLogin prohibit-password PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2修改完成后,保存退出。然后重启SSH服务以使配置生效:
sudo service ssh restart # 或者使用 systemctl(如果WSL发行版支持) sudo systemctl restart ssh注意:在部分WSL2发行版中,
systemctl可能无法直接使用。如果遇到System has not been booted with systemd错误,使用service命令是更通用的做法。
3. WSL2网络特性与防火墙配置
这是连接WSL最容易踩坑的地方。WSL2采用了一种虚拟化技术,其网络模式与WSL1(直接翻译层)有本质不同。
3.1 理解WSL2的虚拟网络
WSL2实例运行在一个轻量级的Hyper-V虚拟机上。这意味着WSL2拥有一个独立的、动态分配的虚拟网络接口(vEthernet)和IP地址。这个IP地址属于一个与Windows主机不同的网络段。简单来说:
- WSL2内部:有一个
eth0接口,IP地址类似172.x.x.x。 - Windows主机:会有一个对应的
vEthernet (WSL)虚拟网卡,也有一个同网段的IP。 - 关键点:WSL2的IP地址不是固定的!每次重启WSL,或者电脑休眠唤醒,这个IP都可能变化。这会给SSH连接带来麻烦。
首先,在WSL内部查看你的IP地址:
ip addr show eth0你会看到类似inet 172.27.112.164/20的输出。这个172.27.112.164就是WSL2当前的内部IP。
3.2 配置Windows防火墙入站规则
默认情况下,Windows防火墙会阻止外部(包括Windows自己)对WSL2虚拟网络端口的访问。我们需要手动添加一条规则放行SSH端口。
- 以管理员身份打开Windows PowerShell。
- 运行以下命令,添加一条针对特定端口(例如22)的入站规则:
New-NetFirewallRule -DisplayName "WSL2 SSH Port 22" -Direction Inbound -LocalPort 22 -Protocol TCP -Action Allow如果你修改了SSH端口(比如2222),则将命令中的-LocalPort 22替换为-LocalPort 2222。
这条规则创建后,Windows主机就可以访问WSL2内部的22端口了。你可以从Windows的命令提示符或PowerShell测试连通性:
# 先获取WSL2的IP,假设你的发行版叫 Ubuntu $wsl_ip = (wsl -d Ubuntu hostname -I).Trim() Test-NetConnection -ComputerName $wsl_ip -Port 22如果显示TcpTestSucceeded : True,恭喜你,防火墙和SSH服务基本通了。
3.3 解决动态IP问题:从Windows主机连接
由于WSL2的IP会变,每次连接前都去WSL里查IP太麻烦。这里有两个更优雅的解决方案:
方案一:使用localhost转发(推荐)这是WSL2提供的一个便利功能。Windows主机可以通过localhost直接访问WSL2中监听端口的服务。但需要确保你在Windows的%USERPROFILE%\.wslconfig文件中启用了该功能(通常默认是开启的)。这意味着,在Windows上,你可以直接用ssh username@localhost来连接WSL,端口映射会自动完成。这是最稳定、最推荐的方式。
方案二:使用Windows主机名在WSL2中,Windows主机有一个特殊的DNS名称host.docker.internal(最初为Docker设计,但WSL2也可用)。反过来,从Windows访问WSL,我们可以利用WSL2实例的主机名。在WSL中运行hostname获取主机名(比如MyUbuntuPC),然后在Windows的C:\Windows\System32\drivers\etc\hosts文件中添加一行映射(需要管理员权限编辑):
127.0.0.1 MyUbuntuPC这样,在Windows终端就可以用ssh username@MyUbuntuPC连接了。但这个方法在IP变化时,hosts文件需要更新,略显繁琐。
方案三:编写脚本动态获取IP(进阶)对于需要自动化脚本的场景,可以在Windows PowerShell中写一个小函数,动态获取IP并连接:
function ssh-wsl { $wsl_ip = (wsl -d Ubuntu hostname -I).Trim() if ($wsl_ip) { ssh username@$wsl_ip } else { Write-Error "无法获取WSL IP地址" } }将username和Ubuntu替换成你的实际用户名和发行版名称。之后在PowerShell中直接运行ssh-wsl即可。
4. 使用主流SSH客户端进行连接
服务端和网络搞定后,我们就可以在客户端愉快地连接了。Windows下有很多优秀的SSH客户端。
4.1 使用Windows内置的OpenSSH客户端
Windows 10/11 现在内置了OpenSSH客户端。你可以在PowerShell或CMD中直接使用ssh命令。这是最轻量、最原生的方式。
# 使用 localhost 连接(最推荐) ssh your_wsl_username@localhost # 或者使用动态获取的IP(需要先获取IP) ssh your_wsl_username@172.27.112.164首次连接时会询问是否信任主机密钥,输入yes即可。然后输入你的WSL用户密码。
4.2 使用MobaXterm连接
MobaXterm是我非常喜欢的全能终端,它集成了SFTP、X11转发、多标签等强大功能。
- 启动MobaXterm,点击左上角的Session按钮。
- 在弹出的窗口中选择SSH。
- 在Remote host栏填写
localhost(或WSL2的IP)。 - Specify username处勾选,并填入你的WSL用户名。
- 端口保持22(如果你修改过则填修改后的端口)。
- 点击OK。
首次连接同样需要接受主机密钥,然后输入密码。连接成功后,你会在左侧看到WSL的文件系统树(SFTP面板),可以直接拖拽文件,非常方便。
MobaXterm中文设置小技巧:如果你需要中文界面,下载安装时选择“便携版”,解压后运行主程序。在菜单栏选择Settings -> Configuration -> General,在Language下拉框中选择“Chinese (Simplified)”,重启即可。注意,安装版可能没有中文语言包。
4.3 使用Xshell连接
Xshell以其强大的会话管理和出色的性能著称,个人和学校用户可以免费使用。
- 打开Xshell,点击菜单栏的文件 -> 新建。
- 在“连接”选项卡中:
- 名称: 给这个会话起个名字,如“My WSL”。
- 协议: 选择SSH。
- 主机: 填写
localhost(或WSL2的IP)。 - 端口号: 22。
- 点击左侧用户身份验证:
- 方法: 选择Password(初次连接)。
- 用户名: 填写你的WSL用户名。
- 密码: 可以留空,每次连接时输入;也可以保存(安全性稍低)。
- 点击连接,接受主机密钥,输入密码即可。
Xshell中文字体优化:如果终端显示中文乱码或字体不好看,可以在会话属性中设置。右键会话 -> 属性,在终端 -> 编码选择Unicode (UTF-8),在外观 -> 字体选择一个支持中文的等宽字体,如“等距更纱黑体 SC Nerd Font”或“Microsoft YaHei Mono”。
4.4 配置SSH密钥登录(免密码)
长期使用密码登录既麻烦又不安全。配置SSH密钥登录是必做的一步。
第一步:在Windows客户端生成密钥对如果你使用MobaXterm或Xshell,它们都内置了密钥生成工具。这里以Windows OpenSSH客户端为例,在PowerShell中操作:
# 在Windows用户目录下的.ssh文件夹生成密钥,默认是RSA 3072位 ssh-keygen -t rsa -b 3072按照提示,选择密钥保存路径(默认按回车即可),设置一个密钥密码(可选,为空则免密码使用密钥)。
完成后,会在C:\Users\你的用户名\.ssh\下生成两个文件:id_rsa(私钥,务必保管好)和id_rsa.pub(公钥)。
第二步:将公钥上传到WSL将公钥内容追加到WSL对应用户的~/.ssh/authorized_keys文件中。
# 在WSL中,确保.ssh目录存在且权限正确 mkdir -p ~/.ssh chmod 700 ~/.ssh touch ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys # 然后,你需要将 Windows 下 id_rsa.pub 文件的内容复制进来。 # 一个简单的方法是:在Windows PowerShell中显示公钥内容,然后复制。 cat /mnt/c/Users/你的Windows用户名/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys或者,你可以用文本编辑器打开Windows的id_rsa.pub,复制全部内容,然后在WSL中执行nano ~/.ssh/authorized_keys,粘贴到文件末尾。
第三步:测试密钥登录回到Windows PowerShell,尝试连接:
ssh your_wsl_username@localhost如果配置正确,它会直接使用密钥登录,无需输入密码(如果你设置了密钥密码,则需要输入)。
第四步:禁用密码登录(可选但推荐)密钥登录成功后,为了安全,可以修改WSL中的/etc/ssh/sshd_config,将PasswordAuthentication设为no,然后重启SSH服务。
sudo sed -i 's/^#*PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config sudo service ssh restart5. 高级应用与集成场景
基础的SSH连接建立后,我们可以玩一些更高级的用法。
5.1 使用VSCode Remote-SSH进行开发
这是“杀手级”应用。VSCode的Remote-SSH扩展允许你直接打开WSL中的文件夹进行开发,享受完整的IDE功能,就像在本地一样。
- 在VSCode中安装Remote - SSH扩展。
- 点击左下角的绿色远程连接按钮,选择Connect to Host... -> Add New SSH Host...。
- 输入连接命令:
ssh your_wsl_username@localhost。 - 根据提示选择SSH配置文件路径(默认即可)。
- 在出现的远程主机列表中,选择
localhost。 - 第一次连接会打开一个新的VSCode窗口(远程窗口)。在顶部选择平台为Linux。
- 连接成功后,你就可以通过文件 -> 打开文件夹来浏览和打开WSL中的任何目录进行编辑和调试了。所有插件和终端都会在远程环境中运行。
5.2 配置SSH服务在WSL启动时自动运行
WSL的一个特点是,它的“系统”并不随Windows开机而自动启动。我们需要在Windows侧做一些配置。
方法一:使用wsl.conf配置(部分发行版支持)在WSL中创建或编辑/etc/wsl.conf文件:
sudo nano /etc/wsl.conf添加以下内容:
[boot] command="service ssh start"这样,每次启动WSL实例时,它会自动执行这个命令来启动SSH服务。但注意,这需要你的发行版支持systemd或service命令在启动时运行。
方法二:创建Windows任务计划程序(更通用可靠)这是我最推荐的方法,它确保每当WSL启动时,SSH服务都能运行。
- 在Windows搜索“任务计划程序”,以管理员身份打开。
- 点击右侧创建任务。
- 常规选项卡:给任务起名,如“Start WSL SSH”,勾选使用最高权限运行。
- 触发器选项卡:点击新建,选择在发生事件时,日志:Microsoft-Windows-Subsystem-Linux/Operational,源:WSL,事件ID:1(这对应WSL发行版启动)。你也可以添加一个“登录时”或“工作站解锁时”的触发器作为备份。
- 操作选项卡:点击新建,操作:启动程序。
- 程序或脚本:
C:\Windows\System32\wsl.exe - 参数:
-d Ubuntu -u root service ssh --full-restart(将Ubuntu替换为你的发行版名称)
- 程序或脚本:
- 条件选项卡:取消勾选只有在计算机使用交流电源时才启动此任务和只有在以下网络连接可用时才启动,避免因条件不满足而不执行。
- 设置选项卡:可以根据需要调整,比如允许按需运行、如果任务失败重启等。
- 点击确定,输入管理员密码。
这样,每当你的WSL发行版启动,SSH服务就会被自动重启,确保可用。
5.3 从局域网内其他设备连接WSL
有时你可能需要从同一局域网下的手机、平板或其他电脑访问WSL的服务(比如测试一个临时搭建的网站)。这需要额外的端口转发。
- 确定WSL2的IP:在WSL中运行
hostname -I。 - 在Windows上设置端口转发:我们需要将Windows主机某个端口(如8022)的流量,转发到WSL2的22端口。以管理员身份打开PowerShell:
# 添加一条端口转发规则,将Windows的8022端口转发到WSL2的22端口 # 替换 `$wsl_ip` 为你的WSL2实际IP $wsl_ip = (wsl -d Ubuntu hostname -I).Trim() netsh interface portproxy add v4tov4 listenport=8022 listenaddress=0.0.0.0 connectport=22 connectaddress=$wsl_ip # 查看已配置的转发规则 netsh interface portproxy show all- 允许Windows防火墙入站:还需要在Windows防火墙上开放你监听的端口(8022)。
New-NetFirewallRule -DisplayName "WSL2 SSH LAN Port 8022" -Direction Inbound -LocalPort 8022 -Protocol TCP -Action Allow现在,局域网内的其他设备就可以通过ssh your_wsl_username@<你的Windows主机IP> -p 8022来连接你的WSL了。
重要提醒:由于WSL2的IP会变,这个转发规则在WSL重启后会失效。你需要一个脚本在WSL启动时(或定期)更新这个转发规则,或者考虑使用更稳定的
localhost转发结合Windows的“远程端口转发”功能,但这涉及更复杂的网络配置。对于临时测试,手动运行上述命令是最简单的。
6. 常见问题排查与优化技巧
即使按照步骤操作,也可能会遇到问题。这里汇总一些常见坑点。
6.1 连接被拒绝 (Connection refused)
- 检查SSH服务是否运行:在WSL中执行
sudo service ssh status。如果没运行,用sudo service ssh start启动。 - 检查监听地址和端口:运行
sudo netstat -tlnp | grep sshd,查看sshd进程是否在0.0.0.0:22上监听。如果不是,检查sshd_config中的ListenAddress和Port。 - 检查Windows防火墙:确认已按照步骤3.2添加了入站规则。可以临时关闭防火墙测试(不推荐长期关闭)。
- 检查WSL网络状态:有时WSL网络模块会卡住。尝试在PowerShell中执行
wsl --shutdown彻底关闭WSL,然后重新启动。
6.2 连接超时 (Connection timed out)
- 确认IP地址正确:WSL2的IP可能已变。重新在WSL中运行
hostname -I获取最新IP。 - 使用
localhost测试:在Windows上尝试ssh localhost。如果localhost能通但IP不通,很可能是Windows主机到WSL虚拟网络的路径问题,坚持使用localhost是最佳实践。 - 检查端口转发(如果从局域网连接):确认
netsh interface portproxy规则已正确添加且IP是最新的。
6.3 权限错误 (Permission denied)
- 密码错误:确认用户名和密码正确。WSL的用户密码就是你安装时设置的那个。
- 密钥认证失败:
- 检查WSL中
~/.ssh/authorized_keys文件的权限必须是600,.ssh目录权限必须是700。 - 检查公钥内容是否正确复制,没有多余空格或换行。
- 在WSL中查看SSH服务日志获取详细错误:
sudo tail -f /var/log/auth.log(Ubuntu通常在这个文件),然后尝试连接,观察日志输出。
- 检查WSL中
sshd_config配置错误:检查PubkeyAuthentication,AuthorizedKeysFile等设置。
6.4 性能与体验优化
- 保持会话活跃:在
~/.ssh/config文件(Windows用户目录下)中添加针对WSL主机的配置,可以发送心跳包防止连接超时。
Host wsl-local HostName localhost User your_wsl_username ServerAliveInterval 60 ServerAliveCountMax 3这样,以后只需要ssh wsl-local即可连接,并且每60秒会发送一个保活包。
使用Windows Terminal并集成SSH:Windows Terminal可以直接添加SSH配置文件,将WSL SSH连接作为一个独立的终端配置文件,一键连接,体验更统一。
定期更新系统和SSH:在WSL中定期运行
sudo apt update && sudo apt upgrade,确保安全和获得最新功能。
配置WSL的SSH服务,本质上是在一个混合网络环境中打通一条稳定的管理通道。从最初的服务安装、网络理解,到客户端的灵活使用,再到自动化和高级集成,每一步都需要对细节有所把握。我最深刻的体会是,优先使用localhost进行连接,它能规避绝大部分因WSL2动态IP带来的麻烦。而将SSH服务与VSCode Remote、任务计划程序结合,则能极大提升开发体验和系统可靠性。整个过程看似步骤不少,但一旦配置完成,它就会成为你Windows下Linux开发工作流中一个无声却强大的基石,让你在享受Windows便利性的同时,又能获得近乎原生的Linux操作体验。