news 2026/9/30 1:39:51

Windows下SSH免密登录配置指南:从密钥生成到安全加固

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Windows下SSH免密登录配置指南:从密钥生成到安全加固

1. 为什么我抛弃密码登录:免密访问的真实价值

先讲个实际情况。我手里常年管着七八台Linux服务器,有公司的生产环境,也有自己折腾的测试机,系统密码各不相同,长度还都不短,每次登录都得从密码管理器里翻出来复制,麻烦不说,SCP传文件更是灾难——每传一趟就要输入一次密码,传两个目录下来手指头都抽筋。后来我下定决心把所有机器全部改成SSH密钥登录,过程并不复杂,但用完之后彻底回不去了。

SSH免密登录的原理,说白了就是“钥匙和锁”的关系。你在自己的Windows电脑上生成一对密钥:一把私钥留在本机,绝对不能给别人;一把公钥放到服务器上。连接服务器的时候,对方会验证你是否持有匹配的私钥,验证通过就放行,完全不需要输入密码。整个过程是加密的,比密码登录更安全,也比密码登录更省事。

这个需求覆盖的人群很广:初次接触Linux的Windows用户、天天要连跳板机的运维、需要写脚本批量同步文件的开发,甚至只是偶尔连一下云服务器的小白,都值得花十分钟把这一套配好。配完之后,你再也不用担心服务器密码复杂度不够被安全部门点名,也不用在终端里一遍遍敲密码了。

本文会从Windows环境准备开始,完整走一遍密钥生成、公钥部署、免密验证、报错排查的流程,最后聊聊安全上我觉得每个人都应该注意的点。

2. 环境准备:先确认Windows侧具备的条件

2.1 检查自带的OpenSSH客户端,多数人不用装任何软件

很多人以为在Windows上搞SSH得先装个PuTTY或者Xshell,其实从Windows 10 1809版本开始,系统就原生内置了OpenSSH客户端,直接就能用。第一步是确认你的电脑上有这个命令。

操作方式:按下Win + X,选“终端”或“Windows PowerShell”,在窗口里运行:

ssh -V

如果输出类似OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2这样的版本信息,说明已经自带客户端了,后面所有操作都能直接做,不用额外安装任何第三方软件。

如果你的系统比较老,没有这个命令,可以去“设置 -> 应用 -> 可选功能 -> 添加可选功能”,找到“OpenSSH客户端”安装。整个过程大概一分钟,比网上那些建议装Git又装Putty的教程清爽得多。

2.2 建议装Windows Terminal(但非必需)

自带的PowerShell窗口其实也能跑完所有命令,但我想说,如果你打算长期跟服务器打交道,Windows Terminal值得安装。微软商店里直接搜就能装,免费,支持多标签页、自定义字体、复制粘贴快捷键也更顺手。平时我习惯开两三个标签页,一个连着测试机,一个写配置文件,另一个查资料。

如果你更习惯类Unix的操作感,也可以装Git Bash。这个工具会额外提供很多Unix小工具,比如cat、grep、ssh-copy-id,但注意Git Bash自带的ssh-copy-id在Windows上不一定能用,后面我会讲替代方案。核心命令用PowerShell完全够。

2.3 把服务器信息提前列好

开始之前,先把下面这些信息准备好,省得到时候手忙脚乱:

信息项示例说明
服务器IP192.168.1.100云服务器填公网IP,内网机填内网IP
用户名root也可能是 ubuntu、centos 等
SSH端口22如果改过端口,后面命令要带上-p
是否支持密码登录支持第一次部署公钥需要密码,或者用其他方式把公钥放上去

这里有个容易忽略的点:云服务商(比如阿里云、腾讯云)通常默认只允许密钥登录,你买完服务器后会让你下载一个.pem私钥文件,这种场景同样适用本文方法,区别只在于第一次部署公钥时你可能需要在控制台网页上操作,而不是在命令行里输密码。如果是这种情况,直接跳到第4节手动部署部分的思路。

3. 生成密钥对:ssh-keygen的命令细节与建议

3.1 加密算法怎么选:Ed25519还是RSA

现在生成密钥,你其实是在选加密算法。目前最常见的有两种:

  • Ed25519:这是现代首选,密钥长度短,安全强度高,生成快,对性能影响小。OpenSSH 6.5以后的版本都支持。
  • RSA:经典老牌,兼容性最好,很多老旧Linux发行版和网络设备只认RSA。建议用4096位。

