SSH概要
Secure Shell,安全外壳协议,简称ssh,是一种建立在应用层基础上的安全协议,通过对密码进行加密传输验证,可在不安全的网络中对网络服务提供安全的传输环境,实现ssh客户端和ssh服务器端的连接
(1).SSH是传输层和应用层上的安全协议,它只能通过加密连接双方会话的方式来保证连接的安全性。当使用ssh连接成功后,将建立客户端和服务端之间的会话,该会话是被加密的,之后客户端和服务端的通信都将通过会话传输。
(2).SSH服务的守护进程为sshd,默认监听在22端口上。
(3).所有ssh客户端工具,包括ssh命令,scp,sftp,ssh-copy-id等命令都是借助于ssh连接来完成任务的。也就是说它们都连接服务端的22端口,只不过连接上之后将待执行的相关命令转换传送到远程主机上,由远程主机执行。
(4).ssh客户端命令(ssh、scp、sftp等)读取两个配置文件:全局配置文件/etc/ssh/ssh_config和用户配置文件~/.ssh/config。实际上命令行上也可以传递配置选项。它们生效的优先级是:命令行配置选项 > ~/.ssh/config > /etc/ssh/ssh_config。
(5).ssh涉及到两个验证:主机验证和用户身份验证。通过主机验证,再通过该主机上的用户验证,就能唯一确定该用户的身份。一个主机上可以有很多用户,所以每台主机的验证只需一次,但主机上每个用户都需要单独进行用户验证。
(6).ssh支持多种身份验证,最常用的是密码验证机制和公钥认证机制,其中公钥认证机制在某些场景实现双机互信时几乎是必须的。虽然常用上述两种认证机制,但认证时的顺序默认是gssapi-with-mic,hostbased,publickey,keyboard-interactive,password。注意其中的主机认证机制hostbased不是主机验证,由于主机认证用的非常少(它所读取的认证文件为/etc/hosts.equiv或/etc/shosts.equiv),所以网络上比较少见到它的相关介绍。总的来说,通过在ssh配置文件(注意不是sshd配置文件)中使用指令PreferredAuthentications改变认证顺序不失为一种验证的效率提升方式。
(7).ssh客户端其实有不少很强大的功能,如端口转发(隧道模式)、代理认证、连接共享(连接复用)等。
(8).ssh服务端配置文件为/etc/ssh/sshd_config,注意和客户端的全局配置文件/etc/ssh/ssh_config区分开来。
(9).很重要却几乎被人忽略的一点,ssh登录时会请求分配一个伪终端。但有些身份认证程序如sudo可以禁止这种类型的终端分配,导致ssh连接失败。例如使用ssh执行sudo命令时sudo就会验证是否要分配终端给ssh
SSH认证过程分析
假如从客户端A连接到服务端B上,将包括主机验证和用户身份验证两个过程,以RSA非对称加密算法为例。
主机验证过程(发生在客户端)
当客户端A要连接服务端B时,首先将进行主机验证过程,即客户端A判断是否曾经连接过主机B。
客户端A执行ssh命令连接时, 会接收到服务端B的ssh公钥, 也可以称作B机器的主机信息(即host key,表示主机身份标识)
服务端B的公钥信息保存在/etc/ssh/ssh_host*文件中, 其中的*表示不同的加密算法, ssh服务启动时会选择一种算法的.pub文件作为公钥
在本例中选择的是ECDSA算法, ssh_host_ecdsa_key.pub文件内容为:
ecdsa-sha2-nistp256 AAAAE...vC2PDRA08c7c= root@iZuf60sq23qlao62jmsy0zZ
通过空格分隔为三个部分:
第一部分表示服务端B的公钥加密算法
第二部分表示服务端B的公钥值
第三部分表示服务端B的公钥生成时的用户信息
第一次建立连接
若客户端A从未连接过服务端B(即第一次建立连接), 则会询问是否进行连接
图中展示了两个信息:
服务端B的公钥是通过ECDSA算法进行加密的
由于公钥长度太长, 这里对公钥再次进行了加密, 得出公钥的指纹, 即SHA256后面的44位字符串
输入yes则会继续连接, 并将B的公钥信息保存至客户端A的~/.ssh/known_hosts文件中, 如:
|1|xNN...6aRA= ecdsa-sha2-nistp256 AAAAE...vC2PDRA08c7c=
每行数据表示一个主机信息, 通过空格分隔为三个部分:
第一部分表示服务端B的ip相关信息
第二部分表示服务端B的公钥加密算法
第三部分表示服务端B的公钥值
其中第2、3两个部分的值和服务端B的公钥文件``ssh_host_ecdsa_key.pub`中的值相同。
后续连接
后面再进行连接时, 则会将服务端B发送过来的公钥信息(host key)和~/.ssh/known_hosts文件中保存的host key进行比较.
若两者相同, 则验证通过, 进行下一个过程--身份验证
若不相同, 则提示主机认证失败, 如:
上述报错意思为本次接收的指纹wtCqN4lUaPNJb1TNuLawnI1JegJ3xGrda5yij+bo0g8和~/.ssh/known_hosts文件中保存的host key指纹不一致, 可以使用ssh-keygen -f "/home/alex/.ssh/known_hosts" -R "[127.0.0.1]:2222"命令删除原文件中保存的host key信息. 删除后再连接, 则又会回到第一次建立连接时的流程
host key指纹
ssh并非直接比对host key,因为host key太长了,比对效率较低。所以ssh将host key转换成host key指纹,然后比对两边的host key指纹即可。host key的指纹可由ssh-kegen命令计算得出。
计算服务端B的host key指纹
(base) alex@Aliyun-ALex:~$ sudo ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key
256 SHA256:N2QawIygnLo3m34fDevSECWNK1S7Ow+54wXnHQwMwko root@iZuf60sq23qlao62jmsy0zZ (ECDSA)
计算客户端A中known_hosts文件保存的B的host key指纹, 两者相同
alex@LPT006526:~$ ssh-keygen -l -f ~/.ssh/known_hosts
256 SHA256:N2QawIygnLo3m34fDevSECWNK1S7Ow+54wXnHQwMwko |1|xNNGD5QK4PWE8ecSJ1aWhdu6gVw=|T13/F6JZiCNy7L7eQVuIAib6aRA= (ECDSA)
身份验证过程
主机验证通过后,将进入身份验证阶段。SSH支持多种身份验证机制,它们的验证顺序如下:gssapi-with-mic,hostbased,publickey,keyboard-interactive,password,但常见的是密码认证机制(password)和公钥认证机制(public key)。当公钥认证机制未通过时,再进行密码认证机制的验证。
在进行上一步的主机验证时, 客户端A已经得到了服务端B的公钥
密码认证
密码认证过程
客户端A将用户输入的密码使用服务端B的公钥进行加密, 将加密结果发送给服务端B
服务端B使用自己的私钥对加密结果进行解密, 得到密码, 与本地密码文件进行比较, 若相同则认证成功, 否则失败
公钥认证
公钥认证前提
公钥认证可以不用输入密码, 但有两个前提:
客户端A也生成一套非对称秘钥, 可以使用ssh-keygen命令生成, 默认情况下会在~/.ssh/目录下生成id_rsa(私钥)和id_rsa.pub(公钥)文件
alex@LPT006526:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/alex/.ssh/id_rsa): # 直接回车,使用默认值
Enter passphrase (empty for no passphrase): # 直接回车,不设置密码
Enter same passphrase again: # 直接回车,不设置密码
Your identification has been saved in /home/alex/.ssh/id_rsa. # 私钥
Your public key has been saved in /home/alex/.ssh/id_rsa.pub. # 公钥
The key fingerprint is:
SHA256:zQtCAGgFVR0Ia89w9D0i0VJMZeAu94XEdbjYTlpuWrM alex@LPT006526 # 公钥指纹
The key's randomart image is: # 公钥图片码
+---[RSA 2048]----+
| o==++B=+o ... |
|.. o++++ ... |
|. + oo+ =o . |
| . =.o o+o= |
| +.oS.O. |
| o..o.B |
| .= o |
| . E |
| |
+----[SHA256]-----+
将客户端A的公钥放在服务端B的~/.ssh/authorized_keys文件中, 可以在客户端A中使用命令ssh-copy-id进行设置, 也可以手动将客户端A的公钥文件~/.ssh/id_rsa.pub中的值追加到服务端B的~/.ssh/authorized_keys文件中
alex@LPT006526:~$ ssh-copy-id alex@47.102.114.90
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/alex/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
alex@47.102.114.90's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'alex@47.102.114.90'"
and check to make sure that only the key(s) you wanted were added.
以上两个前提设置完成后, 在客户端A中直接输入ssh连接命令即可连接至服务端B中, 不需要输入密码
公钥认证的过程
客户端A发送A的公钥给服务端B
服务端B接收到A的公钥后, 去~/.ssh/authorized_keys文件中查找是否存在A的公钥, 若存在, 则用此公钥加密一个随机字符串, 并返回给客户端A
客户端A收到后使用自己的私钥进行解密, 并将解密结果发送给服务端B
服务端B收到A的解密结果后与之前的随机字符串进行比较, 若相同, 则认证成功. 否则认证失败
MFA
多重要素验证(英语:Multi-factor authentication,缩写为 MFA),又译多因子认证、多因素验证、多因素认证,是一种计算机访问控制的方法,用户要通过两种以上的认证机制之后,才能得到授权,使用计算机资源。
相比仅凭账号密码,MFA提供了更加安全的资源保护。下面列举一些MFA的例子:
用户安全问题
密码
OTPs
软件安全码、keys
指纹、人脸识别、声纹及其他生物特征
用户行为足迹分析
OTP
OTP(One-Time-Password)是MFA(Multi-Factor-Authentication)的一个实现模型. 顾名思义,一次性密码。如短信验证码, 谷歌认证等
HOTP
HOTP中,H指代 Hash-based Message Authentication Code,另一种不那么专业的解释方法为:HOTP是一种事件驱动的OTP,它的moving factor基于一个计数器。
HOTP每一次请求,都会让计数器递增,而生成的OTP在下一次计数前保持有效。OTP生成器和服务器会同步监测到用户的有效访问行为。HOTP的一个例子为Yubikey。
TOTP
TOTP中,T指代Time-based,类似HOTP,但是它的moving factor基于时间。
TOTP的有效时间被称为timestep(时间步长),通常被设定为30、60秒,如果在这个时间窗口内没有验证此密码,则会失效。