SSH 服务的远程登录服务方式,通常有密码登录和公钥登录两种。公钥登录方式的好处就不赘述了,本文详解 SSH 公钥登录的配置过程,以及其中常见的坑。
Note:本文所有实验均在 Mac 下的 iTerm2 中操作。
配置单个主机的 SSH 公钥登录,步骤非常简单,三步即可:
- 生成密钥对
- 拷贝公钥文件到服务器
- SSH 直接公钥登录服务器
步骤详解
ssh-keygen 生成密钥对
ssh-keygen 命令可以按照指定的参数生成密钥对,其常用的参数有以下几个:
-t : 加密算法,可选 [dsa | ecdsa | ed25519 | rsa];
-b :密钥长度(256/512/1024/2048……),建议至少1024;
-f : 输出的密钥对文件名;
-N :密钥口令。
比如我要为 test 主机生成一对密钥文件,密钥长度 2048、加密算法 RSA,就可以用以下命令:
|
|
执行此命令会提示 Enter passphrase (empty for no passphrase):
,如果需要密钥口令,就要填上并记下来,如果不需要就直接摁回车键直到结束。命令执行完成后,会在当前目录生成两个文件:私钥文件 test 和 公钥文件 test.pub 。如果不指定 ssh-keygen
命令的 -f 参数,则会默认生成 ~/.ssh/id_ras 和 ~/.ssh/id_ras.pub 两个文件 。
ssh-copy-id 拷贝公钥到服务器
ssh-copy-id 命令负责把上述步骤生成的公钥文件内容拷贝到服务器,确切说,是把 xxx.pub 文件中的内容附加到服务器端的 ~/.ssh/authorized_keys
文件中。
ssh-copy-id 命令使用方式如下:
|
|
其中 -i
即指定上述步骤生成的密钥对中的 公钥文件,意思是把公钥文件 xxx.pub 传到服务端 hostname
,把 xxx.pub 中的内容附加到 hostname:/home/username/.ssh/authorized_keys
文件中。如果不用 -i
指定公钥文件,则默认指定 id_ras.pub 。
举例来说,我想通过公钥登录我 192.168.1.2
上的 jiayu
账户,那么只需把上述步骤中生成的 test.pub 文件上传到该服务器即可:
|
|
运行这条命令会让输入一次账户密码,然后才能成功上传到服务端。
另外,还有好多人在这一步会舍弃 ssh-copy-id
命令,转而手动上传公钥文件到服务端,然后 cat xxx.pub >> ~/.ssh/authorized_keys
,个人不提倡这种做法, ssh-copy-id
这条专用命令就是为了免去麻烦又容易失误的手动操作。
直接登录远程服务器
经过上面两步骤,没什么意外的话就可以用密钥登录远程服务器了。不过这里还有个小细节需要说一下,我们平时用密码 SSH 登录远程服务器,是用 ssh username@host -p <port>
命令然后输入密码。如果我们只有一台远程服务器需要用 SSH 公钥登录的方式,那么最初执行 ssh-keygen 命令的时候就可以不指定 -f
参数,默认生成密钥对文件 id_ras/id_isa.pub ,然后执行命令 ssh username@host -p <port>
不用输入密码即可登录,SSH 命令会默认调用 id_rsa 尝试连接。
但如果执行 ssh-keygen 命令的时候指定了 -f test 参数,那么这时要登录远程服务器就要在 SSH 命令中也指定私钥文件:
|
|
成功登录,配置完成,即可删除本地的公钥文件 xxx.pub,只留下相应的私钥文件。
踩坑
有的朋友会发现,严格按照上述步骤操作,也无法成功连接服务端。此处常见的坑有 2 个:
- 服务端
~/.ssh/
目录和~/.ssh/authorized_keys
文件的权限问题; - 服务端
~/.ssh/authorized_keys
文件内容格式问题。
服务端相关目录和文件权限
个人见过的情况,把服务端 ~/.ssh/
目录权限设置为 700 ,把 ~/.ssh/authorized_keys
文件权限设置为 600 即可。
authorized_keys 中 pubkey 内容要换行
有时候,服务端 SSH 目录和文件权限都没问题,仍然连接失败。此时给 SSH 命令启用 -v
选项打出连接时的详细信息,会发现客户机已经把私钥发送到服务器端,但在服务器端没有验证成功。
并且,在服务端的 SSH 服务日志 /var/log/secure
文件中可以查到类似以下内容的错误信息:
|
|
此时就是服务端 ~/.ssh/authorized_keys
文件内容格式出了问题。根源在于 ssh-copid
命令默认把公钥文件内容直接附加到服务端 authorized_keys
末尾,而没有换行。
解决方案也很简单:Vim 打开服务端 ~/.ssh/authorized_keys
文件,为每个 pubkey 内容手动隔开一行即可。
配置多服务器多公钥登录
前面举的例子都是针对单一服务器 SSH 公钥登录配置,如果我有多台服务器都需要配置成 SSH 公钥登录,该怎么配置?
这里有个便捷的方式,两步即可完成配置:
- 为每台服务器按照上面的 三步走 生成密钥对文件,配置 SSH 公钥登录后,整理好本地所有的私钥文件,最好所有的私钥文件统一放到同一目录下,比如
~/.ssh/priKeys/
; - 编写本地 SSH 配置文件:
~/.ssh/config
假如我的服务端主机与主机别名(方便自己记忆而起的别名)列表如下:
|
|
那么我的本地 ~/.ssh/config
文件配置如下:
|
|
各配置项的意义见上面的注释内容,这样一来,我就可以用 主机别名 直接登录远程服务器了。比如通过 SSH 公钥登录 root@192.168.110.4
,以下命令即可:
|
|
这样,ssh 命令会自动根据 ~/.ssh/config
中的配置项,寻找到 jiayutest
这一个私钥文件,然后拿它去登录 root@192.168.110.4
。