|
| 1 | +--- |
| 2 | +title: 给新服务器配 SSH 免密:它其实只是在认一把钥匙 |
| 3 | +subtitle: 不是把密码藏起来,而是让服务器提前认识你的公钥 |
| 4 | +date: 2026-07-08 |
| 5 | +author: June |
| 6 | +tags: |
| 7 | + - 技术 |
| 8 | + - 技术/运维 |
| 9 | + - 技术/工具 |
| 10 | +--- |
| 11 | + |
| 12 | +新服务器到手后,第一件事通常不是装环境,而是把 SSH 登录整理干净。 |
| 13 | + |
| 14 | +密码登录能用,但它不适合每天敲。容易输错,也容易让人心里没底:这台机器到底配过没有?免密登录听起来像是“把密码省掉”,其实不是。它更像是提前给服务器留一张名单:这把公钥我认识,拿着对应私钥的人可以进。 |
| 15 | + |
| 16 | +## 先把原理想明白 |
| 17 | + |
| 18 | +SSH key 是一对东西:私钥留在本机,公钥放到服务器。 |
| 19 | + |
| 20 | +登录时,服务器不会让你把私钥发过去。它只是出一道题,让本机用私钥签名。签名能被服务器上的公钥验证通过,就放行。 |
| 21 | + |
| 22 | +所以整个过程真正要做的是三件事: |
| 23 | + |
| 24 | +1. 本机生成一对 key; |
| 25 | +2. 把公钥追加到服务器的 `~/.ssh/authorized_keys`; |
| 26 | +3. 在本机的 `~/.ssh/config` 里写一个好记的别名。 |
| 27 | + |
| 28 | +私钥不能发给别人,也不要贴进聊天记录。公钥可以公开一些,但也没必要到处扔。 |
| 29 | + |
| 30 | +## 为什么加了公钥,还是要密码 |
| 31 | + |
| 32 | +这个坑很常见。 |
| 33 | + |
| 34 | +`authorized_keys` 里有你的公钥,不代表服务端一定会用它。OpenSSH 还有自己的配置开关。如果服务器上 `PubkeyAuthentication` 是 `no`,客户端再努力也没用,服务端会直接说:这里只接受密码。 |
| 35 | + |
| 36 | +排查时我一般不猜,直接看两边。 |
| 37 | + |
| 38 | +本地用 `-vvv` 看客户端有没有拿出正确的 key;服务器上用 `sshd -T` 看真实生效的配置。注意是 `sshd -T`,不是只看配置文件里写了什么。因为 `/etc/ssh/sshd_config.d/` 下面的小配置也可能覆盖主配置。 |
| 39 | + |
| 40 | +这一步有点像修灯。灯泡没坏,不代表墙上的开关是开的。 |
| 41 | + |
| 42 | +## 境外服务器先处理网络 |
| 43 | + |
| 44 | +如果服务器在境外,另一件事也要先想清楚:代理。 |
| 45 | + |
| 46 | +SSH 登录本身通常不需要在服务器上开代理,它只要端口能连通就行。但登录进去之后,你很可能要装软件、拉 GitHub 仓库、下载 Docker 镜像、访问包管理源。网络不顺的时候,报错会很像“命令坏了”,其实只是连不上。 |
| 47 | + |
| 48 | +我的习惯是先把基础代理或镜像源准备好,再继续装环境。不要一上来就怀疑 `apt`、`git`、`curl`。服务器网络是第一层地板,地板不平,后面每一步都跟着晃。 |
| 49 | + |
| 50 | +## 别名比记 IP 舒服 |
| 51 | + |
| 52 | +直接敲 `ssh <User>@<Your_IP>` 可以用,但用久了很烦。IP 不好记,端口、用户、私钥路径也容易敲错。 |
| 53 | + |
| 54 | +`~/.ssh/config` 的意义就在这里。你给这台机器起一个别名,以后只敲: |
| 55 | + |
| 56 | +```powershell |
| 57 | +ssh <Host_Alias> |
| 58 | +``` |
| 59 | + |
| 60 | +背后的用户、IP、端口、私钥,全部写进配置。这样也方便给不同服务器用不同 key,不会把所有机器都混在一把钥匙里。 |
| 61 | + |
| 62 | +## 最后一组命令 |
| 63 | + |
| 64 | +下面这组是通用模板,按自己的情况替换占位符就行。 |
| 65 | + |
| 66 | +先在本机生成专用 key: |
| 67 | + |
| 68 | +```powershell |
| 69 | +ssh-keygen.exe -t ed25519 -a 100 -f "$env:USERPROFILE\.ssh\<Key_Name>" -C "<Host_Alias>" |
| 70 | +``` |
| 71 | + |
| 72 | +如果不想每次登录都输入私钥口令,`Enter passphrase` 的时候直接回车两次。更稳一点的做法是设置 passphrase,然后用 `ssh-agent` 缓存。不过个人小服务器图省心的话,无口令 key 也常见,前提是私钥文件别乱放。 |
| 73 | + |
| 74 | +把公钥写到服务器: |
| 75 | + |
| 76 | +```powershell |
| 77 | +Get-Content -Raw -Encoding UTF8 "$env:USERPROFILE\.ssh\<Key_Name>.pub" | |
| 78 | + ssh.exe -o PreferredAuthentications=password -o PubkeyAuthentication=no <User>@<Your_IP> "umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys; chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys" |
| 79 | +``` |
| 80 | + |
| 81 | +如果服务端关了公钥登录,进服务器改: |
| 82 | + |
| 83 | +```bash |
| 84 | +sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d-%H%M%S) |
| 85 | +sudo nano /etc/ssh/sshd_config |
| 86 | +``` |
| 87 | + |
| 88 | +确认有这一行: |
| 89 | + |
| 90 | +```sshconfig |
| 91 | +PubkeyAuthentication yes |
| 92 | +``` |
| 93 | + |
| 94 | +检查配置并重载: |
| 95 | + |
| 96 | +```bash |
| 97 | +sudo sshd -t |
| 98 | +sudo systemctl reload ssh || sudo systemctl restart ssh |
| 99 | +``` |
| 100 | + |
| 101 | +本机写别名: |
| 102 | + |
| 103 | +```sshconfig |
| 104 | +Host <Host_Alias> |
| 105 | + HostName <Your_IP> |
| 106 | + User <User> |
| 107 | + Port 22 |
| 108 | + IdentityFile ~/.ssh/<Key_Name> |
| 109 | + IdentitiesOnly yes |
| 110 | +``` |
| 111 | + |
| 112 | +最后测试: |
| 113 | + |
| 114 | +```powershell |
| 115 | +ssh <Host_Alias> |
| 116 | +``` |
| 117 | + |
| 118 | +如果还有问题,就别急着重来。先看 debug: |
| 119 | + |
| 120 | +```powershell |
| 121 | +ssh.exe -vvv -o IdentitiesOnly=yes -i "$env:USERPROFILE\.ssh\<Key_Name>" <User>@<Your_IP> |
| 122 | +``` |
| 123 | + |
| 124 | +能看懂两行就够了:本地有没有 `Offering public key`,服务端有没有继续允许 `publickey`。这比凭感觉改配置靠谱多了。 |
| 125 | + |
| 126 | +免密不是魔法,也不是把密码藏到了什么地方。它只是把“我是谁”从一串要背的字符,换成了一把本机保存的钥匙。机器认钥匙,人少受罪。 |
0 commit comments