ssh 免密登录踩坑及解决


最近发现 ssh 直接可以免密登录远程服务器,感觉挺有趣的,于是想试试顺便了解下原理。首先便是百度下 ssh 的概念及登录方式及原理,接着就是自己实践了,一开始老是有问题,后面思考可能的原因再尝试便慢慢解决了,结果还是不错的。

简单说下 ssh 的概念吧。主要了解以下几点就差不多了。

  1. 概念:ssh 全称是 Secure Sshell,即安全外壳协议,由 IETF 的网络小组(Network Working Group)所制定。
  2. 作用:为建立在应用层基础上的安全协议。SSH 是较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。ftp、pop和telnet在本质上都是不安全的,因为它们在网络上用明文传送口令和数据,别有用心的人非常容易就可以截获这些口令和数据。而且,这些服务程序的安全验证方式也是有其弱点的, 就是很容易受到“中间人”(man-in-the-middle)这种方式的攻击。通过使用SSH,你可以把所有传输的数据进行加密,这样"中间人"这种攻击方式就不可能实现了,而且也能够防止DNS欺骗和IP欺骗。使用SSH,还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。SSH有很多功能,它既可以代替Telnet,又可以为FTP、PoP、甚至为PPP提供一个安全的"通道"。
  3. 适应平台:几乎所有UNIX平台—包括 HP-UX、Linux、AIX、Solaris、Digital UNIX、Irix,以及其他平台,都可运行SSH。
    1. 从客户端来看,SSH 提供两种级别的登录安全验证。
      1.基于口令的安全验证,意思就是通过账号和密码进行登录到远程主机。所有传输的数据都会被加密,但是不能保证你正在连接的服务器就是你想连接的服务器。可能会有别的服务器在冒充真正的服务器,也就是受到“中间人”这种方式的攻击。
      2.基于密匙的安全验证,需要在发起连接的机器(客户机)建立密钥对,即公钥以及匹配的密钥,将公钥放置到要连接的目标服务器的用户的家目录下的 .ssh 目录下,连接时向服务器发出请求,请求用你的密匙进行安全验证。服务器收到请求,先在该服务器上你要连接的用户的主目录下寻找对应的公用密匙,然后把它和你发送过来的公用密匙进行比较。如果两个密匙一致,服务器就用公用密匙加密“质询”(challenge)并把它发送给客户端软件。客户端软件收到“质询”之后就可以用你的私钥解密再把它发送给服务器。不需要在网络传输密码(口令),不仅加密所有传送的数据,而且“中间人”这种攻击方式也是不可能的(因为他没有你的私人密匙)。
      实践开始:我是在 win10 下测试的,使用了 win10 子系统 ubuntu 作为其中的客户端机器,再开启虚拟机(centos 系统)作为服务器。
      默认 ubuntu 和 centos 都安装了 ssh 服务,没有的话可以自行百度命令安装。先查看 centos 下 sshd 服务是否开启,未开启的话就开启。

      1
      2
      3
      4
      5
      6
      #查看 ssh 默认运行端口是否有 sshd 服务进程
      netstat -anp|grep 22
      #也可以直接查看 sshd 服务运行状态
      ps -ef|grep sshd
      #开启或重启 sshd 服务
      service sshd start(restart)

      linux 系统 bash 查看 ip 命令:ifconfig 获取机器 ip 后,就可以直接在客户机,直接 bash 敲命令:ssh [email protected] 再回车,此时会提示输入目标服务器密码,正确输入即可正常登录了。如下图:

      如图所示,首次连接远程目标服务器,会提示对方身份不可确定,提供密钥供客户端去核实,假如是目标服务的密钥就允许继续连接,这也是为了防止冒充目标服务器发送密钥的行为。这边接受密钥之后,该主机就会记录下到 ~/.ssh/known_hosts 文件,下次就不需要再确认了。如图连接成功发现可以正常获取虚拟主机服务器目录文件即成功。
      为了免去每次连接都需要输入密码的麻烦,密码也容易忘记,所以接下来测试免密登录操作。
      1.先在客户机生成密钥对,有多种密钥可选择,可通过命令 ssh-keygen --help 查看,-b 参数指定密钥位数(bit),-t指定密钥类型。

      根据你生成的密钥对,获取对应的公钥,比如 id_rsa.pub 或者 id_dsa.pub,将其上传到目标服务器的需要免密登录的用户对应家目录下 .ssh 目录下并改名为 authorized_keys ,root 用户默认位置是:/root/.ssh/authorized_keys,其它用户如 yibin,位置是 /home/yibin/.ssh/authorized_keys 。
      1、注意目录权限:.ssh 目录权限必须是 700,chmod -R 700 .ssh/。然后就是 authorized_keys 文件的权限了,默认文件所属用户是 root ,这种情况下假如你只需要在客户机用 root 用户访问目标服务器的 root 用户进行免密登录的话,就可以设置权限为 600,表示只有 root 用户有 rw 权限即读写权限,后面 00 代表组和其它用户无 rwx 权限。现在你就可以去客户机在 root 用户下执行命令:ssh [email protected] 或 ssh 192.168.43.83 (192.168.43.83 是目标服务器 ip)进行登录操作,假如直接跳过密码登录,那么恭喜你成功了!假如提示需要输入密码的话,就到目标服务器查看 sshd 配置文件:/etc/ssh/sshd_config,将配置参数 PubkeyAuthentication 值改为 yes,并去掉注释符 #,还需要看看是否允许 root 登录,即将 PermitRootLogin 值置为 yes,再保存文件,后重启 sshd 服务即可。

      1
      2
      3
      4
      #ubuntu 系统重启 sshd 服务命令
      /etc/init.d/ssh restart
      #centos 系统重启 sshd 服务命令
      service sshd restart


      上面成功实现客户机 root 用户免密登录目服务器 root 用户,方法就是将客户机 root 用户生成的密钥对中的公钥放置到目标服务器要免密登录的 root 用户下的 ~/.ssh/authorized_keys 文件,并设置对应 sshd 服务的配置文件,允许公钥认证登录,此时 authorized_keys 文件权限可以是 600 或者 644 都没问题。
      2、接下来我就想在客户机用 root 用户免密登录目标服务器的非 root 用户,比如 yibin 用户,聪明的你肯定想到了,没错就是将客户机 root 用户的公钥放置到目标服务器的 yibin 用户家目录下 .ssh 目录下,改名为 authorized_keys,完整路径为 /home/yibin/.ssh/authorized_keys,注意 .ssh 文件夹权限需设置为 700,aurhoriized_keys 文件权限为 600 或 644。
      3、客户机非 root 用户免密登录服务器 root 用户
      同样的原理,此时需要在客户机非 root 用户下,我这边是 yibin 用户,从 root 用户切换到 yibin 用户命令,su yibin ,接下来就是生成密钥对了,可以直接使用命令 ssh-keygen 按回车默认生成 rsa 密钥对,再将公钥 id_rsa.pub 上传到服务器的 root 用户家目录的 .ssh 目录下,生成文件:~/.ssh/authorized_keys(即 /root/.ssh/authorized_keys),检查 .ssh 文件夹权限是否为 700,authorized_keys 文件权限是否为 644,注意这里是设置为 644 而不是 600了,否则一直提示需要密码登录。失败原因和下面第4点情况一致,所以统一在第4点解释。

      4、客户机非 root 用户免密登录服务器非 root 用户
      比如客户机 yibin 用户需要免密登录到服务器 yibin 用户,首先在 yibin 用户下生成密钥对,再将公钥复制到服务器 yibin 用户家目录 .ssh 目录下,确保生成文件:~/.ssh/authorized_keys(即 /home/yibin/.ssh/authorized_keys),保证目录 .ssh 权限为 700,authorized_keys 文件权限为 644,一开始我设置成权限为 600,结果就踩坑了,一直没缓过神来,无意间发现文件所属还是 root,然后设置权限是 600 的话,意思是只有 root 有读写权限,组和其它用户都无权限,导致无法免密登录。
      解决方法之一:我直接将文件所属改为 yibin 了,比较暴力,虽然 yibin 可以免密登录 yibin 了,但是其它非 yibin 用户估计就无法免密登录服务器的 yibin 用户了,所以还是参考解决方法二。


      解决方法之二:将文件权限设置为 644,即 root 拥有读写权限,组和其它用户都是 4 权限即 r 权限(读权限),所以客户机 yibin 用户也能免密登录服务器的 yibin 用户,这个解决方案比较合理。见下图:

      至此,客户端(非)root 用户免密登录服务器(非)root 用户的场景就基本讲完了。假如报错如下图,可以查看服务器端是否正确放置 authorized_keys 文件(内容为客户机对应用户的公钥文件),并确认权限是否设置正确,再检查 /etc/ssh/sshd_config 配置文件参数如 PermitRootLogin(假如允许 root 登录就开启,否则最好关闭),PubkeyAuthentication 是否设置为 yes(免密登录需要设置为 yes,否则设置为 no)等。

      /etc/ssh/sshd_config 配置文件参数

      总结:.ssh 文件夹权限设置为 700,authorized_keys 文件权限设置为 644 比较稳妥,除非你客户机都是由 root 用户发起连接就可以设置为 600,否则就像我一样踩坑了!好了,到此就结束了,写了好久尬尬!