ssh登陆发生了什么?

1,103 阅读9分钟

ssh是什么?

SSH 是 secure shell 的缩写,是一个安全远程管理的服务。

它是一个建立在应用层上的安全远程管理协议,算是目前较为可靠的一个传输协议,专门为远程登陆会话和其他网络服务器提供安全性,利用 ssh 协议可以有效防止远程管理过程中的信息泄露问题。

这个协议可用于大多数的 UNIX 操作系统中,它能够实现字符界面的远程登录管理,它默认使用 22 端口,采用密文的形式在网络中传输资源,相对于通过明文传输的 Telnet 协议,具有更高的安全性。

SSH 提供了基于账户密码和密钥对两种登陆验证方式,这两者都是通过密文传输数据的。

密码登陆

查看已有用户和密码

linux 服务器初始是root账户, 服务器只有root账户和密码的信息, 可以登陆linux服务器查看用户名和密码(root账户可以查看所有用户和密码, 普通用户只能查看用户账号信息)

这里以root用户查看为例:

查看已有用户

vim /etc/passwd

可以看到如下内容:

上面每一行都代表一个用户,每一行又通过[:]分为七个部分:

1、账号名称

2、原先用来保存密码的,现在密码都放在/etc/shadow中,所以这里显示x

3、UID,也就是使用者ID。默认的系统管理员的UID为0,我们添加用户的时候最好使用1000以上的UID,1-1000范围的UID最好保留给系统用。

4、GID,也就是群组ID

5、关于账号的一些说明信息

6、账号的home目录,home目录就是你登陆系统后默认的那个目录

7、账号使用的shell类型

查看用户密码

vim /etc/shadow

可以看到如下内容:

这里也是由[:]来进行分割,一共分出来九个部分:

1、账户名称(和passwd文件里的账户信息是对应的)

2、加密后的密码,如果这一栏的第一个字符为!或者*的话,说明这是一个不能登录的账户,从上面可以看出,bin账户就无法登陆。

3、最近改动密码的日期(不是日期吗,咋是一堆数字,别急,这个是从1970年1月1日算起的总的天数)。那怎么才能知道今天距1970年1月1日有多少天呢?很简单,你改下密码,然后看下这个栏目中的数字是多少就可以了!

4、密码不可被变更的天数:设置了这个值,则表示从变更密码的日期算起,多少天内无法再次修改密码,如果是0的话,则没有限制

5、密码需要重新变更的天数:密码经常更换才能保证安全,为了提醒某些经常不更换密码的用户,可以设置一个天数,强制让用户更换密码,也就是说该用户的密码会在多少天后过期,如果为99999则没有限制

6、密码过期预警天数:如果在5中设置了密码需要重新变更的天数,则会在密码过期的前多少天进行提醒,提示用户其密码将在多少天后过期

7、密码过期的宽恕时间:如果在5中设置的日期过后,用户仍然没有修改密码,则该用户还可以继续使用的天数

8、账号失效日期,过了这个日期账号就不能用了

9、保留的, 未使用

创建新用户

在root账户下:

  1. 创建用户
useradd newtestuser

此时passwd文件下已有该用户

但是此时shadow文件下,该账户是不可访问的

  1. 设置密码
passwd newuser

再此查看shadow文件

此时用户创建完毕

  1. 附赠删除用户的命令
userdel -r newuser

该命令不止会删除该用户相关的配置, 包括用户所属的文件都会被删除

ssh用户名密码登陆

前面说了那么多linux用户名密码相关的知识, 现在可以使用ssh命令直接登陆了

ssh 用户名@服务器域名(或者ip)
例如 ssh root@192.168.1.1

ssh用户名密码登陆的验证过程

  1. Client → Server:连接请求

  2. Server → Client:发送公钥

  3. Client → Server:用公钥将密码信息加密,发送

  4. Server → Client:用私钥解密并验证消息,信息合法则建立连接通讯账户密码登录认证过程中传输的是用户的账户名和密码,密码具有足够的复杂度才能具有更高的安全性。

密钥登陆(即免用户名密码的登陆)

密钥登陆的流程

密钥登录比密码登录安全,主要是因为他使用了非对称加密,登录过程中需要用到密钥对。整个登录流程如下:

前提是客户端自己生成密钥对,事先将公钥上传存储到远程服务器上,私钥自己保管

Client → Server:用户发送连接请求,并将公钥发送;

Server → Client:验证本地公钥和发送过来的公钥,如果两钥相同,服务器就会随机生成一串字符串,然后发送给正在进行登录的用户。

