本文先说明云服务器 ECS Linux 服务器 SSH 无法远程登录问题的排查思路,然后 SSH 服务的相关背景知识进行说明。
注意:本文相关配置及说明已在 CentOS 6.5 64 位操作系统中进行过测试。其它类型及版本操作系统配置可能有所差异,具体情况请参阅相应操作系统官方文档。
对于云服务器 ECS Linux,SSH 客户端是主要的运维途径。而 管理终端 可以用于临时运维,或者在客户端登录出现异常时,用于问题排查分析。本文就 SSH 无法登录的可能原因及排查方法进行说明。
针对前述不同因素,常见的问题现象及处理办法说明如下:
客户端无法正常登录时,建议先使用不同的 SSH 客户端基于相同账户信息进行登录测试。如果能正常登录,则判断是客户端配置问题,则需要对客户端配置或软件运行情况做排查分析。
ECS Linux 服务器的登录过程说明,可以参阅产品文档:登录实例
客户端无法正常通过 SSH 连接服务器时,先通过如下方式进行 telnet 端口测试,判断是否是中间网络异常所致:
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >telnet </span><span class = "pun" ><服务器</span><span class = "pln" > IP</span><span class = "pun" >></span><span class = "pln" > </span><span class = "pun" ><</span><span class = "pln" >SSH </span><span class = "pun" >服务端口>比如:</span><span class = "pln" >telnet </span><span class = "lit" > 192.168 </span><span class = "pun" >.</span><span class = "lit" > 0.1 </span><span class = "pln" > </span><span class = "lit" > 22 </span></li> </ol> |
正常情况下,如下图所示,会返回服务端 SSH 软件版本号:
如果端口测试失败,则可以参阅如下文档针对客户端到服务器之间的网络做进一步排查分析:
Linux 系统的 PAM 安全框架,可以加载相关安全模块,对服务器的账户策略、登录策略等进行访问控制。如果相关配置存在异常,或触发了相关策略,就可能会导致 SSH 登录失败。与PAM 安全框架相关的常见案例如下:
Linux 内的系统环境(比如中毒、账户配置、环境变量配置等)如果出现异常,也可能会导致 SSH 登录失败。与 Linux 系统环境相关的常见案例如下:
SSH 服务的默认配置文件为 /etc/ssh/sshd_config。配置文件中的相关参数配置异常,或启用了相关特性或策略,也可能会导致 SSH 登录失败。与 SSH 服务及参数配置相关的常见案例如下:
SSH 服务基于安全性考虑,在运行时,会对相关目录或文件的权限配置、属组等进行检查。过高或过低的权限配置,都可能会引发服务运行异常,进而导致客户端登录失败。与 SSH 服务关联目录或文件配置相关的常见案例如下:
SSH 服务采用非对称加密技术,对所传输的数据进行加密。客户端及服务端会交换和校验相关密钥信息的有效性。与 SSH 服务密钥配置相关的常见案例如下:
如果根据前述问题场景进行排查和处理后,还是无法正常登录。则建议按照如下步骤进行逐一排查分析:
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >tailf </span><span class = "pun" >/</span><span class = "pln" >var</span><span class = "pun" >/</span><span class = "pln" >log</span><span class = "pun" >/</span><span class = "pln" >secure</span></li> </ol> |
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >ssh </span><span class = "pun" >-</span><span class = "pln" >vvv </span><span class = "pun" ><服务器</span><span class = "pln" > IP</span><span class = "pun" >></span><br><br><span class = "pun" >比如:</span><br><span class = "pun" >[</span><span class = "pln" >root @centos </span><span class = "pun" >~]#</span><span class = "pln" > ssh </span><span class = "pun" >-</span><span class = "pln" >vvv </span><span class = "lit" > 192.168 </span><span class = "pun" >.</span><span class = "lit" > 0.1 </span><br><span class = "typ" >OpenSSH_5</span><span class = "pun" >.</span><span class = "lit" >3p1</span><span class = "pun" >,</span><span class = "pln" > </span><span class = "typ" >OpenSSL</span><span class = "pln" > </span><span class = "lit" > 1.0 </span><span class = "pun" >.</span><span class = "lit" >1e</span><span class = "pun" >-</span><span class = "pln" >fips </span><span class = "lit" > 11 </span><span class = "pln" > </span><span class = "typ" >Feb</span><span class = "pln" > </span><span class = "lit" > 2013 </span><br><span class = "pln" >debug1</span><span class = "pun" >:</span><span class = "pln" > </span><span class = "typ" >Reading</span><span class = "pln" > configuration data </span><span class = "pun" >/</span><span class = "pln" >etc</span><span class = "pun" >/</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >ssh_config</span><br><span class = "pln" >debug1</span><span class = "pun" >:</span><span class = "pln" > </span><span class = "typ" >Applying</span><span class = "pln" > options </span><span class = "kwd" > for </span><span class = "pln" > </span><span class = "pun" >*</span><br><span class = "pln" >debug2</span><span class = "pun" >:</span><span class = "pln" > ssh_connect</span><span class = "pun" >:</span><span class = "pln" > needpriv </span><span class = "lit" > 0 </span><br><span class = "pln" >debug1</span><span class = "pun" >:</span><span class = "pln" > </span><span class = "typ" >Connecting</span><span class = "pln" > to </span><span class = "lit" > 192.168 </span><span class = "pun" >.</span><span class = "lit" > 0.1 </span><span class = "pln" > </span><span class = "pun" >[</span><span class = "lit" > 192.168 </span><span class = "pun" >.</span><span class = "lit" > 0.1 </span><span class = "pun" >]</span><span class = "pln" > port </span><span class = "lit" > 22 .</span><br><span class = "pln" >debug1</span><span class = "pun" >:</span><span class = "pln" > connect to address </span><span class = "lit" > 192.168 </span><span class = "pun" >.</span><span class = "lit" > 0.1 </span><span class = "pln" > port </span><span class = "lit" > 22 </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "typ" >Connection</span><span class = "pln" > timed out</span><br><span class = "pln" >ssh</span><span class = "pun" >:</span><span class = "pln" > connect to host </span><span class = "lit" > 192.168 </span><span class = "pun" >.</span><span class = "lit" > 0.1 </span><span class = "pln" > port </span><span class = "lit" > 22 </span><span class = "pun" >:</span><span class = "pln" > </span><span class = "typ" >Connection</span><span class = "pln" > timed out</span></li> </ol> |
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pun" >[</span><span class = "pln" >root @centos </span><span class = "pun" >~]#</span><span class = "pln" > service sshd status</span><br><span class = "pln" >openssh</span><span class = "pun" >-</span><span class = "pln" >daemon </span><span class = "pun" >(</span><span class = "pln" >pid </span><span class = "lit" > 31350 </span><span class = "pun" >)</span><span class = "pln" > is running</span><span class = "pun" >…</span><br><span class = "pun" >[</span><span class = "pln" >root @centos </span><span class = "pun" >~]#</span><span class = "pln" > service sshd restart</span><br><span class = "typ" >Stopping</span><span class = "pln" > sshd</span><span class = "pun" >:</span><span class = "pln" > </span><span class = "pun" >[</span><span class = "pln" > OK </span><span class = "pun" >]</span><br><span class = "typ" >Starting</span><span class = "pln" > sshd</span><span class = "pun" >:</span><span class = "pln" > </span><span class = "pun" >[</span><span class = "pln" > OK </span><span class = "pun" >]</span></li> </ol> |
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >netstat </span><span class = "pun" >-</span><span class = "pln" >ano </span><span class = "pun" >|</span><span class = "pln" > grep </span><span class = "lit" > 0.0 </span><span class = "pun" >.</span><span class = "lit" > 0.0 </span><span class = "pun" >:</span><span class = "lit" > 22 </span><br><span class = "pln" >tcp </span><span class = "lit" > 0 </span><span class = "pln" > </span><span class = "lit" > 0 </span><span class = "pln" > </span><span class = "lit" > 0.0 </span><span class = "pun" >.</span><span class = "lit" > 0.0 </span><span class = "pun" >:</span><span class = "lit" > 22 </span><span class = "pln" > </span><span class = "lit" > 0.0 </span><span class = "pun" >.</span><span class = "lit" > 0.0 </span><span class = "pun" >:*</span><span class = "pln" > LISTEN off </span><span class = "pun" >(</span><span class = "lit" > 0.00 </span><span class = "pun" >/</span><span class = "lit" > 0 </span><span class = "pun" >/</span><span class = "lit" > 0 </span><span class = "pun" >)</span></li> </ol> |
注意:本文相关配置及说明已在 CentOS 6.5 64 位操作系统中进行过测试。其它类型及版本操作系统配置可能有所差异,具体情况请参阅相应操作系统官方文档。
SSH 服务在进行数据传输前,会先进行密钥交换和协商确认。完成后再对后续数据进行加密传输,以提高安全性。本文先对 SSH 服务所采用的非对称加密技术进行简要介绍,然后对 SSH 连接过程中的相关交互,及关联文件进行说明。
SSH 服务基于非对称加密(public-key cryptography,也称公开密钥加密)技术实现数据加密传输。该技术会生成一对数学相关的密钥,其中一个用于对数据进行加密,而且只能用于加密,而另一个只能用于解密。使用加密密钥加密后的数据,只能用对应的解密密钥才能解密。而且,只知道其中一个密钥,无法计算出另一个。因此,如果公开了一对密钥中的一个,并不会危害到另一个的秘密性质。通常把公开的密钥称为公钥(public key),而不公开的密钥称为私钥(private key)。
如果公开的是解密密钥,该场景用于客户端验证持有私钥一方发布的数据或文件的完整性、准确性,以防止数据篡改。相应的密钥称为数字签名(数字证书)。如果公开的是加密密钥,该场景用于客户给私钥所有者上传数据,称为公开密钥加密。 SSH 服务基于该场景实现。
与对称密钥加密相比,非对称加密的优点在于不存在共享的通用密钥。由于解密用的私钥无需发送给任何用户,所以可以避免密钥被劫持或篡改。而加密用的公钥即便被劫持或篡改,如果没有与其匹配的私钥,也无法解密数据。所以,截获的公钥是没有任何用处的。
当前,SSH主要采用 RSA 算法(协议 V2 默认算法)和 DSA 算法(协议 V1 仅支持该算法)来实现非对称加密技术。
SSH 服务建立连接时的相关交互过程,如下SSH 服务连接交互示意图 所示:
连接过程中的相关交互步骤,详细说明如下。
服务端在每次启动 SSH 服务时,都会自动检查 /etc/ssh/ 目录下相关密钥文件的有效性。如果相关文件检查发现异常,则会导致服务启动失败,并抛出相应错误信息。 如果文件相关不存在,则会自动重新创建。
默认创建的相关文件及用途说明如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >ll </span><span class = "pun" >/</span><span class = "pln" >etc</span><span class = "pun" >/</span><span class = "pln" >ssh</span><span class = "pun" >/</span><br><code><span class = "pln" >bash</span></code></li> <li class = "L1" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-------.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 125811 </span><span class = "pln" > </span><span class = "typ" >Aug</span><span class = "pln" > </span><span class = "lit" > 13 </span><span class = "pln" > </span><span class = "lit" > 2015 </span><span class = "pln" > moduli </span><span class = "pun" >→</span><span class = "pln" > </span><span class = "pun" >用于</span><span class = "pln" > DH</span><span class = "pun" >-</span><span class = "pln" >GEX </span><span class = "pun" >算法<</span><span class = "pln" >br</span><span class = "pun" >></span></code></li> <li class = "L2" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-</span><span class = "pln" >r</span><span class = "pun" >--</span><span class = "pln" >r</span><span class = "pun" >--.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 2047 </span><span class = "pln" > </span><span class = "typ" >Aug</span><span class = "pln" > </span><span class = "lit" > 13 </span><span class = "pln" > </span><span class = "lit" > 2015 </span><span class = "pln" > ssh_config </span><span class = "pun" >→</span><span class = "pln" > SSH </span><span class = "pun" >客户端配置文件<</span><span class = "pln" >br</span><span class = "pun" >></span></code></li> <li class = "L3" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-------.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 3879 </span><span class = "pln" > </span><span class = "typ" >Aug</span><span class = "pln" > </span><span class = "lit" > 13 </span><span class = "pln" > </span><span class = "lit" > 2015 </span><span class = "pln" > sshd_config </span><span class = "pun" >→</span><span class = "pln" > SSH </span><span class = "pun" >服务配置文件<</span><span class = "pln" >br</span><span class = "pun" >></span></code></li> <li class = "L4" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-------.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 672 </span><span class = "pln" > </span><span class = "typ" >May</span><span class = "pln" > </span><span class = "lit" > 20 </span><span class = "pln" > </span><span class = "lit" > 14 </span><span class = "pun" >:</span><span class = "lit" > 22 </span><span class = "pln" > ssh_host_dsa_key </span><span class = "pun" >→</span><span class = "pln" > DSA </span><span class = "pun" >算法私钥<</span><span class = "pln" >br</span><span class = "pun" >></span></code></li> <li class = "L5" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-</span><span class = "pln" >r</span><span class = "pun" >--</span><span class = "pln" >r</span><span class = "pun" >--.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 590 </span><span class = "pln" > </span><span class = "typ" >May</span><span class = "pln" > </span><span class = "lit" > 20 </span><span class = "pln" > </span><span class = "lit" > 14 </span><span class = "pun" >:</span><span class = "lit" > 22 </span><span class = "pln" > ssh_host_dsa_key</span><span class = "pun" >.</span><span class = "pln" >pub </span><span class = "pun" >→</span><span class = "pln" > DSA </span><span class = "pun" >算法公钥<</span><span class = "pln" >br</span><span class = "pun" >></span></code></li> <li class = "L6" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-------.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 963 </span><span class = "pln" > </span><span class = "typ" >May</span><span class = "pln" > </span><span class = "lit" > 20 </span><span class = "pln" > </span><span class = "lit" > 14 </span><span class = "pun" >:</span><span class = "lit" > 22 </span><span class = "pln" > ssh_host_key </span><span class = "pun" >→</span><span class = "pln" > SSH V1 </span><span class = "pun" >版</span><span class = "pln" >RSA </span><span class = "pun" >算法私钥<</span><span class = "pln" >br</span><span class = "pun" >></span></code></li> <li class = "L7" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-</span><span class = "pln" >r</span><span class = "pun" >--</span><span class = "pln" >r</span><span class = "pun" >--.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 627 </span><span class = "pln" > </span><span class = "typ" >May</span><span class = "pln" > </span><span class = "lit" > 20 </span><span class = "pln" > </span><span class = "lit" > 14 </span><span class = "pun" >:</span><span class = "lit" > 22 </span><span class = "pln" > ssh_host_key</span><span class = "pun" >.</span><span class = "pln" >pub </span><span class = "pun" >→</span><span class = "pln" > SSH V1 </span><span class = "pun" >版</span><span class = "pln" > RSA </span><span class = "pun" >算法公钥<</span><span class = "pln" >br</span><span class = "pun" >></span></code></li> <li class = "L8" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-------.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 1675 </span><span class = "pln" > </span><span class = "typ" >May</span><span class = "pln" > </span><span class = "lit" > 20 </span><span class = "pln" > </span><span class = "lit" > 14 </span><span class = "pun" >:</span><span class = "lit" > 22 </span><span class = "pln" > ssh_host_rsa_key </span><span class = "pun" >→</span><span class = "pln" > SSH V2 </span><span class = "pun" >版</span><span class = "pln" > RSA </span><span class = "pun" >算法私钥<</span><span class = "pln" >br</span><span class = "pun" >></span></code></li> <li class = "L9" ><code><span class = "pun" >-</span><span class = "pln" >rw</span><span class = "pun" >-</span><span class = "pln" >r</span><span class = "pun" >--</span><span class = "pln" >r</span><span class = "pun" >--.</span><span class = "pln" > </span><span class = "lit" > 1 </span><span class = "pln" > root root </span><span class = "lit" > 382 </span><span class = "pln" > </span><span class = "typ" >May</span><span class = "pln" > </span><span class = "lit" > 20 </span><span class = "pln" > </span><span class = "lit" > 14 </span><span class = "pun" >:</span><span class = "lit" > 22 </span><span class = "pln" > ssh_host_rsa_key</span><span class = "pun" >.</span><span class = "pln" >pub </span><span class = "pun" >→</span><span class = "pln" > SSH V2 </span><span class = "pun" >版</span><span class = "pln" > RSA </span><span class = "pun" >算法公钥</span></code></li> </ol> |
服务端 SSH 服务正常运行后,客户端连接时,进行如下交互:
ssh_host_rsa_key.pub
文件中的内容返回客户端。相关信息通过明文发送。1 2 3 4 5 6 7 8 9 10 11 | <ol class = "linenums" > <li class = "L0" ><code><span class = "pln" >bash</span></code></li> <li class = "L1" ><code><span class = "typ" >The</span><span class = "pln" > authenticity of host </span><span class = "str" > '192.168.0.1 (192.168.0.1)' </span><span class = "pln" > can</span><span class = "str" >'t be established.</span></code></li> <li class = "L2" ><code><span class = "str" >RSA key fingerprint is c2: 49 :d9: 43 : 74 :d5:ed:bc: 28 :9b:d2:7b: 63 : 94 :cf:bc.</span></code></li> <li class = "L3" ><code><span class = "str" >Are you sure you want to continue connecting (yes/no)?</span></code></li> </ol> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <ol class = "linenums" > <li class = "L0" ><code><span class = "pln" >bash</span></code></li> <li class = "L1" ><code><span class = "pln" >cat </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >known_hosts</span></code></li> <li class = "L2" ><code></code></li> <li class = "L3" ><code><span class = "pln" >IP </span><span class = "pun" >明文显示:</span></code></li> <li class = "L4" ><code><span class = "lit" > 192.168 </span><span class = "pun" >.</span><span class = "lit" > 0.1 </span><span class = "pln" > ssh</span><span class = "pun" >-</span><span class = "pln" >rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA3sdlboGEgY9buZpkPuygPw0NxAvmxYd0mc3fo2MgP</span><span class = "pun" >+</span><span class = "typ" >JqgFC9</span><span class = "pun" >/</span><span class = "lit" >9ZXOgDXKJrjE2HKBieJZSPKGncIh</span><span class = "pun" >+</span><span class = "pln" >zLxTvmykeJQBXv7i1GiUjW</span><span class = "pun" >+</span><span class = "pln" >H3VY69Ge3AdGfCd</span><span class = "pun" >+</span><span class = "pln" >XF</span><span class = "pun" >+</span><span class = "typ" >Cvi1e</span><span class = "pun" >+</span><span class = "pln" >j18zhHnjSzvIBoNpT5cBWWNbw7mNHCwTb0sHAVUkWR4Ck</span><span class = "pun" >/</span><span class = "pln" >LM5</span><span class = "pun" >/</span><span class = "pln" >rQ09A</span><span class = "pun" >+</span><span class = "pln" >m6BLfZJL8CRNGxKTbyINi6o812S</span><span class = "pun" >+</span><span class = "typ" >Cy64WqDs1nTpIXp2Bkcpjclb36bFSs9Z</span><span class = "pun" >/</span><span class = "pln" >tWNuJl7A</span><span class = "pun" > //</span><span class="lit">7HNtxMgFGBnE07Ykvvy8s06DUmkyFy8GcXGBpnfdg9utLodfQLFQnKflCQZ110BpQaCWlWPjU9dc4w3XLJ</span><span class="pun">/</span><span class="pln">XQOP4w</span><span class="pun">==</span></code></li> <li class = "L5" ><code></code></li> <li class = "L6" ><code><span class = "pln" >IP </span><span class = "pun" >做了加密处理:</span></code></li> <li class = "L7" ><code><span class = "pun" >|</span><span class = "lit" > 1 </span><span class = "pun" >|</span><span class = "lit" >3efXAZ4sNHcUcHamBy4gDriblc8</span><span class = "pun" >=|</span><span class = "lit" >8idBhLq9aLl2sfh4KswMsk4sPFI</span><span class = "pun" >=</span><span class = "pln" > ssh</span><span class = "pun" >-</span><span class = "pln" >rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwS4DE3hok8RCkxYlTxsexNrNa62e05UGSkoP7ie26DDWjG1Aoc74cCsE4is9p7lEfFUYYlAzeYhPqE</span><span class = "pun" >/</span><span class = "pln" >yGf5YxRZUOU2IeFI4cEqo8YZr7edVYpgAq2f2J0zMwk1syenD12lmUPkYA4mMB6it3jxXR5k</span><span class = "pun" >+</span><span class = "pln" >H0HZh9YA7mRXkiTjlkAMWirBcnUvtKYRv9LRIr3ikUiPy2gfZO291Ae9zuTsWwEtHQxIpiBgk3vwF2gCUFlX9y</span><span class = "pun" > //</span><span class="typ">IsMjdQq5prk7x3BjXhUorqgJO1gt1VHW8Xxx9Oe50YF1hi9DuE6VXwyh4xfHTmauRQybwsYafdA3HxrA2od6x9l19D9EH7xHAjDa5w</span><span class="pun">==</span></code></li> </ol> |
客户端生成临时密钥对:
服务端公钥校验及确认后,客户端会生成一对临时密钥用于客户端加密。该密钥对不会存储到文件,而是记录在内存中。每次连接都会重新生成临时密钥对。
客户端发送公钥信息:
客户端向服务端,发送前述生成的临时密钥对中的公钥信息。相关信息通过明文发送。
至此,服务端及客户端都拥有对方的公钥和自身的私钥,所以称为非对称加密。
后续登录校验及正常的数据传输,都会通过双向加密方式进行。相关交互说明如下:
注意:本文相关配置及说明已在 CentOS 6.5 64 位操作系统中进行过测试。其它类型及版本操作系统配置可能有所差异,具体情况请参阅相应操作系统官方文档。
SSH 服务可以对所有传输的数据进行加密,提供比传统 telnet 服务更高的安全性(更多关于SSH 服务的连接交互过程,可以参阅 云服务器 ECS Linux SSH 连接交互过程简介)。而基于密钥认证的 SSH 自动化登录,在保障安全性的同时,可以简化登录过程,降低运维成本。本文先简要介绍基于密钥交换的 SSH 自动登录的原理,然后对配置方法进行说明。
SSH证书认证登录的基础是一对唯一匹配密钥: 私钥(private key)和公钥(public key)。公钥用于对数据进行加密,而且只能用于加密。而私钥只能对使用所匹配的公钥,所加密过的数据进行解密。私钥需要用户单独妥善保管。SSH 客户端使用私钥向服务器证明自已的身份。而公钥是公开的,可以按需将其配置到目标服务器上自己的相应帐号中。
在进行 SSH 登录认证时,进行私钥和公钥协商。如果匹配,则身份得以证明,认证成功,允许登录。否则,将会继续使用密码验证等其它方式进行登录校验。SSH 证书验证登录配置及登录协商过程,如下证书校验交互登录流程示意图所示:
各步骤补充说明如下:
客户端向目标服务器发送登录请求。在SSH 服务启用了证书验证登录方式后,会优先通过证书验证方式进行登录验证。
目标服务器生成一串随机数,然后使用相应的公钥对其加密。
目标服务器将加密后的密文发回客户端。
客户端使用默认目录或 -i 参数指定的私钥尝试解密。
如果解密失败,则会继续尝试密码验证等其它方式进行登录校验。如果解密成功,则将解密后的原文信息重新发送给目标服务器。意思类似于: “看,这是这段话的原文。我能读懂发过来的密文,我拥有服务器的控制权,请让我登录。”
目标服务器对客户端返回的信息进行比对。如果比对成功,则表示认证成功,客户端可以登录。如果对比失败,则表示认证失败,则会继续尝试密码验证等其它方式进行登录校验。
SSH 协议 V1只使用 RSA 算法,而 SSH 协议V2 对 RSA 算法和 DSA 算法都支持。目前所有OpenSSH 版本都应该对两种算法都支持。两种算法的密钥的生成指令和使用方法相同,本文仅以 RSA 算法为例进行相关说明。
生成密钥对的时候,可以按需决定是否设置密码。但需要注意的是,如果设置了密码,还需结合 ssh-agent 代理和 ssh-add 配置才能实现自动登录。同时,相关配置只对 ssh-agent 启动的相应 shell 生效,用户退出后重新登录时还需重新配置。所以,为简便起见,本文以常见的、不配置密码的情况进行说明。
可以在任意支持环境下生成密钥对。Windows 和 Linux 环境下,配置分别说明如下。
在 Windows 环境下,通常借助各种应用软件来创建和管理密钥对。以常见的 PuTTYgen 为例,请执行如下步骤创建密钥对:
在 Linux 环境下,通常使用系统自带的 ssh-keygen 软件来创建和管理密钥对。请执行如下步骤创建密钥对:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <ol class = "linenums" > <li class = "L0" ></li> <li class = "L1" ><span class = "pln" >ssh</span><span class = "pun" >-</span><span class = "pln" >keygen </span><span class = "pun" >-</span><span class = "pln" >t rsa</span></li> <li class = "L2" ><span class = "typ" >Generating</span><span class = "pln" > public </span><span class = "pun" >/</span><span class = "pln" > private rsa key pair</span><span class = "pun" >.</span></li> <li class = "L3" ><span class = "typ" >Enter</span><span class = "pln" > file </span><span class = "kwd" >in</span><span class = "pln" > which to save the key </span><span class = "pun" >(/</span><span class = "pln" >root</span><span class = "pun" >/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >id_rsa</span><span class = "pun" >):</span><span class = "pln" > </span><span class = "pun" >→</span><span class = "pln" > </span><span class = "pun" >默认保存路径和文件名,可以按需修改。</span></li> <li class = "L4" ><span class = "typ" >Enter</span><span class = "pln" > passphrase </span><span class = "pun" >(</span><span class = "pln" >empty </span><span class = "kwd" > for </span><span class = "pln" > no passphrase</span><span class = "pun" >):</span><span class = "pln" > </span><span class = "pun" >→</span><span class = "pln" > </span><span class = "pun" >如前面所述,不设置密码,回车确认即可。</span></li> <li class = "L5" ><span class = "typ" >Enter</span><span class = "pln" > same passphrase again</span><span class = "pun" >:</span><span class = "pln" > </span><span class = "pun" >→</span><span class = "pln" > </span><span class = "pun" >不设置密码,回车确认即可。</span></li> <li class = "L6" ><span class = "typ" >Your</span><span class = "pln" > identification has been saved </span><span class = "kwd" >in</span><span class = "pln" > </span><span class = "pun" >/</span><span class = "pln" >root</span><span class = "pun" >/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >id_rsa</span><span class = "pun" >.</span><span class = "pln" > </span><span class = "pun" >→</span><span class = "pln" > </span><span class = "pun" >创建的私钥文件。</span></li> <li class = "L7" ><span class = "typ" >Your</span><span class = "pln" > public key has been saved </span><span class = "kwd" >in</span><span class = "pln" > </span><span class = "pun" >/</span><span class = "pln" >root</span><span class = "pun" >/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >id_rsa</span><span class = "pun" >.</span><span class = "pln" >pub</span><span class = "pun" >.</span><span class = "pln" > </span><span class = "pun" >→</span><span class = "pln" > </span><span class = "pun" >创建的公钥文件。</span></li> <li class = "L8" ><span class = "typ" >The</span><span class = "pln" > key fingerprint is</span><span class = "pun" >:</span></li> <li class = "L9" ><span class = "lit" > 17 </span><span class = "pun" >:</span><span class = "pln" >b8</span><span class = "pun" >:</span><span class = "lit" >0e</span><span class = "pun" >:</span><span class = "lit" > 76 </span><span class = "pun" >:</span><span class = "pln" >cb</span><span class = "pun" >:</span><span class = "lit" > 57 </span><span class = "pun" >:</span><span class = "lit" > 21 </span><span class = "pun" >:</span><span class = "lit" >3b</span><span class = "pun" >:</span><span class = "pln" >f2</span><span class = "pun" >:</span><span class = "pln" >bb</span><span class = "pun" >:</span><span class = "lit" >8b</span><span class = "pun" >:</span><span class = "pln" >a2</span><span class = "pun" >:</span><span class = "lit" > 42 </span><span class = "pun" >:</span><span class = "lit" >2b</span><span class = "pun" >:</span><span class = "lit" > 54 </span><span class = "pun" >:</span><span class = "pln" >be root @iZ233gr74jvZ </span></li> <li class = "L0" ><span class = "typ" >The</span><span class = "pln" > key</span><span class = "str" >'s randomart image is:</span></li> <li class = "L1" ><span class = "str" >+--[ RSA 2048 ]----+</span></li> <li class = "L2" ><span class = "str" >| |</span></li> <li class = "L3" ><span class = "str" >| . |</span></li> <li class = "L4" ><span class = "str" >| . o . |</span></li> <li class = "L5" ><span class = "str" >| . . + . |</span></li> <li class = "L6" ><span class = "str" >| o o S + . |</span></li> <li class = "L7" ><span class = "str" >| ... . = = o |</span></li> <li class = "L8" ><span class = "str" >|.. .. + o |</span></li> <li class = "L9" ><span class = "str" >|. oE . o . |</span></li> <li class = "L0" ><span class = "str" >| . ... .. +o |</span></li> <li class = "L1" ><span class = "str" >+-----------------+</span></li> </ol> |
说明:
如果 .ssh 目录不存在,程序会自动创建。
生成的密钥对默认保存在当前用户家目录下的 .ssh 文件夹中,文件名默认为 id_rsa(私钥) 和 id_rsa.pub(公钥)。用户可以按需设置保存路径和文件名。
生成密钥对后,进行如下处理:
私钥用于信息校验,请确保安全。可以将私钥上传到其它源服务器上,或者直接参阅前述说明创建新的密钥对。
公钥信息需要写入目标服务器、目标用户的配置文件中,默认配置文件为对应用户家目录下 .ssh 文件夹中的 authorized_keys,即:
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >authorized_keys</span></li> </ol> |
可以复制公钥信息后,直接通过 vi 等编辑器将其写入上述文件。或者通过如下指令,在源服务器上配置写入:
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >cat </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >id_rsa</span><span class = "pun" >.</span><span class = "pln" >pub </span><span class = "pun" >|</span><span class = "pln" > ssh </span><span class = "pun" ><用户名>@<目标服务器</span><span class = "pln" >IP</span><span class = "pun" >></span><span class = "pln" > </span><span class = "pun" >‘</span><span class = "pln" >cat </span><span class = "pun" >>></span><span class = "pln" > </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >authorized_keys</span><span class = "pun" >’;比如:</span><span class = "pln" >cat </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >id_rsa</span><span class = "pun" >.</span><span class = "pln" >pub </span><span class = "pun" >|</span><span class = "pln" > ssh root @120 </span><span class = "pun" >.</span><span class = "lit" > 26.38 </span><span class = "pun" >.</span><span class = "lit" > 248 </span><span class = "pln" > </span><span class = "pun" >‘</span><span class = "pln" >cat </span><span class = "pun" >>></span><span class = "pln" > </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >authorized_keys</span><span class = "pun" >’;</span></li> </ol> |
注意:
如果修改了默认的目录或文件名,则需要同步修改SSH 服务配置文件(默认为/etc/ssh/sshd_config)中的AuthorizedKeysFile 参数,否则会因找不到公钥信息而导致自动登录失败。
要顺利完成自动登录,还需对SSH 服务相关参数及关联文件、文件夹的权限进行确认或调整。
SSH 服务默认开启了证书认证支持。编辑 SSH 服务配置文件(默认为/etc/ssh/sshd_config),确保如下参数没有显示的置为 no。否则,将参数值修改为 yes,或者整个删除或注释(在最开头添加 # 号)整行配置。比如:
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "com" >#RSAAuthentication yes#PubkeyAuthentication yes</span></li> </ol> |
同时,如前面所述,如果修改了默认的公钥路径或文件名,还需确保 AuthorizedKeysFile 参数值配置的信息与其一致。
注意:如果对相关参数做了修改,需要重启 SSH 服务生效。
SSH 服务证书验证方式登录,对相关目录和文件的权限有要求。权限配置异常可能会导致登录失败。
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >chmod </span><span class = "lit" > 700 </span><span class = "pln" > </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span></li> </ol> |
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >chmod </span><span class = "lit" > 600 </span><span class = "pln" > </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >authorized_keys</span></li> </ol> |
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >chmod </span><span class = "lit" > 400 </span><span class = "pln" > </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >authorized_keyschattr </span><span class = "pun" >+</span><span class = "pln" >i </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span><span class = "pun" >/</span><span class = "pln" >authorized_keyschattr </span><span class = "pun" >+</span><span class = "pln" >i </span><span class = "pun" >~/.</span><span class = "pln" >ssh</span></li> </ol> |
完成上述配置后,在客户端即可免密码直接登录。说明如下:
您可以参阅文档 使用 SSH 密钥对连接 Linux 实例。
Linux 环境下,在客户端直接通过 ssh 软件免密码登录:
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >ssh </span><span class = "pun" ><用户名>@<目标服务器></span><span class = "pln" > </span><span class = "com" ># 比如:ssh root @192 .168. 0.1 </span></li> </ol> |
如果修改了私钥路径或文件名,则需要通过 –i 参数进行指定:
1 2 3 4 5 | <ol class = "linenums" > <li class = "L0" ><span class = "pln" >ssh </span><span class = "pun" >–</span><span class = "pln" >i </span><span class = "pun" ><私钥路径及文件名></span><span class = "pln" > </span><span class = "pun" ><用户名>@<目标服务器></span><span class = "pln" > </span><span class = "com" >#比如:ssh -i /bak/my_rsa user @192 .168. 0.1 </span></li> </ol> |