5. PKI - SSH建立安全信道的过程
- 1. Client: Protocol
- 2. Server: Protocol
- 3. Client: Key Exchange Init
- 4. Server: Key Exchange Init
- 5. Client: Diffie-Hellman Group Exchange Request
- 6. Server: Diffie-Hellman Group Exchange Group
- 7. Client: Diffie-Hellman Group Exchange Init
- 8. Server: Diffie-Hellman Group Exchange Reply, New Keys
- 9. Client: New Keys
- 10. Client: Encrypted packet
- 参考
要先通过SSH进行远程登录,第一步就是要建立安全信道,安全信道建立之后再进行认证,以不保证认证数据能够加密传输。本文将通过Wireshark对SSH协议进行抓包,并对每一步进行详细解释。
1. Client: Protocol
客户端将SSH协议版本发送给服务器:Protocol(SSH-2.0-OpenSSH_7.8)
2. Server: Protocol
服务器发送SSH版本:Protocol(SSH-2.0-QIZHI-3.3)
3. Client: Key Exchange Init
客户端发送自己的密钥交换算法
、加密算法
以及MAC(message authentication code)算法
给服务器。其中各算法按优先级从高到低排列,各算法之间以逗号间隔。
4. Server: Key Exchange Init
同样服务器发送自己的密钥交换算法
、加密算法
以及MAC(message authentication code)算法
给客户端。
客户端和服务器端各自按算法协商规则获取各功能(密钥交换、加密、MAC)对应的算法。
算法协商规则:在客户端支持的算法列表中,第一个被服务器支持的算法确定为双方协商的算法。
按照此规则确定密钥交换算法为 diffie-hellman-group-exchange-sha256
,加密算法为 aes128-ctr
, MAC算法为 umac-64@openssh.com
。
5. Client: Diffie-Hellman Group Exchange Request
接下来会按 diffie-hellman-group-exchange-sha256 算法进行密钥交换。
The server keeps a list of safe primes and corresponding generators
that it can select from. A prime p is safe if p = 2q + 1 and q is
prime. New primes can be generated in the background.The generator g should be chosen such that the order of the generated
subgroup does not factor into small primes; that is, with p = 2q + 1,
the order has to be either q or p - 1. If the order is p - 1, then
the exponents generate all possible public values, evenly distributed
throughout the range of the modulus p, without cycling through a
smaller subset. Such a generator is called a “primitive root” (which
is trivial to find when p is “safe”).The client requests a modulus from the server indicating the preferred
size. In the following description ( C is the client, S is the
server, the modulus p is a large safe prime, and g is a generator
for a subgroup of GF§, min is the minimal size of p in bits that
is acceptable to the client, n is the size of the modulus p in bits
that the client would like to receive from the server, max is the
maximal size of p in bits that the client can accept, V_S is S’s
version string, V_C is C’s version string, K_S is S’s public host
key, I_C is C’s KEXINIT message, and I_S is S’s KEXINIT message
that has been exchanged before this part begins )
服务器端保有一个安全素数及其生成员的清单,如果素数p满足 p=2q+1(q是素数),那么素数p是安全的。新的素数在后台自动生成。
生成元g的选择应确保生成子群的阶不会产生小的素数;也就是说,利用公式p=2q+1,子群的阶必须是q或p-1。如果阶是 p-1,则
指数产生所有可能的公共值,并平均分配在模除p的整个范围内,而不通过较小子集的循环。这样的生成元被叫做“源根”(当p为“安全”时很难找到)。 此处涉及到的数学概念,理解不是很深刻!欢迎数学大神们指正!
客户端从服务器请求一个指定大小的模除。其过程描述如下:
C:客户端
S:服务器
p:安全大素数
g:p对应的生成元
min:客户端可接收的素数p的最小比特数
n: 客户端从服务器接收的素数p的比特数
max:客户端可接收的素数p的最大比特数
V_S:服务器的版本
V_C:客户端的版本
K_S:服务器的主机公钥
I_C:客户端KEXINIT消息
I_S:该阶段开始前交换的服务器端KEXINIT消息
C sends “min || n || max” to S, indicating the minimal acceptable
group size, the preferred size of the group, and the maximal group
size in bits the client will accept.
客户端发送D-H Group Exchange Request,请求信息包括客户端可接收群的最小值、理想值和最大值,以比特为单位。
6. Server: Diffie-Hellman Group Exchange Group
S finds a group that best matches the client’s request, and sends “p
|| g” to C.
服务器发现与客户端请求最佳匹配的群,将p || g 发送给客户端,其中p是一个大而安全的素数,g是该素数的生成元。
7. Client: Diffie-Hellman Group Exchange Init
C generates a random number x, where 1 < x < (p-1)/2. It computes e =
g^x mod p, and sends “e” to S.
客户端产生随机数 x,1 < x < (p-1)/2。计算 e = g^x mod p,发送 e 到服务器。
8. Server: Diffie-Hellman Group Exchange Reply, New Keys
S generates a random number y, where 0 < y < (p-1)/2, and computes f =
g^ y mod p. S receives “e”. It computes K = e^y mod p, H = hash(V_C
|| V_S || I_C || I_S || K_S || min || n || max || p || g || e || f ||
K) (these elements are encoded according to their types; see below),
and signature s on H with its private host key. S sends “K_S || f ||
s” to C. The signing operation may involve a second hashing
operation.
服务器产生随机数y,0 < y < (p-1)/2,且计算 f = g^ y mod p,
服务器接收客户端发送的 e。
计算 K = e^y mod p,
计算哈希值 H = hash(V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K) ,
使用主机私钥对哈希值H进行签名s。
服务器发送 K_S || f || s 给客户端。 K_S: 服务器的主机公钥。
9. Client: New Keys
C verifies that K_S really is the host key for S (e.g., using
certificates or a local database to obtain the public key). C is also
allowed to accept the key without verification; however, doing so will
render the protocol insecure against active attacks (but may be
desirable for practical reasons in the short term in many
environments). C then computes K = f^x mod p, H = hash(V_C || V_S ||
I_C || I_S || K_S || min || n || max || p || g || e || f || K), and
verifies the signature s on H.
客户端验证服务器公钥的真实性(如,通过证书或本地数据库获取公钥)。
客户端同样允许不验证就接收公钥;但是这样做会使协议对主动攻击不安全。
客户端计算 K = f^x mod p,
H = hash(V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K),
并且验证基于哈希值H的签名s。
至此,完成了密钥交换,以后的数据传输都会使用基于密钥 K 的 aes128-ctr 算法进行加解密操作。并基于umac-64@openssh.com算法计算MAC值。
9.1 命令行交互
在命令行输入远程登录命令;
$ ssh user@host
当协议执行到这个阶段时,客户端才会收到服务器公钥的确认提示:
The authenticity of host 'host (12.18.429.21)' can't be established.
RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
Are you sure you want to continue connecting (yes/no)?
这段话的意思是,无法确认host主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?
所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,所以对其进行MD5计算,将它变成一个128位的指纹。上例中是 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d
,再进行比较,就容易多了。
很自然的一个问题就是,用户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在自己的网站上贴出公钥指纹,以便用户自行核对。
假定经过风险衡量以后,用户决定接受这个远程主机的公钥。
当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分。
每个SSH用户都有自己的known_hosts文件,此外系统也有一个这样的文件,通常是/etc/ssh/ssh_known_hosts,保存一些对所有用户都可信赖的远程主机的公钥。
9.2 中间人攻击
在对服务器公钥指纹的确认环节,如果我们没有核对公钥指纹的正确性,那么可能就存在一个风险:
如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户就接受了伪造的公钥。
如果攻击者插在用户与远程主机之间(比如在公共的wifi区域),用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)
10. Client: Encrypted packet
加密传输。
参考
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol
The Secure Shell (SSH) Transport Layer Protocol
The Secure Shell (SSH) Authentication Protocol
SSH原理与运用(一):远程登录
SSH原理与运用(二):远程操作与端口转发
理解SSH的加密与连接过程
Understanding the SSH Encryption and Connection Process