Client → Server:用户收到远程服务器发来的字符串,使用与远程服务器公钥配对的私钥对字符串进行加密,再发送给远程服务器。

Server → Client: 服务器使用公钥对用户发来的加密字符串进行解密,得到的解密字符串如果与第一步中发送给客户端的随机字符串一样,那么判断为登录成功。

查看本地是否有已生成的密钥对

  1. 进入用户目录下的.ssh 文件夹
cd ~/.ssh

  1. 查看是否有密码对文件

如果没有这两个文件需要自行创建⬇️:

本地客户端如何生成密钥对

使用 ssh-keygen 就可以直接生成登录需要的密钥对。ssh-keygen 是 Linux 下的命令,不添加任何参数就可以生成密钥对。

ssh-keygen -t rsa -f ~/.ssh/id_rsa.newId -C "new private key"

-t 参数是指定加密类型

-f 是指定密钥对的生成位置以及文件名的, 默认私钥是~/.ssh/id_rsa, 公钥是~/.ssh/id_rsa.pub 公钥是自动在私钥名称后添加.pub后缀形成的.

-C 是添加注释

执行该命令后会有提示:

加密:输入密码并重复即设置密码

若加密,则在调用密钥文件时需要先验证密钥的密码,密码正确才能使用密钥文件;
不加密:直接回车即可

若不加密,则密钥文件可以直接被调用,整个登陆验证过程无需输入任何密码,即为免密登录;

之后就会发现, 在你指定的路径下生成了私钥文件id_rsa.newId, 和公钥文件id_rsa.newId.pub

将本地公钥文件上传到目标服务器

我们生成了新的公钥文件id_rsa.newId.pub, 现在需要将它上传到目标服务器中.

公钥的内容要保存到要登录的用户的home目录下的 .ssh/authorized_keys 文件中。假设你用root 用户登录远程服务器,那么公钥的内容应该是保存在 /root/.ssh/authorized_keys中。注意 authorized_keys 文件是可以保存多个公钥信息的,每个公钥以换行分开。

注意你把本地公钥文件里的内容保存在哪个用户的authorized_keys的时候, 那你登陆的时候就应该使用哪个用户

本地配置config文件

很多时候, 我们本地会生成多个密钥对, 每一个密钥对对应一台远程服务器, 但是我们在使用ssh 登陆的时候, 默认是使用~/.ssh/id_rsa和~/.ssh/id_rsa.pub作为密钥对的, 因此我们需要进行配置, 告诉ssh在登陆不同服务器的时候应该使用哪个密钥对.

config文件需要创建在 ~/.ssh文件夹下, 和密钥对在一起

配置的内容如下:

Host github.com
    User hahaha
    IdentityFile ~/.ssh/id_rsa
Host 192.168.1.1
    User newId
    IdentityFile ~/.ssh/id_rsa.newId

上面 config 文件字段含义如下:

Host 指明了远程主机的 ip,除了使用 ip 地址,也可以直接使用网址。

User 指的是登录远程主机的用户。

IdentityFile 指明使用哪个私钥文件。

ssh免密直接登陆

假设我把id_rsa.newId.pub的内容是保存在192.168.1.1服务器的/root/.ssh/authorized_keys文件中.

此时登陆使用的命令:

ssh root@192.168.1.1

这个时候,如上面说的,远程服务器会发送一段随机字符串回来,这个时候需要使用私钥对字符串进行加密。而这个私钥会去执行该命令的用户的家目录下的 .ssh 目录读取私钥文件,根据config配置私钥文件为 id_rsa.newId 文件。即 $HOME/.ssh/id_rsa.newId文件。假设在生成密钥的时候对私钥进行了加密,那么这个时候就需要输入密码。

上面的流程用户登录的时候是不会感知的,ssh 在背后完成了所有的校验操作,如果密钥匹配的话,那么用户就可以直接登录到远程服务器,但是如果是首次登录的话,会出现类似下面的提示:

服务端会返回公钥的md5值, SHA256:61U/SJ4n/QdR7oKT2gaHNuGxhx98saqMfzJnzA1XFZg, 你需要手工核对这个值是否正确, 如果正确的话, 就输入yes. 此时会在~/.ssh文件夹下生成一个known_hosts文件, 里面就会包含此次登陆服务器的地址和公钥指, 下一次就不回头弹出这个验证框了.

known_hosts文件内容如下:

192.168.1.1 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPKYWolOYTDevvBR6GV0rFcI0z/DHZizN5l/ajApsgx+UcOOh51liuyBRRCIyF+BR56Le0lP0Pn6nzvLjbqMqg=

参考链接

SSH 登录流程分析

Linux系统SSH通讯过程详解