装SSH这话题看着基础,实际翻车点全藏在细节里。Windows自带OpenSSH、Git自带SSH、第三方工具Bitvise,再加上VSCode远程插件一搅和,新手很容易装完连不上、连上传不了文件、传了又权限报错。这篇不讲虚的,直接按我自己的实操顺序来:先帮你想清楚要客户端还是服务端,再给两条安装路径,接着是工具选型和密钥配置,最后把连接失败最常见的坑挨个过一遍。
1. 装SSH前先回答一个问题:你要的是客户端还是服务端
很多人打开教程就搜"Windows安装SSH",结果装到一半发现装错东西了。SSH这个词本身包含两个方向,你先搞清楚自己到底要哪个,后面才不会白折腾。
SSH客户端是你这台Windows电脑主动去连别人,比如连一台Linux服务器、连GitHub/GitLab拉代码、用VSCode连接远程开发机。这时候你只需要在Windows上装一个ssh.exe,它负责发起连接、提供密码输入和密钥验证。绝大多数Windows用户的真实需求都属于这一类,尤其是日常写代码、管服务器的人。
SSH服务端是让别的机器能连到你这台Windows电脑上。比如你出差想远程连回办公室的Windows机器操作文件,或者同事要通过SFTP往你机器上推东西,或者你想把Windows当成一台跳板机,这时候才需要在Windows上装OpenSSH Server,并且把它作为系统服务在后台跑起来。注意,装了服务端不等于自动装好客户端,反过来也一样,这两个是独立组件,可以只装其中一个。
判断方法很简单:如果你接下来要做的事情是ssh user@host这种命令,那就是客户端;如果你要的是别人能从外面连进来,那就得开服务端。我见过最典型的翻车案例是有人只装了客户端,然后用Bitvise SSH Server去连远程Linux,连半天都连不上——因为Bitvise是服务端软件,方向反了。
另外还要区分一个概念:Git安装包里自带的SSH和Windows系统OpenSSH,它们共用同样的命令写法,但底层程序文件不是同一个。后面配置密钥、排查连接问题时经常会遇到"明明配了密钥却提示Permission denied",往往就是两个SSH读取的known_hosts和私钥位置或权限要求不一致导致的。所以一开始就决定好自己主要走哪条路,后面能少踩一半坑。
2. Windows自带OpenSSH的两条安装路径
微软从Windows 10 1809和Windows Server 2019开始就把OpenSSH做成了可选功能,不需要下载第三方安装包。安装方式有两种:设置界面点一点,或者PowerShell敲命令。我建议你优先用命令行,效率和可重复性都更高,尤其是要在一批Windows机器上批量操作的时候。
2.1 设置界面安装:适合一次性的图形化操作
具体路径是:开始菜单搜索"可选功能",进入后点"添加功能",在列表里找到"OpenSSH客户端"或"OpenSSH服务器",勾选后点安装。装完后不需要重启,但新开的终端窗口才会识别ssh命令,已经在运行的PowerShell/cmd需要关掉重开。
这里有个容易漏掉的点:选项列表里两个条目是分开的,你如果只装了客户端,系统服务里就没有sshd,Get-Service sshd会报不存在;只装服务端,命令行里照样敲不了ssh。所以别勾完一个就以为完事了,看自己需求,两个都要就两个都勾。
2.2 PowerShell命令行安装:适合批量与离线场景
以管理员身份打开PowerShell,然后分情况执行:
# 安装OpenSSH客户端 Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 # 安装OpenSSH服务端 Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0如果你不确定系统里已经装了什么,先查询:
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'返回结果里State是Installed的就是已装的。注意,用Add-WindowsCapability装完客户端后,当前这个已经打开的PowerShell窗口可能还认不到ssh命令,需要新开一个终端;服务端则还要手动启动服务,命令如下:
# 启动sshd服务并设为开机自启 Start-Service sshd Set-Service -Name sshd -StartupType 'Automatic'如果想确认服务到底起没起,用:
Get-Service sshd状态显示Running就说明服务端OK了。第一次启动sshd会默认在C:\ProgramData\ssh下生成配置文件sshd_config,同时还会有ssh_host_rsa_key等一系列主机密钥文件,这些是服务端身份的凭证,千万别删。
2.3 装完后的三条自检命令
我建议安装完别急着进入下一步,先花一分钟确认三件事:
# 查客户端版本 ssh -V # 查服务端服务状态(Windows服务角度) sc query sshd # 查默认端口有没有在听 netstat -ano | findstr :22端口监听这一步特别容易被忽略。如果netstat看不到:22的监听,那不管你防火墙怎么放行、客户端怎么连,都是白搭。原因多半是服务没起来或配置没生效。
如果是在老版本Windows Server上,可能没有Add-WindowsCapability,那就只能下载OpenSSH的二进制压缩包手动解压,再把sshd.exe注册成服务。方法是用管理员PowerShell执行:
# 假设解压到 C:\OpenSSH cd C:\OpenSSH powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1这种老方案还会牵扯到sshd_config路径、PATH环境变量等一堆问题,能用系统自带能力的就别走这条路。
3. 工具选型:Bitvise、Termius、FinalShell各自适合什么场景
Windows自带的OpenSSH装好后,命令行连SSH是没问题了,但很多人实际工作里还是需要图形界面、多服务器管理、SFTP文件面板之类的能力。于是第三方SSH工具选型就成了避不开的话题。这里我把用过的几个主流工具按场景捋一下。
3.1 Bitvise SSH Server:Windows被连端的首选
搜索热词里出现了好几次"bitvise ssh server安装使用教程",说明很多人确实需要把Windows当成SSH服务端来用。Bitvise是一家老牌厂商,它的产品分两块:Bitvise SSH Client是免费的SSH/SFTP客户端,Bitvise SSH Server是商业授权的服务端,个人使用免费许可,商用才需要付费。
服务端安装没什么花头:下载安装包,运行向导,它会自动创建Windows服务。装完后需要注意两个点。第一,默认监听22端口,如果和系统自带OpenSSH Server冲突,两台服务都会起不来,需要把其中一个改成其他端口。第二,Bitvise默认不开放密码登录,它推荐用公钥认证,安装时你可以选择自动生成密钥对。如果你只是想快速连Windows上的SFTP,建议在安装向导里勾选允许密码认证,不然后面配置公钥会多绕一圈。
实际使用中我会在Windows机器上装Bitvise SSH Server,然后在笔记本上用Bitvise SSH Client连它。文件传输走SFTP,终端走SSH,一个窗口搞定,比用系统自带的OpenSSH Server在管理面板上直观不少。不过要注意,Bitvise的配置都在自己的管理界面里,和Windows服务管理器的"sshd"没有任何关系,别搞混。
3.2 Termius:多设备、多平台同步的终端控
Termius是我在笔记本和手机之间切换时的首选。它支持Windows、macOS、Linux、iOS、Android,所有的服务器列表、密钥、端口转发规则都可以云同步。这个工具适合谁?适合手上有一堆服务器、经常出差、又不想每次都在命令行ssh user@host环境里来回敲命令的人。
Termius免费版能存的主机数量有限制,但对大多数中转用途其实够用。它最大的价值在两点:一是把密钥集中管理,手机和电脑共享同一套私钥;二是支持SFTP面板,拖拽上传下载比命令行scp直观。缺点是终端渲染相比原生Windows Terminal少一点极客感,但一般用不出区别。
3.3 FinalShell:Windows上跑着最顺手的中文管理面板
如果你经常要SSH到Linux服务器,同时又想要一个带中文界面的服务器管理工具,FinalShell很合适。它的安装包一开始就是给Windows设计的,后来才有macOS版。装完之后可以保存多台服务器信息,支持双击连接、文件面板同步操作、实时监控CPU和内存曲线。
需要注意一点:FinalShell不是纯粹的命令行工具,它自带了一套Java运行时环境,安装包比较大,首次启动也略慢。另外它的服务器列表和密钥都有本地加密存储,重装系统前记得导出配置,否则一堆服务器信息全丢了。
3.4 选型对比:一句话记住该用哪个
| 工具 | 类型 | 核心场景 | 免费程度 |
|---|---|---|---|
| 系统自带OpenSSH | 命令行客户端/服务端 | 轻量使用、脚本化操作 | 完全免费 |
| Bitvise SSH Server | Windows服务端 | 让Windows能被SSH/SFTP访问 | 个人免费 |
| Bitvise SSH Client | 图形化客户端 | 统一管理多台远程主机 | 免费 |
| Termius | 跨平台终端 | 手机和电脑同步使用 | 基础免费 |
| FinalShell | Windows管理工具 | 带面板和监控的Linux管理 | 免费版本 |
一句话总结:自带的解决90%需求,需要图形化和服务端就上Bitvise,跨设备场景用Termius,喜欢面板管理的用FinalShell。不要贪多,装一个用精就够了。
4. SSH密钥从生成到落地:Git、GitLab、VSCode一套配置通吃
密钥配置是SSH绕不开的核心环节。搜索热词里"ssh密钥""gitlab配置ssh密钥"出现频率极高,说明这就是新手和进阶用户都会遇到的问题。其实Windows上配置SSH密钥的思路和Linux完全一样,只不过在文件路径、权限处理上有些Windows特有的坑。
4.1 生成密钥并选对加密算法
打开PowerShell或者Git Bash,运行:
ssh-keygen -t ed25519 -C "你的邮箱或备注"ed25519是目前推荐优先使用的算法,生成的密钥短、安全性高、多数现代服务器都支持。如果你的服务器或类似老设备不支持Ed25519,再退回到RSA:
ssh-keygen -t rsa -b 4096 -C "你的邮箱或备注"输入命令后会问保存路径,默认是C:\Users\你的用户名\.ssh\id_ed25519,一般直接回车即可。接下来是passphrase,也就是私钥本身的密码,这里可以留空,也可以设置一个。设置了passphrase后,每次用私钥都要输一次密码,但可以用ssh-agent缓存,避免反复输入。我个人建议设置一个,安全性高很多。
生成完成后检查目录:
ls $env:USERPROFILE\.ssh正常情况下你会看到两个文件:id_ed25519(私钥)和id_ed25519.pub(公钥)。私钥放自己电脑上绝对不给别人,公钥才是要上传到服务器的。
4.2 把公钥放到GitHub或GitLab
以GitLab为例:登录GitLab,进入Preferences(偏好设置),左侧栏找到"SSH Keys",把id_ed25519.pub里的内容全部复制粘贴进去,取一个能认出来的标题,保存即可。GitHub的位置也类似,Personal settings里的"SSH and GPG keys"。
这里有个Windows上常见的坑:如果你直接右键复制id_ed25519.pub打开再复制内容,可能因为记事本不识别换行而把完整公钥复制成残缺字符串。建议在终端里用cat把公钥内容打出来:
cat $env:USERPROFILE\.ssh\id_ed25519.pub然后从终端输出里复制,这样可以保证公钥内容完整无缺。
配置好公钥后,不要急着用HTTPS连接,直接在终端测试:
ssh -T git@gitlab.com ssh -T git@github.com第一次连接会提示确认远程主机指纹,输入yes回车即可。看到Welcome相关的问候就算通了。如果在GitLab上显示Welcome to GitLab, @用户名!,说明密钥已经生效。
4.3 VSCode Remote-SSH插件的完整配置流程
VSCode连接远程服务器开发,是目前最主流的远程开发方式。用到的插件叫"Remote - SSH",安装后在侧边栏会出现"远程资源管理器"。
具体连接步骤如下:
- 在VSCode里按F1,输入
Remote-SSH: Connect to Host,回车。 - 选择或输入连接目标,比如
user@192.168.1.100,回车后VSCode会尝试用默认私钥连接。 - 如果端口不是22,需要写成
user@192.168.1.100:2222,注意这个写法在OpenSSH教程里是不支持的,但VSCode的Remote-SSH能识别。 - 连接成功后,VSCode会在远程服务器上自动安装VSCode Server服务端组件,这个过程不需要你干预,等右下角状态栏变成"SSH: 主机名"就说明已经连上了。
连接过程中最容易遇到的一个坑是VSCode选择的SSH客户端不是系统自带的OpenSSH,而是Git Bash里的SSH路径。在VSCode设置里搜索remote.SSH.path,如果没设置,Windows下默认使用ssh.exe;但有时候因为Git改变了PATH,会导致它认错SSH,连接时报Bad owner or permissions或直接找不到ssh命令。
解决办法是手动指定:
"remote.SSH.path": "C:\\Windows\\System32\\OpenSSH\\ssh.exe"还有一个热词场景:VSCode连接时报错"此扩展在此工作区中被禁用,因为其被定义为在远程扩展主机中运行"。这个报错通常出现在你试图在本地打开一个需要远程扩展环境的代码库时。解决方式很简单:在扩展面板里找到对应扩展,确认它是否带有"远程"标签,然后确保你的连接方式走的是Remote-SSH而非普通的本地文件夹打开。
远程主机连上后,每个项目的依赖安装、代码运行都会在远程机器上执行,本地只负责界面渲染。所以建议在远程主机上装一套完整的开发环境,比如Python、Node、Go等,不要用本地环境去猜远程路径。
4.4 Windows下密钥权限的常见问题
Windows上~/.ssh目录和Linux不同,没有严格意义上的600权限概念,但OpenSSH for Windows是会检查文件权限的。如果你把私钥文件复制给其他用户,或者从U盘拷过来的密钥权限不对,可能直接导致连接失败,报错信息类似:
Permissions for 'C:\Users\name\.ssh\id_ed25519' are too open.解决办法是修正ACL:
# 重置继承并只保留当前用户 icacls "$env:USERPROFILE\.ssh\id_ed25519" /inheritance:r icacls "$env:USERPROFILE\.ssh\id_ed25519" /grant:r "$env:USERNAME:F"这个命令的意思是:去掉文件的继承权限,然后只给当前用户完全控制权限。这才是Windows OpenSSH认可的权限模型。很多人配好密钥后连不上,十有八九就是权限太开放。
5. Windows服务端sshd_config改完不生效?关键细节都在这
当你把Windows当成SSH服务端来用时,又要改配置文件、又要调权限、又要处理防火墙,比Linux上复杂得多。Windows的OpenSSH Server配置文件和Linux一样是sshd_config,默认位于C:\ProgramData\ssh\sshd_config。这个文件一定要用管理员权限才能打开修改,否则你改了也保存不了。
5.1 最常用的几个配置项
# 默认端口 Port 22 # 是否允许密码登录 PasswordAuthentication yes # 允许公钥登录 PubkeyAuthentication yes # 指定允许登录的用户列表 AllowUsers yourname # 不想让别人用管理员组登录,可以注释掉或限制 # DenyGroups administrators修改后必须重启sshd服务才能生效:
Restart-Service sshd这个步骤漏掉的人不在少数,改完配置直接测试,连不上才发现服务没重启。
5.2 Windows防火墙放行21/22端口
装完OpenSSH Server以后,系统一般会自动添加防火墙入站规则,但如果你用的是第三方服务端比如Bitvise,或者改了端口,就要自己加规则:
New-NetFirewallRule -DisplayName "OpenSSH Server (sshd)" -Direction Inbound - Protocol TCP -LocalPort 22 -Action Allow当你自定义端口不是22时,务必将-LocalPort改成你的端口号,否则防火墙就白改了。检查已有规则可以用:
Get-NetFirewallRule -DisplayName "*ssh*" | Format-Table5.3 Windows防火墙与公网场景的注意事项
Windows那台机器如果直接暴露在公网,建议不要开放端口22给整个世界。更稳妥的做法是通过防火墙只允许特定IP来源访问。可以在防火墙的Scope选项卡里限制远程地址范围,也可以用命令:
Set-NetFirewallRule -DisplayName "你的规则名" -RemoteAddress 203.0.113.0/24这种限制思路尤其适合公司内部服务器跳板机。如果是家庭网络还做了端口转发,务必记住一点:转发到内网Windows的源地址可能全是路由器IP,你限制得不好可能把自己挡在外面。所以先把规则写得宽松一点测试,确认通了再收紧。
5.4 默认Shell指定:让SSH登录后进入PowerShell而不是cmd
Windows OpenSSH Server默认给连接用户分配的Shell是cmd.exe,这意味着你从远程终端进来敲的命令全是cmd语法,很不习惯。改成PowerShell的方法是在sshd_config最后加一行:
Subsystem powershell C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile或者更简洁地直接指定默认Shell:
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force这个改动对用VSCode Remote-SSH连Windows服务器也很有用,免得进去以后还要手动powershell切换。
5.5 多用户和密钥管理
Windows OpenSSH Server读取公钥的路径是C:\ProgramData\ssh\administrators_authorized_keys(管理员组成员)或C:\Users\用户名\.ssh\authorized_keys(普通用户)。注意,管理员组的authorized_keys文件名不一样,而且默认没有这个文件,要你自己手动创建。最稳妥的做法是直接用管理员会话执行:
scp 用户公钥文件 到 C:\ProgramData\ssh\administrators_authorized_keys或者直接用记事本创建一个新的administrators_authorized_keys文件。创建完务必记得做两件事:设置ACL权限,只允许SYSTEM和Administrators组完全控制;然后重启sshd。否则即便公钥放对了,权限不对也白搭。
6. 连接失败的常见问题与排查思路
搜索热词里出现了"ubuntu ssh无法连接""vscode连接ssh远程服务器"这类内容,说明大家在连接阶段最容易卡住。根据我自己的经验,连接失败90%可以归结为四类原因:服务没起、端口不通、密钥没配置对、防火墙挡了。下面按排查顺序捋。
6.1 第一件事:永远先看服务状态
无论你连Windows服务器还是Linux服务器,第一反应都不该是怀疑网络和防火墙,而是先确认目标机的SSH服务还活着。在Windows上执行:
Get-Service sshd状态不是Running,就先Start-Service sshd。Linux上则是:
systemctl status sshd不是active (running)就先把它拉起来。这一步是最基础的,但也是最容易被跳过的。很多人折腾半天,最后发现服务从装完开始就从来没启动过。
6.2 端口不通:用Test-NetConnection代替ping
ping只能说明主机在线,不能说明SSH服务可用。正确检查端口是否开放,用:
Test-NetConnection 192.168.1.100 -Port 22结果里TcpTestSucceeded为True才表示端口能通。如果是False,依次排查:
- 目标机防火墙服务规则是否存在
- 目标机SSH服务是否正在监听22端口
- 路由器或云安全组是否有端口转发或放行策略
还要留意一个常见的情况:Windows自带OpenSSH Server和Bitvise同时装了,两个服务都想去占22端口,结果一个起来另一个半死。用netstat -ano | findstr :22看PID,再用tasklist | findstr PID查是谁占的,一般就能定位。
6.3 公钥连接失败的经典表现
如果你在客户端里配置好私钥,连接时依旧提示输入密码或直接Permission denied (publickey),通常不是网络问题,而是服务端压根没验证你的公钥。排查方向:
- 确认你上传到服务器的公钥是否和本地
id_ed25519.pub内容一致,最好直接在客户端ssh-keygen -y -f 私钥路径生成一次公钥去对比 - 确认服务端
sshd_config里PubkeyAuthentication yes是否处于非注释状态 - 确认登录的Windows用户属于哪个组,管理员组成员沿用
administrators_authorized_keys,普通用户用C:\Users\用户名\.ssh\authorized_keys
这里最容易出错的就是管理员组路径。文件位置放错、文件名写错、权限没收紧,都会直接导致公钥不生效。调试时可以开启sshd的详细日志,Windows日志在事件查看器里的Applications and Services Logs / OpenSSH / Operational,Linux则是/var/log/auth.log。看日志能直接看到服务端报的"Public key authentication failed"原因。
6.4 VSCode Remote-SSH常见报错汇总
用VSCode连远程服务器时,常见报错和解决思路如下:
| 报错信息 | 原因 | 解决办法 |
|---|---|---|
Could not establish connection to "xxx" | 网络、端口或服务端VSCode Server下载失败 | 检查网络连接,确保能访问远程机的22端口 |
Remote-SSH not supported on this host | 远程主机系统过于老旧或架构不支持 | 确认Windows版本不低于Win10 1809 |
Failed to connect to the remote extension host server | 服务端VSCode Server组件被中断 | 删除远程主机的~/.vscode-server目录后重连 |
Bad owner or permissions | 本地私钥权限过宽 | 按前文icacls命令收紧私钥权限 |
删除~/.vscode-server这个操作比较暴力,但非常有效。VSCode远程版本升级失败或者残留旧进程时,这个目录经常是脏状态的罪魁,删了重连即可,不会影响你的项目代码。
6.5 日志才是最诚实的排错助手
许多人排错喜欢盯着客户端窗口看,其实服务端日志里早就写得清清楚楚。Windows OpenSSH Server日志位置:
事件查看器 -> 应用程序和服务日志 -> OpenSSH -> Operational
Linux上则直接看:
tail -f /var/log/auth.log一条典型的公钥认证失败日志会写成Failed publickey for user ... from ...,看到Failed就直接定位到密钥路径、权限和配置上,比盲试省太多时间。
我个人建议,每次改完配置、重启服务、再做连接测试,同时开着一个终端tail远程主机的日志,这是最直观的排错方式。
7. 再多说一句:把常用命令固化成本机脚本
配置SSH这件事,一次搞定并不难,难的是隔几个月换电脑、换系统后重复来一遍。我自己的做法是把常用操作写成一个简单的PowerShell脚本放在$env:USERPROFILE\scripts\ssh-setup.ps1,内容包括生成密钥、启动sshd、放行防火墙、修改默认Shell、配置VSCode路径。这样换新机之后跑一遍脚本就恢复到熟练配置的状态,非常省事。
另外一个小技巧是给不同服务器创建各自的SSH配置别名。Windows的OpenSSH同样支持C:\Users\用户名\.ssh\config这个文件,在里面加上:
Host myserver HostName 192.168.1.100 Port 22 User root IdentityFile ~/.ssh/id_ed25519设置之后,直接ssh myserver就能连,不用每次敲完整用户名和IP。几台服务器长期用的人都该掌握这个写法,配置好之后使用体验完全不输图形化工具。