1
gamexg 2015-10-16 15:17:56 +08:00 via Android
如果之前连接过第 3 步就会报服务器公钥错误。
|
5
gamexg 2015-10-16 16:14:57 +08:00
ssh 客户端会保存服务器的 ssh 公钥,下次连接时公钥出现了变化会提示的。
ssh 服务器的公钥是公开的,可以获得,但是服务器私钥是保密的。虽然没看过 ssh 的代码,但是客户端既然保存 ssh 服务器的公钥,那么建立连接时绝对会使用服务器的公钥加密握手数据,你没有服务器的私钥,无法解密握手数据,那么 ssh 连接就建立不起来... 查了一下资料,发现 ssh 设计时的安全性很好。即使客户端忽略了服务器公钥变化也无法做到透明的中间人攻击。证书登录时服务器会将一个随机数通过客户公钥加密后发送过来,客户端使用客户私钥解密,解密后不是直接发送到服务器认证身份,而是和 session id 做 MD5 后再发送到服务器认证身份。 session id 的产生依赖于服务器公钥,中间人的公钥和服务器的公钥是不相同的,造成客户端生成的认证数据中间人拿着也无法登陆真实的服务器认证。 可惜现在 md5 并不是很安全了,之前 md5 已经可以做到碰撞出相同的 md5 指纹了,破译出原文的难度就不清楚了。 参考资料: http://erik-2-blog.logdown.com/posts/74081-ssh-principle |
6
zk8802 2015-10-16 16:21:22 +08:00 2
SSH 服务端通过 host key 来避免中间人攻击,包括公钥和私钥两部分。你不可能伪造一份同样的 host key —— 你可以得到远程服务器的公钥,但没有私钥的话,你无法和一个正常的 SSH 客户端完成密钥协商过程(因为你没法解密使用正常公钥加密的数据)。
密钥协商过程大致如下: SSH 开始时,服务器传到客户端的数据中包括服务器的公钥。客户端使用服务器的公钥对发出的数据进行加密,并期待服务器端的 sshd 有对应的私钥,能够解密并理解发出的数据内容。你伪造的中间人得不到对应的私钥,没法知道客户端发回的信息是什么,也就没办法继续协商过程了。 另外再提一句,客户端发回的信息中一定会有随机数,这就要求服务器必须用私钥成功解密客户端的信息之后才能继续协商,从而避免了重放攻击。 参考资料: https://www.vandyke.com/solutions/host_keys/host_keys.pdf |
7
zk8802 2015-10-16 16:23:12 +08:00
如果你是 Linux 用户,可以在 /etc/ssh/ 目录下看到你主机的 host key(s)。
|
8
honeycomb 2015-10-16 16:24:05 +08:00
|