跳到主要内容

启用OpenSSH服务

大部分来自微软官方文档,但这里有一些细节是错的或可选的,我根据实际经验,总结出这篇笔记。

服务端

先决条件检查

运行下面的命令。 当你是内置 Administrator 组的成员时,输出将显示True。

(New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

安装适用于 Windows 的 OpenSSH

为了确保 OpenSSH 可用,请运行以下 cmdlet:

Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'

一般自带Client,但没有Server,如果两者均尚未安装,则此命令应返回以下输出:

Name  : OpenSSH.Client~~~~0.0.1.0
State : NotPresent

Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent

根据需要安装组件

# Install the OpenSSH Client
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

# Install the OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

启动并配置 OpenSSH 服务器以供初始使用

# Start the sshd service
Start-Service sshd

# OPTIONAL but recommended:
Set-Service -Name sshd -StartupType 'Automatic'

# Confirm the Firewall rule is configured. It should be created automatically by setup. Run the following to verify
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
} else {
Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
}

完成后,确认端口没有被防火墙影响时,即可尝试用其他客户端,通过账号密码的方式连接到服务器

ssh domain\username@servername

基于密钥的身份验证

生成密钥部分不额外介绍,可参考微软官方文档

与微软文档的差异

  • 客户端向服务器复制公钥时,微软文档默认用户名相同,但实际测试时,需要手动指定用户名。
# Get the public key file generated previously on your client
$authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ed25519.pub

# Generate the PowerShell to be run remote that will copy the public key file generated previously on your client to the authorized_keys file on your server
# 这里的$env:USERPROFILE,会在服务器上创建客户端用户名的文件夹,所以客户端与服务器用户名不同时,需要留意
$remotePowershell = "powershell New-Item -Force -ItemType Directory -Path $env:USERPROFILE\.ssh; Add-Content -Force -Path $env:USERPROFILE\.ssh\authorized_keys -Value '$authorizedKey'"

# Connect to your server and run the PowerShell using the $remotePowerShell variable
ssh username@domain1@contoso.com $remotePowershell
  • 没有设置管理用户的情况

“公钥 (.ssh\id_ed25519.pub) 的内容需放置在服务器上的一个名为 administrators_authorized_keys 的文本文件中”,但我实际上不需要那么高的权限,所以没有做这部分操作。如果不设置管理用户,要同时修改C:\ProgramData\ssh\sshd_config文件,注释掉Match Group administrators这部分代码

# Example of overriding settings on a per-user basis
#Match User anoncvs
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server

# 不设置管理用户的时候,注释掉最底下这两行
#Match Group administrators
# AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

设置完成后,拒绝使用账号密码方式登录

默认情况下,OpenSSH 服务器允许通过账号密码的方式登录,但实际生产环境,我们希望使用密钥的方式登录,所以需要禁用账号密码的方式登录。通过修改C:\ProgramData\ssh\sshd_config文件实现,将以下内容取消注释并且修改为no

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
PermitEmptyPasswords no

客户端

如果客户端按照上面的教程,先用账号密码登录过,再设置密钥登录,那不会有什么问题,后续登录都用密钥登录(相关内容可以参考微软官方文档或搜索ssh-add用法)即可。