一、故障背景与排查前准备

我们先从一个真实的开发场景说起:上周我帮一个刚入行的前端小同事处理问题,他刚入职公司,按照运维给的文档配置了SSH密钥登录自己的开发服务器,结果试了十几次都弹密码框,密钥死活连不上,但用密码登录却一点问题都没有。他自己瞎改了好几个配置文件,最后把自己的密钥都弄乱了,还是没搞定。 遇到这种情况,别着急乱改,先把准备工作做好,不然只会越改越乱。首先你得确认自己有两台设备:一台是你用来操作的本地电脑(比如你的笔记本),另一台是你要登录的远程服务器(比如开发用的Linux服务器)。然后要明确几个基础信息:远程服务器的IP地址、你登录用的用户名、远程服务器上存放密钥相关文件的路径(一般是/home/你的用户名/.ssh这个文件夹)。 另外,你得先确认密码登录是正常的,这是排查的基础——如果密码都登不上,那问题就不是密钥的事了。先试一次密码登录,确认能正常进入服务器,比如登录后能看到服务器的欢迎语,能执行ls、cd这些基础命令,没问题了再开始排查密钥的问题。

二、核心排查步骤与详细操作

2.1 本地电脑的密钥检查

很多人以为密钥的问题都出在服务器上,其实本地的密钥文件权限不对、密钥配错了,都会导致认证失败。先从本地开始查,毕竟本地操作不用来回登录服务器,更方便。

2.1.1 确认本地密钥是否存在

本地的密钥一般存在你的用户文件夹下的.ssh目录里,Windows的话一般是C:\Users\你的用户名.ssh,Mac和Linux的话是/Users/你的用户名/.ssh。先进入这个目录,看看有没有id_rsa(私钥)和id_rsa.pub(公钥)这两个文件。 比如在Mac上,打开终端,执行下面的命令(技术栈统一用Shell,后面的所有命令都用Shell技术栈):

# 进入本地.ssh目录
cd ~/.ssh
# 查看目录下的所有文件
ls -la

执行完之后,你应该能看到类似下面的输出:

total 16
drwx------  5 yourname  staff  160 10 12 14:30 .
drwxr-xr-x+ 30 yourname  staff  960 10 12 14:20 ..
-rw-------  1 yourname  staff  2602 10 12 14:30 id_rsa
-rw-r--r--  1 yourname  staff   562 10 12 14:30 id_rsa.pub

如果没有这两个文件,说明你根本没生成密钥,直接用密码登录当然没问题,但密钥登录就不行。生成密钥的命令也很简单:

# 生成SSH密钥,一路回车即可(可以设置密码,也可以不设)
ssh-keygen -t rsa -b 4096

生成之后再用上面的ls命令检查,确认id_rsa和id_rsa.pub都存在。

2.1.2 检查本地密钥的权限

SSH对密钥文件的权限要求很严格,私钥文件必须只有你自己能读写,公钥可以让其他人读,但不能让其他人写。如果权限不对,SSH会直接忽略这个密钥,不会用它来认证。 比如上面的输出里,id_rsa的权限是-rw-------,这就对了——第一个-表示是文件,后面的rw-表示所有者(你自己)有读写权限,后面的三个---表示同组的人没有权限,最后三个---表示其他人没有权限。如果你的id_rsa权限是-rw-rw-r--,那肯定有问题,必须改过来。 修改本地密钥权限的命令:

# 修改私钥权限为只有所有者可读写
chmod 600 ~/.ssh/id_rsa
# 修改公钥权限为所有者可读写,其他人可读
chmod 644 ~/.ssh/id_rsa.pub

改完之后再用ls -la检查,确认权限正确。

2.2 远程服务器的密钥配置检查

本地没问题了,就轮到远程服务器了。远程服务器上的密钥配置主要是authorized_keys文件,这个文件用来存放允许登录的公钥,SSH认证的时候会用本地的私钥和这个文件里的公钥匹配,匹配上了就允许登录,匹配不上就弹密码。

2.2.1 确认authorized_keys文件存在

先登录远程服务器(用密码登录),然后进入用户的.ssh目录,检查有没有authorized_keys文件。

# 登录远程服务器,替换成你的用户名和IP
ssh your_username@your_server_ip
# 登录成功后,进入用户的.ssh目录
cd ~/.ssh
# 查看目录下的文件
ls -la

如果没有authorized_keys文件,那肯定连不上,需要把本地的公钥复制到这个文件里。复制的方法很简单,先在本地终端打开id_rsa.pub文件,把里面的内容复制下来,然后在远程服务器的.ssh目录下创建authorized_keys文件,把内容粘贴进去。 比如在远程服务器上创建并写入:

# 创建authorized_keys文件并写入公钥内容(把复制的公钥替换成你自己的)
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC1...(你的公钥内容)" >> authorized_keys

也可以用更简单的命令直接把本地公钥复制到服务器:

# 在本地终端执行,直接把本地公钥复制到远程服务器的authorized_keys文件
ssh-copy-id your_username@your_server_ip

这个命令会自动创建authorized_keys文件,还会自动设置正确的权限,非常方便。

2.2.2 检查authorized_keys文件的内容

确认文件存在之后,还要检查内容对不对——有没有复制错公钥,有没有换行或者空格的问题。SSH要求每个公钥占一行,不能有多余的空格,也不能有换行。 比如你复制公钥的时候,不小心多复制了一个空格,或者把两行公钥粘到了同一行,SSH就识别不出来。用下面的命令查看文件内容:

# 查看authorized_keys文件的内容
cat authorized_keys

输出应该是一行完整的公钥,开头是ssh-rsa,后面是一串乱码一样的字符串,最后是注释(一般是你的本地用户名和电脑名)。如果有多余的行,或者内容不对,就把错误的内容删掉,重新粘贴正确的公钥。

