客户端(C)连接服务端(S)时,会在自己的~/.ssh/known_hosts中记录S名称的Hash(如果希望在known_hosts文件中使用原服务端名称,在/etc/ssh/ssh_config中去掉"HashKnownHosts yes",或者在~/.ssh/config中增加"HashKnownHosts no")以及一个很长的特征串,当有人伪装成S骗取密码,或者S操作系统重装之后,由于后面这个特征串发生了变化,所以ssh会发出警告,只有从~/.ssh/known_hosts中删掉要连接的S那一行才能重新连接。
使用密钥而不是密码登录S的好处是不需要每次输入密码,且能够避免“中间人攻击”,基于密钥的配置过程是:
-
C创建自己的公钥和私钥(ssh-keygen命令);
-
C将自己的公钥保存到S(ssh-copy-id命令,实际上是加自己的公钥加入了S的~/.ssh/authorized_keys文件中);
这样就配置好了,以后当客户端需要登录服务端时,连接过程是:
-
C与S首先进行Diffie–Hellman key exchange(参考http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange 其中的插图对这种算法为什么是安全的解释的很清楚:密钥的混合类似于颜色的混合,反向操作几乎是不可能的,因此将混合后的密钥在网络上传输是安全的),最终生成本次会话的密钥;
-
后续的报文基于上面生成的密钥进行对称加密传输(也就是加密和解密使用同一个密钥)。
网上有写SSH登录过程使用非对称加密传输(及公钥加密、私钥解密,见http://en.wikipedia.org/wiki/Public-key_cryptography),这是SSH v1的加密方式。
详细的连接过程参考man sshd.