我的倾向是:除非你的服务器是CentOS 6、Ubuntu 14.04这种上古版本,否则一律选Ed25519。原因很简单:同样的安全性,它的密钥更短,使用更流畅,配合现代系统完全没有兼容性问题。

老系统怎么判断?拿不准就选RSA 4096,兼容性一定是最大的。下面两张图感受一下区别:

特性Ed25519RSA 4096
密钥长度固定,极短4096位
性能快较慢
安全强度高高
兼容性OpenSSH 6.5+所有平台
推荐场景现代Linux、主流云服务器老旧系统、网络设备

3.2 执行生成命令,并理解每个参数

确认终端没问题之后,在PowerShell里执行:

ssh-keygen -t ed25519 -C "windows-acer" -f $env:USERPROFILE\.ssh\id_ed25519

逐个参数解释一下:

  • -t ed25519:指定使用Ed25519算法。如果要用RSA,就写-t rsa -b 4096。
  • -C "windows-acer":这是注释信息,作用是让你以后看到公钥就能认出这是哪台电脑生成的密钥。不填的话默认是“用户名@主机名”,也够用,但我习惯写个这台机器的主人或者机器名,多台设备管理起来方便。
  • -f:指定密钥保存位置和文件名。这里我指定到了当前用户的.ssh目录下,文件名是id_ed25519。如果你在Windows上直接用默认路径,一般就是C:\Users\你的用户名\.ssh\id_ed25519。

执行完,终端会提示你设置passphrase。这是给私钥加的一道口令密码,不是服务器的登录密码,而是你使用私钥时额外要输入的短语。它跟密码的区别是:你每连一次服务器可能都要输一遍这个口令,所以很多人干脆留空。

我不建议留空。私钥文件在你硬盘上就是一串文本,如果电脑被偷、被植入木马,私钥被拷走,对方就能拿它直接登录你所有配置了对应公钥的服务器,没有任何防线。设一个passphrase等于给私钥再加一层锁,泄露了也还能抢救。后面我会讲用ssh-agent缓存来减少反复输入的麻烦,这个口令不算白设。

生成完成之后,在.ssh目录下会看到两个文件:

  • id_ed25519:私钥,绝对不要发给任何人。文件权限也尽量收紧。
  • id_ed25519.pub:公钥,这个可以随便分发,放到服务器上就行。

3.3 查看公钥内容,确认它长什么样

在同一个终端里运行:

type $env:USERPROFILE\.ssh\id_ed25519.pub

输出大致是:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPxg9xWCT3GsR+qFZ4x0vjWewBghmncn3wZbRzu4q2KOt windows-acer

注意整个内容是一行,开头是算法名,中间是一长串base64编码的密钥数据,最后是我的-C注释。复制的时候记得完整复制整行,不要手动换行,也不要带多余空格,否则服务器端可能识别失败。

提示:Windows上type命令在CMD和PowerShell里都能用,cat命令在PowerShell 7和Git Bash里也能用。习惯哪个用哪个。

4. 把公钥部署到Linux服务器上

4.1 最省事的部署方式:PowerShell一行命令搞定

如果你第一次还能用密码登录服务器,那部署公钥最简单的方式就是把本地公钥内容追加到服务器上~/.ssh/authorized_keys文件里。

在PowerShell里执行:

type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh 用户名@服务器IP "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

拆开来看,这条命令由三部分组成:

  1. type ... .pub—— 读取本地公钥文件内容。
  2. |—— 管道符号,把公钥内容作为输入传给SSH命令。
  3. ssh 用户名@服务器IP "..."—— 先登录到服务器,然后在服务器上依次执行引号内的命令:创建.ssh目录(如果不存在的话)、设置目录权限700、把接收到的公钥追加写入authorized_keys、再把文件权限设为600。

这里我特意把权限设置写在一条命令里了。这一步很重要,很多新手就栽在这里——公钥写进去了,但authorized_keys文件权限太宽松(比如644),SSH服务会直接拒绝使用这个密钥登录,认为不安全。

执行过程中会要求你输入服务器密码,密码正确后就部署成功了。

4.2 没有密码或密码不可用,怎么办

有些场景你压根没法用密码登录。比如云服务器创建时只下载过.pem私钥文件,或者你压根还没找管理员要密码。这时候可以分两种情况处理。

如果手里有.pem私钥文件,用它先登录一次服务器再手动操作:

