每天都要 SSH 连服务器,每次都输密码,繁琐不说还容易被暴力破解。其实只要配置一次密钥认证,之后就可以免密、安全、快速地登录远程主机。这篇文章手把手带你完成这件事,Windows、macOS、Linux 三个平台全覆盖。
为什么要用 SSH 密钥?
- 不用再输密码:配置好后
ssh user@host直接进入,脚本和 CI 也能自动化连接。 - 比密码更安全:密码可以被猜测或暴力破解,密钥是 2048/4096 位的非对称加密,几乎不可能被攻破。
- 可以精细控制:密钥可以设置口令(passphrase),还可以随时吊销、更换,管理多台服务器非常方便。
密钥是怎么工作的?
SSH 密钥是一对文件:
- 私钥(
id_ed25519或id_rsa):只留在你自己的电脑上,绝不能外传,相当于你的"钥匙"。 - 公钥(
id_ed25519.pub或id_rsa.pub):可以随便分发,把它放到远程主机的authorized_keys文件里,相当于把"锁的备份"给了服务器。
登录时,服务器用公钥验证你的身份,本地用私钥完成签名——私钥从未离开你的电脑,所以非常安全。
准备工作
- 一台本地电脑(Windows 10/11、macOS 或 Linux 均可)。
- 一台能通过 SSH 登录的远程主机(Linux 服务器、云主机、VPS 等),已知其 IP 和登录用户名,并且当前能用密码登录。
- Windows 用户请确认系统自带 OpenSSH(Win10 1809 及以上默认自带,无需额外安装)。
第一步:生成本地密钥对
Windows(PowerShell 或 CMD)
打开 PowerShell 或命令提示符,执行:
1ssh-keygen -t ed25519 -C "you@example.com"
按提示操作:回车确认默认保存位置(C:\Users\你的用户名\.ssh\id_ed25519),然后设置一个 passphrase(推荐,不想设就直接回车)。
如果你需要兼容很老的服务器(不支持 Ed25519),可以改用 ssh-keygen -t rsa -b 4096。macOS
打开终端,执行:
1ssh-keygen -t ed25519 -C "you@example.com"
同样回车确认保存位置(~/.ssh/id_ed25519),再设置 passphrase 即可。
Linux
打开终端,命令与 macOS 完全一致:
1ssh-keygen -t ed25519 -C "you@example.com"
生成完成后,可以用下面的命令确认文件已生成:
1ls -la ~/.ssh/
你会看到 id_ed25519(私钥)和 id_ed25519.pub(公钥)两个文件。
第二步:把公钥放到远程主机
这里有三条路,任选其一。
方法一:ssh-copy-id(macOS / Linux 首选)
这是最省事的方式,一条命令完成上传并自动追加到 authorized_keys:
1ssh-copy-id user@your-server-ip
输入一次远程密码后,公钥就装好了。
方法二:Windows 手动上传(PowerShell)
Windows 没有 ssh-copy-id,用下面这一行代替(会先读取你的公钥,然后远程执行追加命令):
1type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@your-server-ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
方法三:纯手动(任何平台通用)
先在本地查看公钥内容:
1cat ~/.ssh/id_ed25519.pub
复制输出的整行内容,然后登录远程主机:
1ssh user@your-server-ip
在远程主机上执行(把 粘贴公钥 替换为刚复制的内容):
1mkdir -p ~/.ssh2chmod 700 ~/.ssh3echo "粘贴公钥内容" >> ~/.ssh/authorized_keys4chmod 600 ~/.ssh/authorized_keys
权限很重要:~/.ssh目录必须是 700,authorized_keys文件必须是 600,否则 SSH 会拒绝使用。
第三步:验证免密登录
在本地执行:
1ssh user@your-server-ip
如果不再要求输入密码(或只需输入 passphrase),说明配置成功!
常见问题排查
还是提示要密码?
- 确认公钥确实在远程的
~/.ssh/authorized_keys里,而且是一整行。 - 检查权限:
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys。 - 用
ssh -v user@host查看详细输出,重点看Authentications that can continue。
提示 Permissions too open(Windows 常见) PowerShell 里执行:
1icacls $env:USERPROFILE\.ssh\id_ed25519 /inheritance:r /grant:r "$($env:USERNAME):R"
服务器不允许密钥登录(只认密码)?
部分云厂商默认没有开启 PubkeyAuthentication,或 sshd_config 里被设成了 no,这时即使公钥已装好,登录时仍会要求密码。解决办法:
- 先用密码方式登录远程主机(若密码登录也被禁止,用云厂商控制台自带的 VNC / 网页终端进入)。
- 编辑
/etc/ssh/sshd_config,确认或取消注释这一行:
1PubkeyAuthentication yes
- 重启 SSH 服务使其生效:
1sudo systemctl restart sshd
旧系统(CentOS 6 等)用sudo service sshd restart;Ubuntu/Debian 也可用sudo service ssh restart。
不允许 root 登录?
很多服务器出于安全默认 PermitRootLogin no,root 即使装了密钥也登不进去。解决思路:
- 推荐做法:改用普通用户登录,需要管理操作时用
sudo提权;把公钥装到该普通用户的~/.ssh/authorized_keys即可。 - 必须用 root 时:编辑
/etc/ssh/sshd_config,设置为:
1PermitRootLogin prohibit-password
这个值表示"允许 root 用密钥登录、禁止密码登录",比 yes 安全得多。保存后重启 sshd,并把公钥装到 root 的 ~/.ssh/authorized_keys(普通用户可用 sudo 完成前面三步命令)。
- 还是登不上? 检查
sshd_config里是否有AllowUsers/AllowGroups/DenyUsers限制,确认你的用户名在允许列表内,改完同样要重启 sshd。
连不上,报 Permission denied (publickey) 远程服务器可能禁用了密码登录。请先用带密码的方式通过其他通道(如云厂商控制台的 VNC)登录,检查 /etc/ssh/sshd_config 中的 PubkeyAuthentication yes,然后重启 sshd。
多台服务器都要免密? 把同一把公钥分别装到每台服务器即可;如果想用不同密钥连不同主机,可以在 ~/.ssh/config 里配置:
1Host myserver2 HostName your-server-ip3 User yourname4 IdentityFile ~/.ssh/id_ed25519
安全建议
- 私钥绝不外传:
id_ed25519(无.pub后缀的那个)谁都不能给,也不要提交到 Git 仓库。 - 给私钥设 passphrase:即使电脑丢失,别人也打不开你的私钥。
- 配置好后关闭密码登录:在
sshd_config里设置PasswordAuthentication no并重启 sshd,从此只有持钥匙的人能进。 - 定期轮换密钥:离职、怀疑泄露时,及时换新并清理远程
authorized_keys。 - 开启 root 密钥登录要谨慎:
PermitRootLogin保持prohibit-password而非yes,并优先使用普通用户 + sudo。
配置一次,终身受益。现在就动手吧!