Windows:如何使用ssh连接win系统

2,255 阅读8分钟

前言

使用ssh连接操控linux主机是很常见的做法,但在win系统却比较少

刚好业务有需求,所以记录下为win10系统搭建ssh server的方法

win11可用,操作相同

安装ssh服务

找到3种安装方法,进行三选一即可

推荐直接使用“系统-界面安装即可”

综上

建议使用“系统-界面安装”重启,如果不行考虑“外部-Github安装”

系统-界面安装(优先尝试)

在网上最多的方法,win10已经集成openssh,客户端已安装,服务端是可选件

参考文章:win10/11 安装ssh并作为服务器使用-腾讯云开发者社区-腾讯云

但是发现不同版本有差异,添加可选功能的位置不同,可以都看看

  1. 应用 -> 应用和功能 -> 可选功能
  2. 系统 -> 可选功能

或者直接在win搜索框搜索“可选功能” -> 添加可选功能,选择 openssh服务端安装重启

安装完务必在“服务”,查看“OpenSSH SSH Server”、“OpenSSH Authentication Agent”

右键启动,右键属性改为自动启动

额外

可以打开开发者选项:更新和安全 -> 开发者选项 -> 开发人员模式按钮

据说虽然不影响主流程,但是在某些权限问题上会减少错误

系统-命令行安装(仅供参考)

管理员启动powershell执行

安装

# 查看ssh client、server安装情况
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
# 安装 OpenSSH 客户端
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
# 安装 OpenSSH 服务器
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# 设置自启动
Set-Service -Name sshd -StartupType 'Automatic'
# 启动服务
Start-Service sshd

检查状态

# 查看服务状态
Get-Service sshd | Select-Object Name, StartType, Status
# 查看22端口是否在监听
netstat -ano | findstr :22

检查防火墙

# 防火墙是否放行(安装完一般会有,不用管)
Get-NetFirewallRule -Name *OpenSSH-Server* | select Name, DisplayName, Description, Enabled
# (可选)手动添加放行22入站端口
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

额外(如需卸载)

#卸载服务端(需要重启)
Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

外部-Github安装(最后方案)

Releases · PowerShell/Win32-OpenSSH

上面的系统方式,无论是界面还是命令行,他们都可能有奇怪的bug,比如:安装失败、安装成功但无法启动等等

可以尝试卸载掉后,去Github直接下载msi安装包手动安装

下载win64的msi安装,安装后在“服务”可以找到,为已运行状态,并且已经配置好自动启动

额外说明

使用此方法安装的sshd,以下检测命令无效

# 此命令会显示未安装,因为不是通过系统安装的
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'

连接ssh服务

确定本机账户密码(重要)

win10的ssh连接账户密码有大坑!!

需要清楚以下概念:

本地账户:本地文件系统的账户,打开cmd,默认在 C:\Users\26211>,那么本地账户就是26211

微软账户:登录此笔记本的微软账户,在系统-账户里可以看到,一般是个邮箱

假设

  • 本地账户:26211、2333(屏幕解锁密码)

  • 微软账户:12345@qq.com、abc123

那么ssh连接就是:本地账户+微软密码

也就是在ssh连接工具要填写,用户=26211,密码=abc123

连接本机测试

知道规则是 本地账户+远程密码后

打开cmd

# 尝试连接本机
ssh summer@127.0.0.1
# 输入密码:abc123

如果没有提示密码错误,之后成功会闪一下,cmd刷新,顶部栏变成是 conhost.exe

这样就已经算是连接上了

拓展配置

配置免密登录

  • 配置允许密钥登录

打开编辑 C:\ProgramData\ssh\sshd_config

# 确保以下2条没有被注释
PubkeyAuthentication yes
AuthorizedKeysFile        .ssh/authorized_keys
# 确保以下2条有注释掉
#Match Group administrators
#AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

保存后在powershell重启服务

Restart-Service sshd
  • 确保ssh-agent服务正常运行

打开服务,找到 OpenSSH Authentication Agent,查看是否已启用并正在运行

  • 将客户端密钥加入服务端

(可选)如果没有公钥,使用 ssh-keygen -t rsa 然后一直回车即可生成

客户端公钥位置:‪C:\Users\summer\.ssh\id_rsa.pub(此电脑用户是summer,其他电脑酌情修改)

将其复制一份出来,改名为 authorized_keys,然后上传到服务端同目录(.ssh下)即可

(可选)如果有多台机器需要免密登录不想覆盖

可以把客户端id_rsa.pub的内容复制出来,追加到服务端的authorized_keys

额外

  • 如果服务端变动,重装了ssh server

如果服务端重装系统或者重新配置ssh server,则客户端需要清理此文件后再试