ssh -i C:\Users\你的用户名\Downloads\mykey.pem 用户名@服务器IP

登录进去之后,手动完成上面那条管道命令的后半部分:创建目录、粘贴公钥、改权限。

如果连私钥都没有,只能去云厂商控制台的网页终端登录,那就在网页终端的shell里执行:

mkdir -p ~/.ssh chmod 700 ~/.ssh echo "ssh-ed25519 AAAA...你的公钥内容..." >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys

这种情况下的公钥内容,就需要你先把Windows上的id_ed25519.pub内容复制出来,再手动粘贴到服务器。粘贴的时候留意一下:很多网页终端默认开启了自动换行,可能导致公钥被截断成多行,这会让密钥失效。看到粘贴结果有换行就重新粘一次,确保它是一行完整的内容。

4.3 服务器端配置项检查

公钥已经放进authorized_keys了,但免密登录还不一定马上能用。服务器端的SSH配置也需要确认两个核心选项。

用root或sudo权限打开SSH配置文件:

sudo vim /etc/ssh/sshd_config

重点看这两行:

PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys
  • PubkeyAuthentication:必须为yes,表示允许公钥认证方式。
  • AuthorizedKeysFile:默认就是.ssh/authorized_keys,如果被改过,说明服务器可能从别的路径读取公钥,那你就得把公钥放到对应文件里。

改完配置记得重启服务让它生效:

sudo systemctl restart sshd

不同发行版的服务名可能有区别,CentOS/RHEL旧系统是service sshd restart,Ubuntu/Debian上可能是systemctl restart ssh。拿不准就两个都试,或者用systemctl status sshd看一下服务名。

还有一个容易忽略的:如果服务器开启了SELinux强制模式,有时候权限对了,但SELinux上下文不对,照样登录不了。云服务器和桌面版Linux一般遇不到,但如果你在公司内网的机器上折腾,遇到密钥放进去仍无法登录的情况,可以考虑sudo restorecon -Rv ~/.ssh恢复一下上下文。

5. 免密登录验证与日常使用优化

5.1 第一次连接:接受指纹并确认免密成功

公钥部署完成后,在Windows上直接执行:

ssh 用户名@服务器IP

如果一切正常,不会再问密码,而是会提示你确认服务器的指纹信息:

The authenticity of host '192.168.1.100 (192.168.1.100)' can't be established. ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxx. Are you sure you want to continue connecting (yes/no/[fingerprint])?

输入yes回车即可。这个提示是SSH在帮你登记这台服务器在known_hosts中的指纹,防止以后有假冒服务器来骗取登录信息。第一次遇到正常确认就行。

确认完之后,你会直接进入服务器的shell,免密登录成功。

如果你在前面设置了passphrase,这里会先要求你输入私钥的口令,输完后收尾,之后连接还可能再问。如果觉得麻烦,往下看ssh-agent的部分。

5.2 用config配置文件管理多台服务器

服务器多了之后,每次都要敲ssh root@192.168.x.x -p 2222这类长命令很痛苦。Windows的OpenSSH同样支持~/.ssh/config配置文件,可以给每台服务器起个简短别名。

在C:\Users\你的用户名\.ssh\目录下新建一个文件,命名为config(没有扩展名),内容示例:

Host prod HostName 10.0.0.5 User root Port 22 IdentityFile ~/.ssh/id_ed25519 Host test HostName 192.168.1.50 User testuser Port 2222 IdentityFile ~/.ssh/id_ed25519_other

配置完之后,连接服务器只需要输入:

ssh prod

ssh会根据别名自动读取HostName、User、Port和私钥文件路径。这个文件里可以放任意多台机器的配置,运维效率提升非常明显。想查配置是否生效,可以执行ssh -G prod看解析结果,比一个个敲命令舒服得多。

5.3 用ssh-agent缓存passphrase,告别每连必输

很多人在passphrase这里妥协:设了嫌麻烦,不设心里又不踏实。其实有个两全其美的办法——ssh-agent。

ssh-agent是OpenSSH自带的一个后台服务,作用是把私钥加载到内存里,之后一定时间内连接服务器都不需要再输入passphrase。

在Windows上,首先要确保ssh-agent服务处于运行状态。在PowerShell(管理员模式)里执行:

Get-Service ssh-agent

如果状态不是Running,就启用并启动:

Set-Service -Name ssh-agent -StartupType Automatic Start-Service ssh-agent

然后加载你的私钥:

