SSH协议通过known host来减少受到中间人攻击(Man-in-the-Middle Attack)的可能性.我们这个案例是连接本机的ssh服务端,风险比较小.如果我们需要在一个复杂的网络环境中去连接一个远端的服务器,很可能会遭遇到中间人攻击,假如本机和远端机器间各种一个或者若干个局域网,中间可能还通过广域网,在这种情况下,黑客可以在网络中间设置一个欺诈服务器,伪装成我们要连接的远端服务器,我们就可能会连接上错误的服务器,或者所有的请求和响应都被它代理,失去SSH的加密特性.
    SSH的公钥加密过程:

    1. 远程主机收到用户的登录请求,把自己的公钥发给用户.
    2. 用户使用这个公钥,将登录密码加密后,发送回来.
    3. 远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录.
      如果我们连上黑客的伪服务器,它就可以把伪造的公钥发给我们,从而截获我们的密码.
      当我们第一次连接ssh服务端时,会将服务端上的公钥指纹打印出来,用户需要检查下这个指纹是否是正确的,如果指纹不对,需要拒绝连接.为了能够鉴别出这个指纹,ssh服务端的管理员需要事先在网页/邮件/聊天工具中将这个指纹公告出来.

    在上面的ssh连接案例中,我们可以看到ssh服务端ECDSA公钥的指纹的两种表达方式(SHA256/MD5)

    1. ECDSA key fingerprint is SHA256:xRaqsG/D2EFWfKbv6Ke8ImjHXBpo3jZ3N1Xp0NVhJLg.
    2. ECDSA key fingerprint is MD5:d1:36:75:6d:b2:da:9d:f9:5e:ea:01:3f:6e:66:aa:e2.

    这与我们安装ssh服务端时看到的日志是一致的:

    1. Your public key has been saved in /etc/ssh/ssh_host_ecdsa_key.pub.
    2. The key fingerprint is:
    3. SHA256:xRaqsG/D2EFWfKbv6Ke8ImjHXBpo3jZ3N1Xp0NVhJLg root@ssh_server

    我们也可以用如下指令查看下ssh_host_ecdsa_key.pub的指纹:

    1. [root@ssh_server .ssh]# ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub
    2. 256 SHA256:xRaqsG/D2EFWfKbv6Ke8ImjHXBpo3jZ3N1Xp0NVhJLg root@ssh_server (ECDSA)
    3. [root@ssh_server .ssh]# ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub -E md5
    4. 256 MD5:d1:36:75:6d:b2:da:9d:f9:5e:ea:01:3f:6e:66:aa:e2 root@ssh_server (ECDSA)
    5. [root@ssh_server .ssh]#

    第一次连接到ssh服务端后,客户端会把服务端的公钥记录在$HOME/.ssh/known_hosts里,这样后面再从同一个客户端(相同用户下)上连接同一ssh服务端就不会再有这个提示了,我们再从本机连接一次ssh服务端,这时没有出现服务端公钥指纹确认:

    1. [root@ssh_client .ssh]# ssh 172.17.0.2
    2. root@172.17.0.2's password:
    3. Last login: Mon Mar 19 23:48:41 2018 from localhost
    4. [root@ssh_server ~]#

    我们可以看看这个known_hosts,里面记录着主机名,公钥类型,公钥 等信息.

    1. [root@ssh_client .ssh]# pwd
    2. /root/.ssh
    3. [root@ssh_client .ssh]# cat known_hosts
    4. 127.0.0.1 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH992J2KjIMS25eYhKtfYs6WM8rqMK4K29b4AoGv3xY0pNsj1LdEB4zS6dMY2U3zYrcRKsoH19shsqrUuDEmCz4=
    5. [root@ssh_client .ssh]#

    同样我们可以查查这个文件里的公钥指纹:

    1. [root@ssh_client .ssh]# ssh-keygen -l -f ./known_hosts
    2. 256 SHA256:xRaqsG/D2EFWfKbv6Ke8ImjHXBpo3jZ3N1Xp0NVhJLg 172.17.0.2 (ECDSA)
    3. [root@ssh_client .ssh]#

    我们再试试从其他机器第一次连接这个ssh服务端(通过执行ip addr可以查看到这个机器的ip是172.17.0.2),同样会有这个指纹确认的过程:

    1. xxx@xxx-TP:~$ ssh root@172.17.0.2
    2. The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
    3. ECDSA key fingerprint is SHA256:xRaqsG/D2EFWfKbv6Ke8ImjHXBpo3jZ3N1Xp0NVhJLg.
    4. Are you sure you want to continue connecting (yes/no)? yes
    5. Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
    6. root@172.17.0.2's password:
    7. X11 forwarding request failed on channel 0
    8. Last login: Tue Mar 20 23:49:24 2018 from localhost
    9. [root@ssh_server ~]#

    我们在服务端上更新一下ecdsa的key.

    1. [root@ssh_server .ssh]# ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
    2. Generating public/private ecdsa key pair.
    3. /etc/ssh/ssh_host_ecdsa_key already exists.
    4. Overwrite (y/n)? y
    5. Enter passphrase (empty for no passphrase):
    6. Enter same passphrase again:
    7. Your identification has been saved in /etc/ssh/ssh_host_ecdsa_key.
    8. Your public key has been saved in /etc/ssh/ssh_host_ecdsa_key.pub.
    9. The key fingerprint is:
    10. SHA256:gsnACdBRyVrZsJFSVzfJHYEhgUL9gY5bmyq08fJy6Jc root@ssh_server
    11. The key's randomart image is:
    12. +---[ECDSA 256]---+
    13. |+..**B.++o+=oo |
    14. | oo.B+= .o+.. |
    15. | ++.+ . . |
    16. | .o.oo . |
    17. | +o.oS |
    18. | o . o. |
    19. | . = o |
    20. | * E |
    21. | ..B. |
    22. +----[SHA256]-----+
    23. [root@ssh_server .ssh]#

    再次尝试登录:

    1. [root@ssh_client .ssh]# ssh root@172.17.0.2
    2. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    3. @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
    4. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    5. IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    6. Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    7. It is also possible that a host key has just been changed.
    8. The fingerprint for the ECDSA key sent by the remote host is
    9. SHA256:gsnACdBRyVrZsJFSVzfJHYEhgUL9gY5bmyq08fJy6Jc.
    10. Please contact your system administrator.
    11. Add correct host key in /root/.ssh/known_hosts to get rid of this message.
    12. Offending ECDSA key in /root/.ssh/known_hosts:1
    13. ECDSA host key for 172.17.0.2 has changed and you have requested strict checking.
    14. Host key verification failed.
    15. [root@ssh_client .ssh]#

    这就是典型的服务端返回的host key和本地存储的不一致告警.我们这个例子中是强制更新了ssh服务端密钥对,在实际使用中,经常会出现的是:ssh服务端机器被重装了;ssh服务端的ip地址被其它机器占用了,导致连错机器等,也有可能是发生了中间人攻击,网络上有人伪装了个ssh服务端机器.
    如果我们能确认host key是正常发生变动的,可以将本地存储的host key删除,重认新的host key.从前面的例子中,我们已经知道,客户端上的host key是存储在$HOME/.ssh/known_hosts里的.如果里面只有一条记录,我们可以清空这个文件,如果里面有多条记录,我们可以打开这个,定位到对应的记录,删除.

    1. [root@ssh_client .ssh]# ls -tlr
    2. total 4
    3. -rw-r--r-- 1 root root 171 Mar 19 23:48 known_hosts
    4. [root@ssh_client .ssh]# cat known_hosts
    5. 172.17.0.2 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH992J2KjIMS25eYhKtfYs6WM8rqMK4K29b4AoGv3xY0pNsj1LdEB4zS6dMY2U3zYrcRKsoH19shsqrUuDEmCz4=
    6. [root@ssh_client .ssh]#

    我们这里只有一个文件,我们可以尝试把文件清空,为了方便后续测试,我们先把文件备份一下:

    1. [root@ssh_client .ssh]# cp known_hosts mykh.bak
    2. [root@ssh_client .ssh]# >known_hosts
    3. [root@ssh_client .ssh]# cat known_hosts
    4. [root@ssh_client .ssh]#

    文件清空之后,再尝试登录:

    1. [root@ssh_client .ssh]# ssh root@172.17.0.2
    2. The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
    3. ECDSA key fingerprint is SHA256:gsnACdBRyVrZsJFSVzfJHYEhgUL9gY5bmyq08fJy6Jc.
    4. ECDSA key fingerprint is MD5:38:6b:a9:be:47:08:08:b8:51:fe:f5:e1:c0:01:d4:ef.
    5. Are you sure you want to continue connecting (yes/no)? yes
    6. Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
    7. root@172.17.0.2's password:
    8. Last login: Sat Apr 7 01:11:33 2018 from localhost
    9. [root@ssh_server ~]#

    可以实现重新确认key,并正常登录.
    如果known_hosts里有多于一条的记录,我们就不能简单清空文件,否则其他主机的host key信息也会被删除,需要找到我们要删除的记录,手工删除它:

    1. [root@ssh_client .ssh]# cat known_hosts
    2. 172.17.0.2 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH992J2KjIMS25eYhKtfYs6WM8rqMK4K29b4AoGv3xY0pNsj1LdEB4zS6dMY2U3zYrcRKsoH19shsqrUuDEmCz4=
    3. 172.17.0.1 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOD62GxuUdjHtnIgOVXQaagVlCQ21IiGtQBNVPWNszmO8oKT5EOzuZdYybTPnOS2oR/MzJ65iX4KqSeGpC7rJuQ=
    4. [root@ssh_client .ssh]#

    我们这里有两条记录,可以通过vi进去,删除172.17.0.2的那条记录,实现重认host key:

    1. [root@ssh_client .ssh]# cp known_hosts mykh.bak
    2. cp: overwrite 'mykh.bak'? y
    3. [root@ssh_client .ssh]# ssh root@172.17.0.2
    4. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    5. @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
    6. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    7. IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    8. Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    9. It is also possible that a host key has just been changed.
    10. The fingerprint for the ECDSA key sent by the remote host is
    11. SHA256:gsnACdBRyVrZsJFSVzfJHYEhgUL9gY5bmyq08fJy6Jc.
    12. Please contact your system administrator.
    13. Add correct host key in /root/.ssh/known_hosts to get rid of this message.
    14. Offending ECDSA key in /root/.ssh/known_hosts:1
    15. ECDSA host key for 172.17.0.2 has changed and you have requested strict checking.
    16. Host key verification failed.
    17. [root@ssh_client .ssh]# vi known_hosts
    18. [root@ssh_client .ssh]# cat known_hosts
    19. 172.17.0.1 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOD62GxuUdjHtnIgOVXQaagVlCQ21IiGtQBNVPWNszmO8oKT5EOzuZdYybTPnOS2oR/MzJ65iX4KqSeGpC7rJuQ=
    20. [root@ssh_client .ssh]# ssh root@172.17.0.2
    21. The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
    22. ECDSA key fingerprint is SHA256:gsnACdBRyVrZsJFSVzfJHYEhgUL9gY5bmyq08fJy6Jc.
    23. ECDSA key fingerprint is MD5:38:6b:a9:be:47:08:08:b8:51:fe:f5:e1:c0:01:d4:ef.
    24. Are you sure you want to continue connecting (yes/no)? yes
    25. Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
    26. root@172.17.0.2's password:

    OpenSSH有个HashKnownHosts选项,如果开启了这个选项,known_hosts里存储的就是hash后的结果:

    1. xxx@xxx-TP:~/.ssh$ grep HashKnownHosts /etc/ssh/ssh_config
    2. HashKnownHosts yes
    3. xxx@xxx-TP:~/.ssh$ more known_hosts
    4. |1|Y7vypCJauRdlINk5AYLBRjzMHZc=|+Z6FhMBXHvSNdwxWbRTnZnRhuSM= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAjejdMKtKTwP
    5. WgoxubOie71Q8iePHJ2BDCGad37jBpU1J/0kIpnwSwK5M7TAGupXltpfvvUI7Nf1CvM/8hsFCY=
    6. |1|HuXbxymRZ0uAXm1epm+8XY3K8/0=|p2ei6uHnnd2F8X6MQ3PAs3BYw3I= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKZLbMSYFabjt
    7. fUcb7t/5yD43U8lPlSeuqjI96+EKDVyZxauXCuMcVWfnByQ5ssKi28BPwDRxqZPrOUAtn5d/xU=
    8. |1|Zx92xoC3AFjKY/dUro9htuLiles=|2DbvgHAZvqr30WMNyLjw0hAb3og= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA/xwD0eRiU/M
    9. s5lcduwx5N5V3GvO/1NRlmxnCy0bIx2rGjFPdcvjeeowY6gBeG1WSXuIZ8vci12bpfS3Qmf+qs=

    对于这种情况,靠肉眼是没法识别出哪条记录是我们需要删除的,我们需要用ssh-keygen指令来找出需要删除的host key:

    1. xxx@xxx-TP:~/.ssh$ ssh-keygen -F 172.17.0.2
    2. # Host 172.17.0.2 found: line 61
    3. |1|32Y9sbXMbVva7F+CNaDLI+Nih2c=|BgmXf2XFHv3dwRhzIqFXbVT5D+w= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH992J2KjIMS25eYhKtfYs6WM8rqMK4K29b4AoGv3xY0pNsj1LdEB4zS6dMY2U3zYrcRKsoH19shsqrUuDEmCz4=

    从上面的结果可以看出,我们可以vi known_host文件,输入冒号:61,定位到61行,按dd删除这行.事实上ssh-keygen还有一个参数,可以直接把某个ssh服务端对应域名的host key删除,我们执行ssh指令可以看到这个提示(部分版本OpenSSH的客户端有这个提示,不管有没有这个提示,这个指令都是能执行):

    1. xxx@xxx-TP:~/.ssh$ ssh root@172.17.0.2
    2. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    3. @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
    4. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    5. IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    6. Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    7. It is also possible that a host key has just been changed.
    8. The fingerprint for the ECDSA key sent by the remote host is
    9. SHA256:gsnACdBRyVrZsJFSVzfJHYEhgUL9gY5bmyq08fJy6Jc.
    10. Please contact your system administrator.
    11. Add correct host key in /home/xxx/.ssh/known_hosts to get rid of this message.
    12. Offending ECDSA key in /home/xxx/.ssh/known_hosts:61
    13. remove with:
    14. ssh-keygen -f "/home/xxx/.ssh/known_hosts" -R 172.17.0.2
    15. ECDSA host key for 172.17.0.2 has changed and you have requested strict checking.
    16. Host key verification failed.

    这个指令就是 ssh-keygen -f "/home/xxx/.ssh/known_hosts" -R 172.17.0.2,
    我们可以执行这个指令,再尝试登录:

    1. xxx@xxx-TP:~/.ssh$ ssh-keygen -f "/home/xxx/.ssh/known_hosts" -R 172.17.0.2
    2. # Host 172.17.0.2 found: line 61
    3. /home/xxx/.ssh/known_hosts updated.
    4. Original contents retained as /home/xxx/.ssh/known_hosts.old
    5. xxx@xxx-TP:~/.ssh$ ssh root@172.17.0.2
    6. The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
    7. ECDSA key fingerprint is SHA256:gsnACdBRyVrZsJFSVzfJHYEhgUL9gY5bmyq08fJy6Jc.
    8. Are you sure you want to continue connecting (yes/no)? yes
    9. Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
    10. root@172.17.0.2's password:
    11. X11 forwarding request failed on channel 0
    12. Last login: Sat Apr 7 08:51:46 2018 from localhost
    13. [root@ssh_server ~]#

    执行ssh-keygen -f后,可以重认host key.