1. 为什么需要SSH密钥免密登录?
每次连接远程服务器都要输入密码,不仅麻烦还存在安全隐患。我在管理十几台Ubuntu服务器时,曾经因为频繁输入密码导致手指抽筋(不开玩笑),更糟糕的是某次在公共场合操作时差点被身后的人窥屏记下密码。密钥认证彻底解决了这些问题。
SSH密钥对由公钥和私钥组成,采用非对称加密原理。公钥可以放心地放在服务器上,私钥则保存在本地Windows电脑上。当连接建立时,服务器会用公钥加密一段随机数据,只有拥有对应私钥的客户端才能解密这段数据——这就证明了你的身份。
相比密码认证,密钥登录有三大优势:
- 安全性:私钥从不传输,暴力破解几乎不可能
- 便捷性:一次配置后永久免密登录
- 可管理性:可以针对不同服务器使用不同密钥
重要提示:私钥相当于你的数字身份证,必须像保护银行卡密码一样保护它。绝对不要将私钥文件发送给任何人,也不建议设置空密码保护私钥。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Windows端密钥生成与配置
2.1 安装OpenSSH客户端
现代Windows 10/11已经内置了OpenSSH客户端,按Win+R输入optionalfeatures打开"启用或关闭Windows功能",勾选"OpenSSH客户端"即可。如果使用老版本Windows,可以从Git for Windows中获取完整的SSH工具链。
验证安装是否成功:
bash复制ssh -V
应该显示类似OpenSSH_for_Windows_8.6p1的版本信息。
2.2 生成ED25519密钥对
在PowerShell中执行:
bash复制ssh-keygen -t ed25519 -C "your_email@example.com"
这里有几个关键点需要注意:
-t ed25519:选择更安全高效的ED25519算法,而非传统的RSA-C:添加注释,通常用邮箱作为标识- 保存路径:默认在
C:\Users\你的用户名\.ssh\id_ed25519 - 密码短语:建议设置(至少12位),这样即使私钥泄露也不至于被直接利用
生成完成后,你会得到两个文件:
id_ed25519:私钥(必须严格保密)id_ed25519.pub:公钥(需要上传到服务器)
2.3 管理多组密钥(可选)
如果你需要管理多台服务器,可以为每台服务器创建独立密钥:
bash复制ssh-keygen -t ed25519 -f ~/.ssh/ubuntu_server_key
然后在~/.ssh/config文件中配置别名:
code复制Host myserver
HostName 192.168.1.100
User admin
IdentityFile ~/.ssh/ubuntu_server_key
这样以后只需执行ssh myserver即可连接。
3. Ubuntu服务器端配置
3.1 安装OpenSSH服务
Ubuntu Server通常预装了OpenSSH服务端,如果没有可以通过:
bash复制sudo apt update && sudo apt install openssh-server -y
检查服务状态:
bash复制sudo systemctl status ssh
3.2 安全加固SSH配置
编辑/etc/ssh/sshd_config文件,建议做以下修改:
bash复制Port 2222 # 修改默认端口
PermitRootLogin no
PasswordAuthentication no # 禁用密码登录
PubkeyAuthentication yes
重启服务使配置生效:
bash复制sudo systemctl restart ssh
特别注意:在禁用密码认证前,请确保已经成功配置密钥登录,否则可能把自己锁在服务器外。建议先在另一个终端保持一个活跃的SSH连接作为备用。
3.3 添加公钥到授权列表
将Windows生成的公钥内容(id_ed25519.pub文件内容)添加到服务器的~/.ssh/authorized_keys文件中:
bash复制mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "你的公钥内容" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
4. 连接测试与故障排除
4.1 首次连接测试
从Windows执行:
bash复制ssh -p 2222 username@server_ip
如果一切正常,应该会提示输入私钥密码短语(如果有设置),而不会要求输入服务器密码。
4.2 常见问题排查
问题1:Permission denied (publickey)
- 检查
sshd_config中PubkeyAuthentication是否为yes - 确认
authorized_keys文件权限是600 - 使用
-v参数查看详细日志:ssh -vvv user@host
问题2:私钥密码忘记
只能重新生成密钥对并重新配置,所以建议使用密码管理器保存密码短语。
问题3:连接超时
- 检查防火墙是否放行了SSH端口(默认22或你修改的端口)
- 确认服务器IP和端口正确
- 测试网络连通性:
ping server_ip
4.3 高级技巧:SSH-Agent管理密钥
为了避免每次连接都要输入私钥密码,可以使用ssh-agent:
bash复制# 启动agent
eval $(ssh-agent -s)
# 添加私钥
ssh-add ~/.ssh/id_ed25519
这样在当前会话期间就只需输入一次密码了。可以将这些命令添加到PowerShell的$PROFILE文件中实现自动加载。
5. 安全最佳实践
- 定期轮换密钥:每3-6个月更换一次密钥对
- 使用强密码保护私钥:即使私钥泄露,没有密码也无法使用
- 限制访问IP:在
sshd_config中添加AllowUsers user@ip限制 - 监控登录尝试:定期检查
/var/log/auth.log - 备份密钥:将
.ssh目录备份到加密的USB驱动器中
我在实际运维中遇到过因为私钥泄露导致的安全事件,攻击者利用被盗的密钥在凌晨3点登录服务器部署挖矿程序。从那以后,我养成了以下习惯:
- 为不同环境(生产/测试/开发)使用不同密钥
- 使用Yubikey等硬件安全模块存储密钥
- 设置服务器端的入侵检测系统(如fail2ban)
6. 扩展应用场景
配置好SSH密钥后,你还可以实现:
- VSCode远程开发:在Remote-SSH扩展中使用密钥连接
- 自动化脚本:在CI/CD流程中免密执行远程命令
- 文件传输:搭配scp/rsync实现安全文件同步
- 端口转发:建立加密隧道访问内网服务
比如用rsync同步文件:
bash复制rsync -avz -e 'ssh -p 2222' /local/path user@server:/remote/path
对于团队协作,建议使用专门的SSH证书颁发机构(CA)来集中管理访问权限,而不是共享密钥。HashiCorp Vault等工具可以帮助实现这一点。