2.2.3 检查authorized_keys文件的权限

和本地的密钥一样,authorized_keys文件的权限要求也很严格。SSH要求这个文件只能被所有者读写,不能被同组的人或者其他人读写,不然SSH会认为这个文件不安全,直接忽略。 比如你用ls -la查看远程服务器的.ssh目录,authorized_keys的权限应该是-rw-------,如果是-rw-rw-r--或者其他权限,就必须改过来。 修改远程服务器上authorized_keys权限的命令:

# 修改authorized_keys权限为只有所有者可读写
chmod 600 ~/.ssh/authorized_keys

改完之后再检查一遍权限,确认正确。

2.3 检查.ssh目录的权限

除了文件的权限,.ssh目录本身的权限也很重要。SSH要求.ssh目录只能被所有者读写执行,不能被同组的人或者其他人读写执行,不然SSH会认为这个目录不安全,直接拒绝密钥登录。 比如远程服务器上的.ssh目录权限应该是drwx------,如果是drwxr-xr-x,那肯定有问题。修改目录权限的命令:

# 修改.ssh目录权限为只有所有者可读写执行
chmod 700 ~/.ssh

本地的.ssh目录权限也要检查,本地的.ssh目录权限也应该是drwx------,修改命令和远程的一样:

# 本地修改.ssh目录权限
chmod 700 ~/.ssh

2.4 检查SSH服务的配置

如果上面的步骤都没问题,还是连不上,那就要检查远程服务器上的SSH服务配置了。SSH服务的配置文件一般在/etc/ssh/sshd_config,这个文件里有几个关键的配置项,决定了是否允许密钥登录。 用下面的命令打开配置文件(需要root权限,所以要加sudo):

# 打开SSH服务配置文件
sudo vi /etc/ssh/sshd_config

找到下面几个配置项,确认它们的设置:

  1. PubkeyAuthentication:这个配置项决定是否允许密钥登录,必须设置为yes。
  2. AuthorizedKeysFile:这个配置项指定了authorized_keys文件的路径,一般是.ssh/authorized_keys,不要改。
  3. PasswordAuthentication:这个配置项决定是否允许密码登录,我们的场景是密码能登录,密钥不能,所以这个配置项应该是yes,不用改。 如果PubkeyAuthentication被设置成了no,那肯定连不上,把它改成yes,然后保存退出。改完配置之后,要重启SSH服务,让配置生效:
# 重启SSH服务,不同的Linux发行版命令可能不一样,Ubuntu用这个
sudo systemctl restart ssh
# CentOS用这个
sudo systemctl restart sshd

重启之后再试一次密钥登录,应该就能连上了。

三、应用场景与技术优缺点分析

3.1 应用场景

SSH密钥登录主要用在需要频繁登录远程服务器的场景,比如开发人员登录开发服务器、运维人员登录生产服务器、服务器之间的自动同步(比如备份、数据同步)等。比如开发人员每天都要登录开发服务器调试代码,如果用密码登录,每次都要输入密码,很麻烦,用密钥登录就可以一键登录,效率很高。 另外,密钥登录比密码登录更安全,因为密码容易被暴力破解,而密钥是一对公钥和私钥,私钥只有你自己有,别人就算拿到公钥也没法登录,所以适合对安全要求比较高的场景。

3.2 技术优缺点

优点:

  1. 安全:密钥登录采用非对称加密,私钥只有所有者持有,不容易被破解,比密码登录安全很多。
  2. 方便:配置好之后可以一键登录,不用每次都输入密码,适合频繁登录的场景。
  3. 支持自动化:可以配合脚本实现服务器之间的自动登录和操作,比如自动备份、自动部署等。 缺点:
  4. 配置复杂:对新手来说,配置密钥的步骤比较多,容易出错,比如权限设置不对、公钥复制错了等。
  5. 依赖密钥文件:如果本地的私钥文件丢失或者损坏,就没法用密钥登录了,必须重新生成密钥并配置。
  6. 权限要求严格:对密钥文件和目录的权限要求很严格,稍微改一点就会导致认证失败,排查起来比较麻烦。

四、注意事项

  1. 私钥要保密:私钥是你登录服务器的凭证,一定要保存在安全的地方,不要随便分享给别人,也不要存在公共的电脑上。如果私钥丢失,要及时删除服务器上对应的公钥,重新生成密钥。
  2. 定期更换密钥:和密码一样,密钥也要定期更换,比如每半年换一次,这样可以提高安全性。
  3. 不要修改密钥文件的权限:很多人在配置密钥的时候,为了方便,会把密钥文件的权限改成所有人都能读写,这样会导致SSH认证失败,一定要严格按照要求设置权限。
  4. 配置完成后要测试:配置完密钥之后,一定要测试一下能不能正常登录,确认没问题之后再用,避免影响工作。
  5. 备份密钥文件:要把本地的私钥文件备份到安全的地方,比如U盘、云盘(加密的),防止电脑损坏或者丢失导致私钥丢失。

五、文章总结

SSH密钥认证失败但密码可登录的问题,大部分都是因为权限设置不对、公钥配置错误或者SSH服务配置不对导致的。排查的时候要按照从本地到远程、从基础配置到高级配置的顺序,一步一步来,不要乱改配置。 首先检查本地的密钥是否存在、权限是否正确,然后检查远程服务器上的authorized_keys文件是否存在、内容是否正确、权限是否正确,再检查.ssh目录的权限,最后检查SSH服务的配置。只要按照这个步骤来,大部分问题都能解决。 密钥登录虽然配置起来有点麻烦,但安全又方便,适合大部分的远程登录场景,只要掌握了排查方法,遇到问题就能快速解决。