博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

ssh使用密钥认证

Posted on 2020-06-09 12:57  面具下的戏命师  阅读(906)  评论(2编辑  收藏  举报

ssh使用密钥认证

SSH 为 Secure Shell 的缩写,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。

验证方式

从客户端来看,SSH提供两种级别的安全验证。

(一)、基于口令的安全验证

只要你知道自己帐号和口令,就可以登录到远程主机。所有传输的数据都会被加密,但是不能保证你正在连接的服务器就是你想连接的服务器。可能会有别的服务器在冒充真正的服务器,也就是受到“中间人”这种方式的攻击。

(二)、基于密匙的安全验证

基于密钥的认证方式必须为自己创建一对密匙(公钥和私钥),并把公用密匙放在需要访问的服务器上。如果你要连接到SSH服务器上,客户端软件就会向服务器发出请求,请求用你的密匙进行安全验证。服务器收到请求之后,先在该服务器上你的主目录下寻找你的公用密匙,然后把它和你发送过来的公用密匙进行比较。如果两个密匙一致,服务器就用公用密匙加密“质询”(challenge)并把它发送给客户端软件。客户端软件收到“质询”之后就可以用你的私人密匙解密再把它发送给服务器。
第一种级别相比,第二种级别不需要在网络上传送口令。基于密钥认证可以实现免密码登录。此处主要总结一下与ssh相关的一些命令,我们使用ssh-keygen命令即可生成私钥与公钥。

生成公钥和密钥

直接执行ssh-keygen命令,会进入交互模式,并等待用户输入生成密钥文件的路径,私钥与公钥默认生成在当前用户家目录下的 .ssh 目录中。如果不指定其他路径,直接回车即可,如果对应目录下已经存在了同名的密钥文件,还会提示你是否覆盖。随后,出现了Enter passphrase(输入密码)的提示,我们可以为生成的私钥设置码,如果为私钥设置了密码,在每次使用私钥的时候,都会提示我们输入私钥的密码,直接回车,代表不为私钥设置密码,Enter same passphrase again表示确认密码。

[root@all ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
98:f3:e0:08:75:47:d7:d7:95:7b:3c:2e:1a:10:b2:d3 root@all
The key's randomart image is:
+--[ RSA 2048]----+
|        . ..   .+|
|       o o  . ...|
|    . . = .  . ..|
|   . . * E     oo|
|  .   = S .   . o|
|   . o +   . . . |
|    . . .   o .  |
|           .     |
|                 |
+-----------------+

完成上述步骤后,即在用户家目录的.ssh目录中生成了一对密钥文件,私钥文件id_rsa与公钥文件id_rsa.pub

从文件名称可以看出,我们生成的是rsa密钥,我们也可以选择其他算法,从而生成其他类型的密钥文件,默认生成RSA类型的密钥。在版本2的ssh协议中我们可以使用的密钥类型有: "dsa", "ecdsa", "ed25519", "rsa"。

拥有了自己的私钥与公钥,还需要把公钥交给要访问的服务器,才实现免密登录。假设我们要访问的服务器是 192.168.126.131 。这时候就可以使用 ssh-copy-id 命令完成公钥的交付工作。

ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.126.131

使用"-i"选项指定要传输的公钥,然后指明账户与IP地址。传输公钥第一次需要输入密码验证。

[root@all ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.126.131
root@192.168.126.131's password: 
Now try logging into the machine, with "ssh 'root@192.168.126.131'", and check in:

  .ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.

提示我们已经添加了密钥,可以通过 ssh root@192.168.126.131 进行验证了。

注意:也可以root用户的公钥发给其他服务器的普通账户,只有认证的两个用户之间可以免密登录。

我们已经把公钥交给了192.168.126.131的root账户。root将别人家的公钥放在了自己家目录的.ssh/authorized_keys文件中。通过查看可以发现,authorized_keys文件的内容和源服务器的id_rsq.pub的内容是一致的。所以,我们通过拷贝文件内容一样也可以实现公钥的交付。

cat ~/.ssh/id_rsa.pub | ssh -p 22 zsy@192.168.126.131 "umask 077;mkdir -p ~/.ssh;cat - >> ~/.ssh/authorized_keys"

上述这条命令和ssh-copy-id效果是相同的。纯手动的去'复制'、'粘贴'公钥中的内容,但是这样容易出错,因为对方服务器的账户中可能还没有对应的.ssh目录,也没有authorized_keys文件,你需要手动的创建它们,权限设置也容易出错,所以还是建议使用ssh-copy-id命令。

注意:有些服务的sshd服务不用默认端口,在使用ssh-copy-id命令时,需要指定端口,在redhat6 和 readhat7 中,命令略有差别。6需要加双引号

# 当前系统为redhat6
ssh-copy-id -i ~/.ssh/id_rsa.pub "zsy@192.168.126.131 -p 22222"

# 当前系统为redhat7:
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.126.131 -p 22222

常见问题

通常的问题是,你已经将本机的公钥推送到了对方服务器的某个账户中,但是仍然不能免密码登录对应账户。

出现上述问题,通常可能是由于如下原因引起的:

1、ssh服务端不支持基于公钥认证或者修改了默认的公钥认证文件

服务端可以禁用使用公钥认证的机制,PubkeyAuthentication配置项用于控制是否可以使用公钥进行认证,PubkeyAuthentication默认值为yes,表示支持公钥认证,服务端默认使用authorized_keys作为存储用户公钥的文件,在服务端的sshd_config配置文件中可以使用AuthorizedKeysFile配置项指定其他文件为认证文件。

2、ssh服务端相关目录或者文件的权限过大

服务端用户家目录.ssh目录的权限正常700,服务端用户家目录.ssh/authorized_keys文件的权限默认为600

3、ssh服务端的authorized_keys文件中包含windows字符

通常纯手动复制粘贴公钥内容到authorized_keys并且操作时经过windows系统处理,会出现这种情况

4、ssh客户端连接服务端时,没有指定对应账户的用户名

如果我们想要从hostB的B账户连接到hostA的A账户,则需要在hostB中执行命令ssh A@hostA,如果在hostB的B账户中直接执行命令ssh hostA,并没有指定连接的用户名,则表示连接到hostA中的B账户,也就是说,如果你在hostB的B账户中执行ssh hostA,相当于执行了ssh B@hostA,如果你把B的公钥交给了hostA的A账户,却在链接时没有指明A账户,则很有可能会连错账户,自然无法认证成功,这种低级错误在你有些疲惫的时候很难发觉。

5、ssh客户端的私钥权限过大,正常情况下,将私钥的权限设置为600即可,如果权限过大,可能会在连接ssh服务端时看到如下提示

Permissions 0644 for '/root/.ssh/id_rsa' are too open.

It is required that your private key files are NOT accessible by others.

This private key will be ignored.

bad permissions: ignore key: /root/.ssh/id_rsa

6、在创建密钥对时,没有使用默认的密钥名称,比如id_rsa或者id_dsa,而是使用了自定义的密钥名称,如果将自定义名称密钥对中的公钥拷贝到了远程主机中,在连接到远程主机时,需要指定对应的自定义名称的私钥才能够实现免密码连接,使用"-i"选项可以指定密钥,当指定密钥后,ssh会使用指定的密钥与远程主机上的公钥进行认证,否则ssh仍然使用默认名称的私钥进行认证,如果你自定义了密钥对的名称,但是在连接时没有指定对应私钥,由于默认私钥与远程主机中的自定义公钥不匹配,自然无法基于密钥进行认证,会再次提示你输入密码。

第一次登录询问

首次进行ssh链接时,出现以下提示:

The authenticity of host '192.168.100.1(192.168.100.1 )' can't be established.  RSA key fingerprint is a0:00:d3:33:54:96:40:03:ff:ad:15:a9:59:22:f4:2a.  

Are you sure you want to continue connecting (yes/no)?  

批量连接时或者在脚本中在跳出这个提示很麻烦。可以通过以下三种方式避免第一次登录询问 yes/no

一、修改配置文件

修改本机的/etc/ssh/ssh_config文件中的"# StrictHostKeyChecking ask" 为 "StrictHostKeyChecking no",然后重启sshd服务。

二、创建config文件

创建文件  ~/.ssh/config,添加一行:

StrictHostKeyChecking no

保存退出,再使用ssh连接其他机器就不再跳了

三、使用 -o 参数

ssh -o stricthostkeychecking=no