ssh-add $env:USERPROFILE\.ssh\id_ed25519

这条命令会要求你输入一次passphrase,之后只要agent服务在运行,免密登录不再询问口令。每次重启电脑后需要重新执行一次ssh-add,或者你可以在$PROFILE(PowerShell配置文件)里加入这行命令,省去手动操作。

5.4 多台Windows设备之间同步公钥

如果你家里一台台式机、一台笔记本都要连同一批服务器,不需要每台机器重新生成公钥部署一遍。方法是:把A电脑生成的id_ed25519.pub内容复制到B电脑的~/.ssh/authorized_keys里,或者干脆把A电脑的整个.ssh/id_ed25519和.pub文件拷贝到B电脑的.ssh目录下。

注意:私钥被拷贝到另一台机器,等于一次性把访问权限给了那台机器。如果复制的是私钥文件,一定确保两台都是你自己的可信设备,并且文件不要经过网盘等中间环节裸奔传输。更稳妥的做法是每台设备生成独立的密钥对,服务器上同时追加多个公钥,这样某台设备丢了,单独删掉对应公钥就行,不需要全盘重来。

6. 免密登录失败的完整排查链路

这部分我特意单独开一节,因为免密登录失败是大部分人第一次配置时最糟心的环节。我会按照实际操作中最常见的出错顺序,带你把问题逐个排掉。

6.1 排查第一站:客户端连着是不是同一个用户

一个特别低级的坑:在Windows上生成密钥、部署公钥的时候用的是root,结果登录时写的是ubuntu或centos,系统去找这个用户的authorized_keys,当然找不到你的公钥,直接报Permission denied (publickey)。

所以排查第一件事:确认ssh 用户名@IP里的用户名,跟部署公钥时用的用户一致。公钥部署在谁的~/.ssh/authorized_keys里,你就得用谁的身份登录,这不是Windows能替你决定的。

6.2 排查第二站:服务器上authorized_keys文件内容对不对

在服务器上执行:

cat ~/.ssh/authorized_keys

看看输出是否只有一行,开头是否为ssh-ed25519或ssh-rsa,内容是否和Windows上id_ed25519.pub完全一致。注意Windows上复制到Linux后,行尾可能残留\r回车符,这在某些情况下会干扰密钥解析。如果发现尾部多了一个字符,可以用sed -i 's/\r$//' ~/.ssh/authorized_keys清理掉。

再检查权限:

ls -l ~/.ssh/authorized_keys

文件权限必须是600或者更严格,目录权限是700。如果输出是-rw-r--r--这种644权限,SSH会认为文件不够安全,直接忽略里面的公钥。修复命令:

chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys

6.3 排查第三站:用ssh -v看详细日志

Windows命令行怎么都连不进时,最好用的工具就是verbose模式:

ssh -v 用户名@服务器IP

或者更详细一点:

ssh -vvv 用户名@服务器IP

输出结果里,重点看下面几行:

debug1: Authentications that can continue: publickey,password debug1: Next authentication method: publickey debug1: Offering public key: C:\\Users\\.../.ssh/id_ed25519 debug1: Authentications that can continue: publickey,password

看到Offering public key正常,但后面还是Authentications that can continue,说明公钥被服务器拒绝。这个时候就要回服务器看SSH日志:

sudo journalctl -u sshd -f

或者老系统:

sudo tail -f /var/log/secure

日志里会明确告诉你认证为什么失败,比如Authentication refused: bad ownership or modes就是权限问题,No such file or directory就可能是路径不对。看日志定位问题,比瞎猜高效得多。

6.4 排查第四站:服务器sshd服务是否正常

有时候公钥和权限都对,但就是连不上,报错不是认证失败,而是:

Connection timed out

或者:

Connection refused

这种情况八成是网络层面的问题,跟密钥本身无关。从Windows先ping一下服务器:

ping 服务器IP

能通的话,继续在Windows上检查服务器22端口是否可达:

Test-NetConnection 服务器IP -Port 22

如果TcpTestSucceeded为False,那就是防火墙或安全组挡了。云服务器请在控制台安全组规则里放通22端口(或你的自定义SSH端口);自建服务器检查firewall-cmd --list-all或ufw status,确认SSH端口是否放行。

如果端口通了但还是拒绝,再检查服务器上sshd是否在运行:

systemctl status sshd

没运行就启动它,并设为开机自启:

systemctl enable --now sshd

