在Linux中,经常使用ssh登录远程的Linux服务器。包括 密码认证模式 和 公钥免密认证 模式。下面以客户端和服务端均为Linux为例进行说明
ssh命令使用的几个文件
服务器端(Linux为例)
- /etc/ssh/目录下:sshd_config、ssh_host_ecdsa_key、ssh_host_ecdsa_key.pub、ssh_host_rsa_key、ssh_host_rsa_key.pub 主要存放作为sshd服务的配置。 以及服务器的公钥、私钥等(整个服务器的,不是某个用户的)。
- 服务端用户~/.ssh目录下:authorized_keys 该文件存放已认证用户的publickey公钥(每行一条),代表已被该服务器用户认证可信的客户端公钥列表,客户端可免密码以该服务端用户身份登录。
客户端(Linux为例)
- /etc/ssh/目录下:ssh_config 存放ssh命令作为客户端的配置。
- 客户端用户~/.ssh目录下:
- known_hosts 存放已被该客户端认证可信的服务器公钥列表(内容一般对应服务器上的ssh_host_ecdsa_key.pub文件)
- id_rsa和id_rsa.pub文件。放在客户端客户端用户的私钥和公钥(可以使用ssh-keygen工具生成私钥和公钥)
ssh命令登录的流程原理
- 客户端登录请求登录,建立TCP连接、协商版本等工作。
- 服务器将自己的公钥(server pubkey)发给客户端,客户端如果认可该服务器公钥(人工确认yes),则加入到客户端的kown_hosts文件中。下次就不必人工再次确认。
- 服务器产生会话ID(session id)发给客户端。然后客户端产生会话秘钥(session key),将session key与session id异或后,用server pubkey加密后,发给服务器。
- 服务器使用服务器自己的私钥(server prikey)解密,获得session key。 (这时,双方都拿到了session key)
- 客户端将自己当前用户名和主机名(姑且叫client_user, client_hostname)使用session key 加密发给服务器。同时还告诉服务器准备以哪个用户(login_user)来登录服务器。
- 服务器解密后,使用client_user, client_hostname,从服务器用户(server_user=login_user)目录下authorized_keys文件查找客户端公钥。
- 如找到客户端的公钥:
- 则进入publickey认证模式:服务器生成随机数,将该数使用客户端公钥加密后,发给客户端
- 客户端用户(client_user)使用自己的私钥解密该随机数,并将结果发给服务器,服务器比较一致后,则返回登录成功,最终以(server_user=login_user)名义成功登录。
- 如果没找到客户端的公钥
- 这进入password认证模式,服务器告诉客户端需要密码。
- 客户端提示输入密码(server_user=login_user的密码),然后使用session key加密后,传给服务器。服务器密码交易通过后,则返回登录成功。最终以(server_user=login_user)名义成功登录。
免密码登录(既publickey认证模式)的步骤
要实现客户端免密码登录服务器,只需要让服务器在publickey认证模式下(能找到client_user, client_hostname对应的公钥)。既:
1、在客户端通过ssh-keygen工具,生成某个客户端用户(client_user)的id_rsa和id_rsa.pub文件(这两个文件应当存放在客户端用户的~/.ssh目录下);
2、人工将客户端用户(client_user)的公钥(既id_rsa.pub文件中的内容,有且只有一行)内容字符串文本,拷贝到服务器用户(server_user)的.ssh目录下authorized_keys文件中(注意authorized_keys文件中一行代表一条公钥,可追加的文件末尾)。
拷贝完成后,客户端立即可免密码登录成功。(网上有文章说的必须要先使用密码登录一次才行,这种说法是错误的)
其中几点注意:
- 既对于同一台服务器而言,不同客户端(或同客户端下不同用户)的用户目录下的know_hosts文件中,反映该服务器的公钥内容串是相同的(内容一般对应服务器上的ssh_host_ecdsa_key.pub文件);
- 客户端和服务端上的用户.ssh 目录权限必须严格是700(权限过多也不行)。
- 服务端上的用户.ssh/authorized_keys文件权限应为600或644(即除了自己外,group和other都最多可拥有读权限但不能拥有写权限)。
ssh命令登录时,有三个涉及用户的地方,要注意分清:
- 服务端用户server_user。服务端上已存在的用户,既以该用户登录并使用服务端上的资源)。本文称server_user。
- 登录服务端用户login_user。客户端执行ssh命令是,在命令行中指定的将登录服务端的用户,本文称login_user。应当是服务端上已存在的用户。
- 客户端用户client_user。客户端Linux的当前用户(既在客户端中执行ssh命令的当前用户),本文称为client_user。
这三用户的关系是:
- server_user=login_user
- 如果是需要密码(password认证模式):则与client_user关系不大(仅需要要保存kown_hosts在用户目录下)。只要知道了服务端用户的密码即可登录。 这就是我们日常密码模式登录,在哪里都可以登录,根本不用管客户端是什么在哪里(当然网络必须允许)
- 如果是免密码(publickey认证模式):则与依赖client_user。因为ssh命令登录时会将client_user发给服务端,服务端也需要根据client_user从authorized_keys文件找已认证的公钥内容,找到后客户端还需依赖client_user目录下私钥文件来解密服务器发来的随机数。既服务端对客户端的免密认证,是区分客户端用户的(多个客户端用户如需免密认证,这需要分别向服务器authorized_keys添加对应公钥)
- 如果客户端上同一个client_user,需要免密登录多台服务器(例如用一台机器来免密集中管理多个服务器的场景),只需要将该client_user的公钥串,复制到每个服务器用户(server_user)目录下的authorized_keys即可。 公钥串仅生产一份即可,既每台服务器上都拥有相同的client_user的公钥串。
- client_user目录下的私钥公钥文件(id_rsa和id_rsa.pub)与用户密切相关。拷贝其他用户的这两个文件,是不能使用的
附:ssh-keygen工具
ssh-keygen工具生成过程示例:

ssh-keygen工具生成的私钥、公钥内容示例:

特别注意:公钥id_rsa.pub文件中的文本内容有且只有一行,该行最后为客户端用户名@客户端主机
1441






