为什么SSH口令登录不太安全

3,597 阅读2分钟

SSH相信大家都不陌生,常用的远程登录有两种方式:

  1. 口令登录(每次登录输入用户名密码)
  2. 公钥登录

第一种方式登录只需要知道账号密码,相对第二种方式要更方便,然而第一种方式相对不那么安全。具体原因我们从它们的原理入手。

口令登录

口令登录命令

$ ssh <user>@<host>

原理如下:

  • 客户端向服务端发起请求
  • 服务收到请求将自己生成的公钥返回给客户端
  • 客户端用返回来的公钥加密自己的登录密码,发送给服务端
  • 服务端用自己的私钥解密,并验证密码是否正确,如果正确,允许登录

整个验证机制是没什么问题的,但是当遇到 中间人攻击 这种机制的安全性便会遭到破坏,什么是 中间人攻击

  • 客户端向服务端发起请求
  • 攻击人截获请求,并向客户端返回自己的公钥
  • 客户端用公钥加密登录密码并返回
  • 攻击人用自己的私钥解密,获得服务器的登录密码

中间人攻击使你每次登录都带有潜在风险,中间人在和你同一个网络环境,比如公共wifi环境,就能轻易截获和伪装成服务器窃取你的密码。那么有什么应对方式呢?

$ ssh <user>@<host>
The authenticity of host 'hostname (<ip>)' can't be established.
RSA key fingerprint is 97:8c:1c:f2:6f:15:6b:5c:3a:ec:aa:48:46:79:7c:20.
Are you sure you want to continue connecting (yes/no)?

当首次登录一台远程主机的时候,会出现以上提示,大致意思是无法确认远程主机是否真实,这是主机的公钥指纹97:8c:1c:f2:6f:15:6b:5c:3a:ec:aa:48:46:79:7c:20,询问是否继续,如果接受这个风险,便可继续连接并会保存这个公钥到know_hosts文件中,如果下次再连接,会自动对比公钥。如果下次连接公钥变化了,会发出一下告警并拒绝连接

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED 

通过以上机制,我们只需要确保第一次登录时候,远程的登录的主机是真实的,除非远程主机重装了,或手动修改了,通常情况公钥不会修改。唔...那么问题又来了,我们怎么知道真实远程主机的公钥指纹是什么?目前来说没什么好办法,只能依靠远程主机提供商把公钥指纹贴出来。

公钥登录

公钥登录命令

$ ssh  -i PrivateKey.pem <user>@<host>

原理如下:

  • 客户端自己生成密钥对,事先将公钥上传存储到远程服务器上,私钥自己保管
  • 客户端发起登录请求
  • 服务器发一串随机字符串给客户端
  • 客户端用自己的私钥加密随机字符串,返回给服务端
  • 服务端用事先存储好的公钥解密,确认字符串是原来发出的字符串,便允许登录

公钥登录的前提是事先将自己生成的公钥存储到远程的服务器,通常有两种方式

  • 如果你的远程服务器是云提供商上的,一般都会提供密钥对管理的功能,有些甚至可以自动创建密钥对,并提供私钥的下载(比如AWS),没有的话也没关系,通过以下命令生成密钥对,并将公钥(id_rsa.pub)上传到云上即可。
    $ ssh-keygen -t rsa -b 4096  #一路回车即可,密钥默认保存在 ~/.ssh/id_rsa 和 ~/.ssh/id_rsa.pub
    
  • 如果远程服务器提供商没有密钥对管理的功能,那只能手动操作上传了
    • 生成密钥对并上传公钥

    以下操作需要能够密码登录远程主机

    $ ssh-keygen -t rsa -b 4096  #在~/.ssh/目录下生成两个文件,其中id_rsa是私钥,id_rsa.pub是公钥,分别保存以备用
    $ ssh-copy-id  <user>@<host>  #需要输入登录密码,成功后可以在服务器 ~/.ssh/authorized_keys文件中看到添加的公钥
    
    • 确保客户端和服务器上的 .ssh 的权限是700,authorized_keys的权限是600
      $ chmod 700 ~/.ssh
      $ chmod 600 ~/.ssh/authorized_keys 
      
    • 确保服务器上/etc/ssh/sshd_config 中以下是没有注释的
      RSAAuthentication yes
      PubkeyAuthentication yes
      AuthorizedKeysFile .ssh/authorized_keys
      
    • (可选)把密码登录关闭,在服务器上/etc/ssh/sshd_config设置
      PasswordAuthentication no
      
    • 重启服务器上的sshd
      $ systemctl restart  sshd