SSH 免密登录是怎么玩儿的?

作为一名运维人员,经常会遇到SSH登录,而当你有很多服务器的时候使用密码可能不是一个好的选择了, 就像我要登录自己的服务器、公司各个环境的服务器,虽然有工具可以帮我们做这些,但我习惯在命令行下操作。 下面我带你了解一下免密登录的原理和如何实现。

基本概念

SSH协议

SSH 是一种计算机之间加密登录的协议,它相对于telnet和rsh的明文传输, 提供了加密、校验和压缩,使得我们可以很安全的远程操作, 而不用担心信息泄露(当然不是绝对的,加密总有可能被破解,只是比起明文来说那是强了不少)。

加密

加密的意思是将一段数据经过处理之后,输出为一段外人无法或者很难破译的数据,除了指定的人可以解密之外。 一般来说,加密的输入还会有一个key,这个key作为加密的参数,而在解密的时候也会用一个相关联(有可能是相同)的key作为输入。 粗略来说是下面的流程:

# 加密方
encrypted_data = encrypt(raw_data, key)
# 解密方
raw_data = decrypt(encrypted_data, key1)

目前主流的加密算法一般分为下面两类:

  1. 私钥(secret key)加密,也称为对称加密
  2. 公钥(public key)加密

私钥加密

所谓的私钥加密,是说加密方和解密方用的都是同一个key,这个key对于加密方和解密方来说是保密的, 第三方是不能知道的。在第三方不知道私钥的情况下,是很难将加密的数据解密的。 一般来说是加密方先产生私钥,然后通过一个安全的途径来告知解密方这个私钥。

公钥加密

公钥加密,是说解密的一方首先生成一对密钥,一个私钥一个公钥,私钥不会泄漏出去,而公钥则是可以任意的对外发布的。 用公钥进行加密的数据,只能用私钥才能解密。加密方首先从解密方获取公钥,然后利用这个公钥进行加密,把数据发送给解密方。 解密方利用私钥进行解密。如果解密的数据在传输的过程中被第三方截获,也不用担心,因为第三方没有私钥,没有办法进行解密。

公钥加密的问题还包括获取了公钥之后,加密方如何保证公钥来自于确定的一方,而不是某个冒充的机器。 假设公钥不是来自我们信任的机器,那么就算我们用公钥加密也没有用,因为加密之后的数据是发送给了冒充的机器, 该机器就可以利用它产生的私钥进行解密了。所以公钥加密里面比较重要的一步是身份认证。

需要说明一下,一般的私钥加密都会比公钥加密快,所以大数据量的加密一般都会使用私钥加密, 而公钥加密会作为身份验证和交换私钥的一个手段。

数据一致性/完整性

数据一致性说得是如何保证一段数据在传输的过程中没有遗漏、破坏或者修改过。一般来说,目前流行的做法是对数据进行hash, 得到的hash值和数据一起传输,然后在收到数据的时候也对数据进行hash,将得到的hash值和传输过来的hash值进行比对, 如果是不一样的,说明数据已经被修改过;如果是一样的,则说明极有可能是完整的。

目前流行的hash算法有MD5SHA-1算法。

身份验证

身份验证说的是,判断一个人或者机器是不是就是你想要联系的。也就是说如果A想要和B通信,一般来说开始的时候会交换一些数据, A怎么可以判断发送回来的数据就真的是B发送的呢?现实中有很多方法可以假冒一个机器。

在SSH里面,这主要是通过公钥来完成的。首先客户端会有一个公钥列表,保存的是它信任的机器上面的公钥。 在开始SSH连接之后,服务器会发送过来一个公钥,然后客户端就会进行查找,如果这个公钥在这个列表里面,就说明这个机器是真的服务器。

当然实际的情况会复杂一些。实际上服务器不是真的发送公钥过来,因为这很容易被第三方盗取。

免密码登录

  1. 在自己的操作系统上生成一对SSH KEY,如果已经存在可以不生成
  2. 将公钥上传到服务器上

生成SSH私钥和公钥

ssh-keygen		# ssh-keygen不带参数默认为rsa加密

如果你只输入ssh-keygen生成的RSA密钥长度为2048,如果你对安全性要求比较高可以指定4096位的长度:

ssh-keygen -b 4096 -t rsa

这里-b就是多少位,当然你对这些参数感兴趣可以使用–help参数看看具体的含义和解释。

当你在生成SSHKEY的时候在命令行下会提示你Enter file in which to save the key,让你确认密钥文件保存的路径, 一般回车即可(一般默认会在当前用户家目录下的.ssh目录下)。

第二个提示是 Enter passphrase (empty for no passphrase) 让你输入一个密钥的密码,如果不输入则留空;回车生成公私钥完毕 :)

其实吧我们生成证书就是为了免密登录,如果说这里设置了密钥那么还是需要自己输入密码去解开证书加密的,所以博主推荐不设置密码

此时你可以使用cat命令看下自己的公私钥。

服务器配置

我们前面在自己的操作系统生成了公私钥,然后将公钥的内容告诉给服务器就可以了,让服务器知道自己公钥的操作方式还蛮多的。

上传公钥文件

将本地的公钥文件上传到服务器上,如果说你已经给服务器设置过别名了,那么这个过程将会非常的简单便捷,具体看下面的代码。

# 若已设置过别名
scp id_rsa.pub $你设置好的别名:
# 若无设置别名
scp -P $端口 id_rsa.pub $用户@$IP:

然后在服务器需要免密登录的用户家目录下查看是否有 ~/.ssh/authorized_keys 这个文件,如果没有手动创建一个:

touch ~/.ssh/authorized_keys

然后我们将公钥内容写入到authorized_keys文件中,因为这个文件可能已经有内容了,所以你可以使用如下方式

cat ~/id_rsa.pub >> ~/.ssh/authorized_keys

这样就将公钥内容追加到authorized_keys中了,然后需要注意配置权限了,否则SSH不会工作的,我在这里踩了坑。。

  1. 将.ssh目录的权限为700
  2. 将authorized_keys目录的权限为600

为服务器设置别名

Q::为什么要设置服务器别名?

A:设置了服务器别名后,可以用最便捷的方式登录服务器

配置本地的ssh,修改 ~/.ssh/config 文件(如果没有,新建一个):

image-20201028142649066

格式如上,主要由5个字段组成:服务器别名、服务器地址、端口、用户名、认证方式

基本上这些字段都比较通俗易懂,认证方式我个人比较推荐用IdentitiesOnly

IdentitiesOnly

指定 ssh 只能使用配置文件指定的 identity 和 certificate 文件或通过 ssh 命令行通过身份验证,即使 ssh-agent 或 PKCS11Provider 提供了多个 identities。值可以为 no(default)/yes。

如果说一切配置正常,那么使用使用ssh登录到服务器将会是一件非常爽快的事情

ssh $服务器别名

这一行命令就免密登录上你的机器啦