6.5 最隐蔽的坑:修改过端口但命令没带端口号

很多生产服务器为了防扫描,会把SSH端口从默认的22改成别的,比如58422。这种情况下直接ssh 用户名@IP是不会成功的,连密码都不会让你输。解决方式很简单,在ssh命令里加-p 端口号:

ssh -p 58422 用户名@服务器IP

如果你用了config文件,在对应Host段落里写Port 58422即可,日常连接则直接享受别名带来的便利。

7. 安全底线与我的个人建议

免密登录配置完成,但并不等于结束,安全上的几个原则我在多次踩坑之后现在每次都严格遵守。

7.1 私钥必须贴身保管,不要裸奔分发

私钥文件就是你全部服务器的合钥匙。不要把它通过微信、邮件、云盘明文传递;不要把整个.ssh目录打包丢到一个共享U盘里;更不要把私钥贴到聊天工具或者代码仓库里。我见过有人为了图省事,把私钥内容直接写进文档发到群里,等于把所有服务器大门敞开。

如果非要在多台设备之间复制私钥,请用加密压缩工具打包后传递,或者直接用U盘物理拷贝,用完及时删除中间痕迹。

7.2 passphrase一定要设置,但记得配合ssh-agent

很多人设了passphrase之后觉得烦,干脆取消。而我的做法是:所有私钥一律设置passphrase,然后用ssh-add加载到系统ssh-agent中,这样平时使用完全感觉不到口令存在,但私钥文件泄露时还有一层保护。这是一对很好的组合——安全性和易用性都兼顾。

Windows下设置passphrase之后,如果你发现每次打开新终端都要重新ssh-add,可以在PowerShell配置文件中预置加载逻辑,或者手动把ssh-agent服务设置为自动启动,再配合配置文件里的AddKeysToAgent yes选项(写入~/.ssh/config顶行),让OpenSSH在首次使用私钥时自动加入agent缓存。

7.3 确认免密成功后再考虑关闭密码登录

有些新手配置完密钥后会寻求把密码登录彻底关闭,来杜绝密码爆破。这个方向是对的,但时机很重要。关掉PasswordAuthentication no之前,我建议先在另一个终端窗口测试一次纯密钥连接,确认不用密码也能顺利登录,再修改服务器配置。否则一旦密钥这边还有隐藏问题,你在断开当前连接后,可能再也进不了系统。

修改方式:

sudo vim /etc/ssh/sshd_config

找到:

PasswordAuthentication yes

改为:

PasswordAuthentication no

改完后重启sshd:

sudo systemctl restart sshd

然后新开一个窗口测试连接。能进,说明一切正常;不能进,就赶紧恢复配置。这个操作其实不难,但很多人因为心急跳过验证步骤,最后只能跑到云控制台用网页VNC救场。

7.4 最后再分享一个小技巧:scp也可以免密了

配置完免密登录,附带的好处是scp传文件也不用输密码了。比如从服务器上下载日志:

scp 用户名@服务器IP:/var/log/nginx/access.log D:\logs\access.log

或者上传一个配置文件:

scp D:\config\nginx.conf 用户名@服务器IP:/etc/nginx/conf.d/test.conf

既然ssh能免密,scp走的是同一套认证机制,自然也是免密的。写自动化脚本的时候,这省掉的可不是一点点操作成本。

整体来说,整套流程从生成密钥到日常使用,大概十几分钟就能搞定。我的个人建议是:先拿一台不重要的测试服务器练习一遍,把各个环节捋顺,再往生产环境推进。毕竟多花十分钟配置,能在这之后无数次的连接中省回无数个十分钟。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 1:39:32

C++ sort() 结构体排序全解:比较函数、多关键字与稳定排序实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 1:39:07

模块化机房建设全攻略:等级规范、选型逻辑与落地避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 1:39:05

Bug分类定级指南:从定义到定级矩阵的实战方法论

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 1:39:05

拆透 el-form 校验链路:model、prop 与 rules 实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 1:39:00

FPGA实战:CORDIC算法实现三角函数计算与EGo1上板验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/30 1:38:57

大模型全生命周期开源评测工具链生态与实操全景横评

大模型全生命周期开源评测工具链生态与实操全景横评在 2026 年的大模型(LLM)研发与生产化落地中,“如何科学、客观、无偏地评估一个大模型究竟有多聪明、有多安全、有多可信”,已经成为决定企业技术路线与投资决策的核心胜负手。 …

作者头像 李华