资讯动态

SSH公钥免密登录配置指南:从原理到iTerm2高效管理

发布时间:2026/10/16 1:30:32 来源:尧图企业网站定制
1. 天天输入SSH密码的日子到底卡在哪里如果你和我一样手里管着三五台Linux服务器每天的工作流离不开ssh userhost那你一定懂这种痛公司网络的密码策略三个月一换测试机、生产机、跳板机的密码还不一样每次登录都要从密码管理器里翻半天好不容易输对了过一会儿又要重新建会话再来一遍。我用Mac做主力开发终端主要就是iTerm2。很早之前就想把SSH公钥免密登录配好但一直拖到有一天连续在三台机器之间切换、输了整整六次密码之后才下决心一次性解决。配完之后最大的感受是这活儿真该第一天就做。整个过程不算复杂核心就是SSH的公钥认证机制加上iTerm2的Profile管理做好之后“双击打开标签页直接进服务器”跟开本地终端一样顺畅再也不用记那堆容易混淆的密码。这篇文章就把我从原理到实操、从最朴素的免密登录到iTerm2进阶配置的完整过程整理出来。适合这几类人看刚把工作主力从Windows换成Mac、第一次认真配置SSH的开发者手头有多台服务器、受够了反复输密码的运维或后端以及明明配过公钥但偶尔还是被要求输密码、想彻底搞清楚原因的人。需要说明的是我接下来写的内容基于一个非常常见且稳妥的做法在本机生成密钥对把公钥放到服务器的authorized_keys文件里利用SSH的挑战-响应机制完成免密认证。全程不涉及任何额外软件纯靠macOS自带的OpenSSH和iTerm2本身就能搞定。2. SSH公钥认证到底是怎么“对上暗号”的很多人配SSH公钥免密的时候只是照着命令敲了一遍成功了就不管了失败就网上搜答案。结果一遇到权限问题、密钥不生效、换机器连不上就完全懵了。我之前也这样直到有一次排查公司某台服务器的连接问题时把原理彻底撸了一遍之后所有奇怪问题基本都能自己定位了。2.1 公钥和私钥的关系锁在门外钥匙在自己手里想象一个场景我有一间屋子门上挂了一把锁。这把锁很特殊锁头上明晃晃地刻着“锁扣样式A”任何人都能看见这个样式但只有我手里那把特制的钥匙能打开它。放在SSH里这个“锁扣样式A”就是公钥可以随便给别人看、可以放在服务器上那把“特制钥匙”就是私钥必须死死攥在自己手里绝对不能离开本机。服务器把公钥存进~/.ssh/authorized_keys文件就等价于在门上挂好了锁。你每次发起SSH连接本质上是向服务器证明“我有那把能打开锁的钥匙”。关键点是证明的方式不是“把钥匙递给服务器看看”而是服务器出一道题你用私钥“签名”之后交回去服务器用公钥验签。签名的数学特性保证了——只有持有私钥的人才能做出有效签名而公钥只能验证、无法伪造。整个过程中私钥数据永远不出现在网络里这正是公钥认证安全性的根基。2.2 挑战-响应认证流程一句话版本具体握手过程大致是这样客户端发起 SSH 连接告诉服务器“我想用公钥认证这是我的公钥指纹”。服务器查authorized_keys找到对应的公钥生成一段随机数据挑战发给客户端。客户端用本地私钥对这个挑战做签名把签名结果返回。服务器用手里那把公钥验证签名通过就放行。整个过程没有密码在网络上传输所以也不存在抓包抓到密码的问题。这跟传统的密码认证有本质区别——密码认证是把“秘密本身”交出去核对公钥认证是“证明我知道某个秘密而不交出秘密”。2.3 为什么authorized_keys和known_hosts不是一回事初学者最容易混的就是这两个文件。authorized_keys位于服务器端的~/.ssh/目录下里面存的全是允许登录这台机器的用户公钥。它是“门上的锁扣样式”每一位能免密登录该账户的用户公钥都会以一行一行的形式出现在这个文件里。known_hosts则在客户端也就是你的Mac上~/.ssh/known_hosts。它的作用是记住你曾经连接过的服务器指纹防止中间人攻击。当你第一次连接一台新服务器时SSH会提示“无法确认主机真实性是否继续连接”你输入yes之后主机指纹就被记进known_hosts。之后如果服务器重装系统、密钥变了SSH会发现指纹对不上直接报Host key verification failed宁可拒绝连接也不让你稀里糊涂地把数据发给一个可疑的“陌生人”。理解这两者的分工之后很多报错就很好猜了authorized_keys的问题导致“不让你进”known_hosts的问题导致“连都不让你连”。3. macOS上生成密钥、投递公钥的完整流程原理讲清楚了下面进入实操。这一段是整篇的核心我会把每一步的命令、参数、以及为什么要这样写都交代清楚你照着做就能打通免密登录。3.1 先看看本机是不是已经有密钥了很多人在Mac上折腾过Git、配过代码托管平台可能已经生成过SSH密钥。如果重复生成倒也没什么破坏性但会产生一堆用不上的文件反而增加管理成本。所以第一步永远是检查ls -al ~/.ssh/如果看到id_ed25519和id_ed25519.pub或者id_rsa和id_rsa.pub那说明已经有密钥了。.pub结尾的是公钥没有.pub的是私钥。如果目录不存在或者里面是空的那就正式生成一对新密钥。3.2 生成密钥我为什么推荐Ed25519生成命令很简单ssh-keygen -t ed25519 -C 用于公司服务器登录这里两个参数值得说清楚。-t指定密钥算法我推荐ed25519-C是注释一般写用途或自己的邮箱方便以后在authorized_keys里一眼认出这把公钥是谁的。关于密钥算法我做过一个小对比算法长度安全性兼容性我的建议Ed25519256位高现代密码学界广泛认可需要OpenSSH 6.52014年后的系统基本都支持首选RSA传统建议4096位足够但需要更长密钥达到相当强度极广老系统也能用备用方案现在绝大多数服务器都是CentOS 7、Ubuntu 18.04往后的版本Ed25519完全没问题。我自己的做法是日常服务器一律Ed25519除非遇到某个特别老的嵌入式系统才临时用RSA。如果你拿不准服务器能不能用Ed25519那就用ssh-keygen -t rsa -b 4096稳妥但生成慢一点、密钥长一点。运行ssh-keygen之后终端会问你要把密钥存到哪里默认是~/.ssh/id_ed25519直接回车即可。接着会问是否设置 passphrase口令短语。这个地方很多人直接回车留空我建议还是设一个。passphrase 相当于私钥的最后一层保险。如果私钥文件被拷走了没有 passphrase 的人拿到私钥也白搭。担心麻烦后面我马上讲怎么用ssh-agent让它只在第一次解锁之后都自动放行。3.3 让ssh-agent记住passphrase而不是每次都问你设置完 passphrase 之后如果直接拿这把密钥去连接服务器SSH会提示你输入私钥的 passphrase每次连接都要来一遍的话体验跟输密码也没差多少。解决办法是让macOS自带的ssh-agent把解锁后的私钥“记在”内存里。先确认agent在运行eval $(ssh-agent -s)然后把私钥交给agent同时让它把passphrase存进macOS的钥匙串Keychain这样连重启电脑之后都不用重新输ssh-add --apple-use-keychain ~/.ssh/id_ed25519第一次执行时它会要求你输入一次私钥的passphrase之后就不再问了。注意--apple-use-keychain是macOS上OpenSSH的特定选项如果你在某些Linux发行版上看到类似教程命令不完全一样那是正常的。如果你希望以后每次新生成的密钥都自动进入这个“免打扰”流程还可以在~/.ssh/config里加上两行配置后面第4章会详细讲这个文件的写法这里先提前贴出来Host * AddKeysToAgent yes UseKeychain yesAddKeysToAgent yes表示只要用到某个私钥就让agent记住它UseKeychain yes表示passphrase放钥匙串托管。配上之后基本就是配一次、用到天荒地老。3.4 把公钥投递到服务器标准法和手动法拿到公钥之后需要把它放到服务器的~/.ssh/authorized_keys文件里。最省事的是用ssh-copy-idssh-copy-id -i ~/.ssh/id_ed25519.pub userserver_ip这条命令会提示你输入一次服务器登录密码输入之后它自动把公钥追加到服务器的~/.ssh/authorized_keys并设置好权限。如果你手头那台服务器没有ssh-copy-id命令个别精简版系统确实没有可以用下面这条手动命令效果一模一样cat ~/.ssh/id_ed25519.pub | ssh userserver_ip mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys拆开看就是先ssh登录服务器创建.ssh目录如果不存在把目录权限改成700然后把本机公钥内容追加到authorized_keys最后把该文件权限改成600。这里有个必须养成的习惯公钥文件写完之后服务端的权限一定要严格检查。~/.ssh目录应该是700authorized_keys文件应该是600。如果权限太宽松比如~/.ssh是755很多SSH服务器出于安全策略会直接忽略这个公钥表现为“明明公钥放对了还是让你输密码”。我在第5章会专门列这个坑。3.5 首次连接确认known_hosts并验证免密公钥投递完成后验证一下ssh userserver_ip如果是第一次连接这台服务器会看到类似这样的提示The authenticity of host server_ip (x.x.x.x) cant be established. ED25519 key fingerprint is SHA256:... Are you sure you want to continue connecting (yes/no)?这是SSH在问你要不要把服务器指纹写进known_hosts。确认这就是你要连的那台机器输入yes回车。之后如果一切正常你将直接进入服务器全程不需要输入密码。此时再顺手测试一下scp或rsync是否也免密比如scp -i ~/.ssh/id_ed25519 localfile.txt userserver_ip:/tmp/没有提示输密码说明整条链路彻底打通了。后面你会发现不仅SSH登录爽了写脚本做部署、用rsync同步文件都变得非常顺滑因为脚本里不再需要处理“expect”之类交互密码的脏活。4. iTerm2里更高效的连接组织方式免密登录配好之后基础体验已经提升了一大截。但如果你手里有多个环境、多个用户、多把私钥光靠每台机器一条ssh userip还是有点低效。iTerm2的价值在这里就体现出来了。4.1 用Profile把“主机、用户名、私钥、窗口标题”打包iTerm2的Profile通俗讲就是提前保存好的一套终端启动配置。你可以为每一台服务器建一个Profile双击选中之后它自动帮你打开一个标签页并执行连接命令。操作路径打开iTerm2按Cmd ,进入 Preferences找到Profiles左侧点新建。右侧关键设置项如下Name给这个连接起个容易认的名字比如api-prod、web-test-01。Command把默认的Login Shell改成Command然后在输入框里填ssh -i ~/.ssh/id_ed25519 userserver_ip如果你后面配置了~/.ssh/config下面马上讲这里甚至可以只写ssh api-prod连IP和用户名都不用写。Working Directory登录后进入什么目录。SSH登录一般跟本地目录无关保持默认即可。Badge这是iTerm2一个很有用的可视化功能可以在标签页角落显示一块“铭牌”。我习惯设为api-prod这样一排标签页开着的时候一眼就知道当前在哪台机器上不用一个个点开看命令行的登录提示。配置完成后按Cmd O会弹出Profile列表键入名字回车新标签页直接打开并连上服务器。整排标签页开着的状态下Cmd 数字可以快速切换配合Badge文字管理多台机器的体验接近无缝。4.2 用SSH config统一管理主机信息让命令更短如果你有大量服务器我更推荐先把主机信息统一写进~/.ssh/config再配合iTerm2的Profile。这个文件是OpenSSH客户端的通用配置macOS完全兼容。一个典型的多主机配置长这样Host api-prod HostName 192.168.1.10 User deploy IdentityFile ~/.ssh/id_ed25519 AddKeysToAgent yes UseKeychain yes Host db-backup HostName 192.168.1.21 User backup IdentityFile ~/.ssh/id_ed25519_backup AddKeysToAgent yes UseKeychain yes Host * AddKeysToAgent yes UseKeychain yes配置完成之后你可以在终端直接ssh api-prodiTerm2的Profile里Command也可以简化为ssh api-prod。以后服务器IP变了只需要改~/.ssh/config一处所有Profile和命令行引用都不受影响。我的经验是把能塞进Host配置的信息全塞进去终端的输入量会大幅减少也降低了记错IP、记错用户名的概率。我自己按环境维护了一份表格你可以参考着建Host别名用途用户私钥文件api-prod线上API服务器deploy~/.ssh/id_ed25519web-test-01测试环境Web-1ubuntu~/.ssh/id_ed25519_testdb-backup数据库备份跳板backup~/.ssh/id_ed25519_backupsftp-file文件传输专用sftpuser~/.ssh/id_ed25519_sftp多把私钥对应多台机器的时候IdentityFile必须显式指定不然SSH默认只尝试id_ed25519或id_rsa错了就直接跳去用密码认证。4.3 Trigger触发器顺手解决sudo还要输密码的问题很多时候免密登录是通了但登录之后执行sudo还要输入当前用户的登录密码这依然会打断操作节奏。iTerm2的Trigger功能可以在这里帮上忙只是使用时要稍微谨慎一点。Trigger的配置思路是终端输出里一旦出现特定正则表达式iTerm2就自动执行预设动作。以sudo为例步骤是打开对应Profile的Advanced-Triggers点Edit新增一条规则正则表达式(?i)password:动作选择Send Text值填你的sudo密码\n注意最后的\n相当于回车以后这个Profile里只要出现password:提示iTerm2就往终端里自动送去密码。真实体验是sudo命令敲下去还没反应过来就已经回到提示符了。但要提醒两点。第一Trigger的密码是明文存在iTerm2配置文件里的任何能读到这台Mac配置的人都能看到所以务必只在个人设备、可信环境中使用第二正则匹配要写得收敛一点别把SSH登录的密码提示也误触发了。如果你已经配好公钥免密正常登录根本不会出现密码提示Trigger只会在sudo这类场景里生效冲突概率不大。说实话这个功能属于锦上添花可配可不配我用了很久没有出过问题但如果你对安全极度敏感跳过这一节完全不影响免密登录的体验。5. 配置后最常见的坑和排查路径我见过不少同事配置免密登录后过一段时间突然失效然后一脸懵。这里把我在实际工作中踩过、帮别人排查过的常见问题整理成一份清单按概率排序。遇到问题先别急着删了重新配对照着查一遍通常十分钟内能定位。5.1 权限不对导致的Permission denied这是最高频的坑。表现形式是authorized_keys里明明有公钥SSH还是提示输入密码或者干脆直接Permission denied (publickey,password)。原因基本跑不出下面这张权限表路径属主权限要求原因用户主目录~登录用户不能是其他用户可写建议755或700太宽松会被sshd拒绝信任~/.ssh目录登录用户700防止其他用户往里塞公钥或读私钥~/.ssh/authorized_keys文件登录用户600防止被篡改排查命令ls -la ~ | grep .ssh ls -la ~/.ssh如果发现权限不对登录服务器后执行chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R $(whoami):$(whoami) ~/.ssh改完再重新连接。这个坑之所以反复出现是因为很多人喜欢用sudo去执行投递公钥的命令结果authorized_keys的属主变成了root普通用户登录时sshd一检查属主不对直接不认。5.2 服务器重装或指纹变化导致的Host key verification failed这种情况往往发生在服务器重做系统、重置云主机之后。你的Mac上known_hosts里存着旧指纹服务器提供的指纹已经变了SSH为了防中间人攻击会直接拒绝连接。报错里通常带着REMOTE HOST IDENTIFICATION HAS CHANGED。解决办法是删掉旧记录重新确认ssh-keygen -R server_ip然后再ssh userserver_ip它会重新询问是否信任新指纹输入yes即可。顺带一提如果只是偶尔用不同系统连同一台服务器出现这个提示是正常的别慌确认不是有人在恶意劫持连接后清理旧记录重连即可。5.3 服务端sshd_config没开公钥验证一般正常安装的Linux发行版默认开启PubkeyAuthentication yes但有些最小化安装或加固过的系统会把它关掉。表现是客户端这边看起来一切正常服务器却一直要求密码。这时候到服务器上检查sudo grep -E PubkeyAuthentication|PasswordAuthentication /etc/ssh/sshd_config确认PubkeyAuthentication yes再看看PasswordAuthentication是否开着。如果你希望改成“只允许公钥登录、彻底禁用密码登录”来防爆破可以把它改成no然后重载sshdsudo systemctl reload sshd # 或较老系统 sudo service ssh reload这里要特别叮嘱一句在任何生产服务器上做禁用密码登录的操作之前一定要开一个新的SSH会话确认公钥登录稳定可用之后再关掉密码认证。不然中间任何一个环节出错你可能进不去机器只能去云控制台瞎折腾。我有一次就是改完配置忘了reload顺手把会话关了结果被挡在门外后来只能从另一台跳板机绕进去。5.4 多把私钥导致的“总是要我输密码”如果你配置完~/.ssh/config发现ssh 别名能免密但ssh 完整userhost又要密码多半是没指定IdentityFileSSH默认只试默认路径的私钥。用-i明确指定试试ssh -i ~/.ssh/id_ed25519_special userhost能通的话就去~/.ssh/config对应Host段里把IdentityFile补上。另外如果你用了ssh-add -D清空过agent里的密钥某些场景下即使IdentityFile写对了SSH也只走agent里的密钥这时候重新执行ssh-add ~/.ssh/你的私钥就好。5.5 实在是不知道问题在哪开调试模式看如果以上都排除了还是不生效直接开SSH的调试输出一步步看认证过程ssh -v userhost想更详细就ssh -vvv。重点看输出里有没有类似这样的行debug1: Offering public key: /Users/yourname/.ssh/id_ed25519 ED25519 SHA256:xxx debug1: Server accepts key: /Users/yourname/.ssh/id_ed25519 ED25519 SHA256:xxx debug1: Authentications that can continue: publickey,password如果看到Offering public key后紧接着Authentications that can continue说明服务器拒绝了你提供的公钥如果压根没有Offering public key那一行说明客户端这边就没打算用这把私钥去查IdentityFile和agent状态。这个方法比瞎猜快很多我用它解决过至少三次“看起来完全正常但就是连不上”的问题。说到底SSH公钥免密这件事原理并不复杂真正影响体验的都是细节。你在自己Mac上把密钥生成好、权限管好、配置项摸熟之后这套东西就会变成日常工作里最不起眼但又最可靠的一环。我现在的习惯是新拿到一台服务器第一件事就是生成专用密钥、写入config、投递公钥前后不到五分钟以后再也不用翻密码本。希望这篇文章能帮你把这条路一次走通。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