C:\Users\summer\.ssh\known_hosts

  • 如果还要输密码,再看看文章,里面讲到一个.ssh文件夹权限的问题

Windows配置ssh免密码登录 - 猴子吃桃_Q - 博客园

修改默认shell

默认ssh连接到win的默认shell是cmd,功能较弱,建议修改为git bash或者powershell

我选择git bash,因为可以使用如cat、find、grep等 linux bash命令,并且git bash兼容cmd命令,但是不兼容powershell

可以把git bash作为默认shell,当需要执行powershell命令时,命令行输入powershell回车切换,执行完可以命令行输入bash切回来(前提是把git bash配置进了环境变量)

git bash

前提条件:1.安装git(自带git bash)、2.配置bash进环境变量

我的Git安装在D:\Code\Env\Git,bash位置在其下 bin\bash.exe

D:\Code\Env\Git\cmdD:\Code\Env\Git\bin 加入系统Path变量

然后就可以在powershell执行以下命令,把bash设置为默认ssh shell

警告:一定要确保路径没有填错,否则ssh将彻底连接不上)

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "D:\Code\Env\Git\bin\bash.exe" -PropertyType String -Force
  • 添加中文支持

ssh登录bash后会发现不支持中文,用记事本打开在Git安装目录下的 etc\bash.bashrc,末尾追加:

export LANG="zh_CN.UTF-8"

重启ssh终端连接后,可以显示中文了

  • 兼容cmd的 /xx 格式参数

例如 taskkill /f /im nginx* 在cmd、powershell都是正常的

但是在git bash,会把命令里的/f、/im理解成路径,毕竟linux里/就是路径分隔符

临时解决方法:

# 方法1:对此命令不把 / 解释为路径分隔符
MSYS_NO_PATHCONV=1 taskkill /f /im nginx.exe
# 方法2:转义
taskkill //f //im nginx.exe

永久解决方法:

用记事本打开在Git安装目录下的 etc\bash.bashrc,末尾追加:

alias taskkill=MSYS_NO_PATHCONV=1 taskkill

相当于取别名,为此命令永久添加 MSYS_NO_PATHCONV=1 前缀

powershell

简单,执行1行命令即可

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force

powershell 7

powershell7需要手动安装,要去官网下载,相比系统自带的powershell(一般是5.1.xx版本),功能更加强大,支持命令提示,可以尝试

如果想把pwsh7设置为ssh默认shell,可以执行以下命令设置

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Program Files\PowerShell\7\pwsh.exe" -PropertyType String -Force

使用技巧:

使用 bash -c "<bash才支持的命令>",可以在pwsh中执行bash才能执行的类linux命令

ssh终端管理员权限

在ssh终端使用此命令检测当前是否为管理员权限:

# true 为拥有管理员权限
([Security.Principal.windowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")

发现ssh连接已经是管理员权限,无需配置(ssh自带管理员?)

允许远程执行脚本

默认我们不允许在远程终端执行脚本,可以配置开启

管理员模式启动 powershell(或者通过ssh终端-默认shell为powershell后)

# 查看执行策略,默认是 Restricted(禁止脚本运行)
Get-ExecutionPolicy
# 修改为允许运行脚本
Set-ExecutionPolicy RemoteSigned

# 此时应该可以运行了
.\test.ps1

永久运行程序(nohup)

在ssh终端启动的进程,会随着ssh终端关闭而销毁

而 win 下没有 linux 那样的 nohup 命令,但是可以使用“计划任务”达到类似效果

以常驻运行dufs文件服务器为例:

启动计划任务有两种方式(二选一):

  1. 命令方式:直接把运行命令写入 /tr 参数后,双引号括起来

  2. 脚本方式:复杂命令可以写入ps1脚本,使用powershell运行

# (脚本方式) 启动一个计划任务:执行运行dufs的脚本
schtasks /create /tn "DufsService" /tr "powershell -ExecutionPolicy Bypass -File E:\dufs.ps1" /sc onstart /ru SYSTEM /f
# (命令方式) 启动一个计划任务:执行运行dufs的命令
schtasks /create /tn "DufsService" /tr "dufs E:\share --allow-upload --allow-search --allow-archive --assets 'D:\Program Files\dufs\dufs-material-assets'" /sc onstart /ru SYSTEM /f

# 立刻启动计划任务
schtasks /run /tn "DufsService"
# 查看是否创建成功
schtasks /query /tn "DufsService"
tasklist | findstr dufs
# 查看是否创建成功(详细,可看见创建时的命令行)
schtasks /query /tn "DufsService" /v /fo list

关闭ssh终端,发现dufs文件服务仍正常运行,试验成功

需要销毁时:

# 停止程序
taskkill /f /im dufs*
# 销毁创建的计划任务
schtasks /delete /tn "DufsService" /f