远程管理的好抓手 — SSH

一、缘起

对计算机系统进行维护、管理和使用,最直接的方式,毫无疑问就是直接坐到物理计算机前,利用计算机系统的输入设备对其进行的管理与使用。这种方式可以视为一种直接管理模式,简单明了。但是,在现实应用中,还有很多不同的场景,比如:

  • 我们需要管理和使用的计算机并不在身边,甚至距离很远,比如在数据中心机房中的大型计算机;
  • 我们需要管理和使用的设备虽然就在身边,但是这些设备没有一个明显即时可见的交互输出设备,我们没法“直接”通过可见交互来管理这些设备,比如一些嵌入式的设备;

此时,直接管理模式很难发挥作用,则利用身边可及的本地计算机系统,通过目标计算机系统可达的“链路”,构建一种“远程”的模式,来管理那些没法通过直接手段管理的计算机,已是必然之选。通过远程连接管理计算机也由此而来。

利用网络来远程管理计算机,尤其是类Unix系统,已有多年的历史,甚至在internet普及推广之前,就已经有了一些广受欢迎的远程管理程序,如rlogin、telnet等,这些程序在特定的年代、特定的需求下发挥了重要作用,但是,随着internet的广泛应用,这些程序以明文形式传输所有的交互信息,包括登录命令和密码,已显然不能适应internet的使用要求。

此时,需要一种更为安全的计算机系统远程管理手段,一种新的更为安全的协议应运而生,即 SSH协议(Secure Shell)

二、协议设计

1、主机管理的基本逻辑

现代操作系统设计都是多用户、多权限设计,当我们应用或维护某台计算机系统时,必然是以该计算机系统已有的某个用户账户的身份,登录到该特定名称的计算机,对其进行管理和使用。也就是说,(用户名,主机名) 的二元组,就代表了一个计算机管理的接口。当需要对某台远程计算机进行管理时,也不例外,首先也是要确定这个接口,不同计算机系统接口不同。

通过特定的(用户名,主机名)二元组接口进入主机后,就可以拿到针对这个特定接口的shell,利用这个shell,即可根据特定的(用户名,主机名)二元组的具体权限对计算机系统的资源进行使用并维护。类Unix系统中,默认的 bash 的 prompt 符号对这一特点有突出体现。

SSH视为提升传统远程管理程序而生,那么,它首先具备传统远程管理的能力。对类Unix系统而言,只要拿到其shell,即可进行管理和使用,ssh的基本功能也是利用 “用户名@主机名” 二元组连接远程主机,拿到对应shell后,进行远程管理。

2、SSH协议的安全加强

SSH 协议构建于TCP层之上,是基于应用层的协议。传统的远程管理,是利用某种协议建立远程连接后,基于shell的远程管理。SSH,全名为Secure Shell,顾名思义,其核心目的就是为计算机上的shell提供安全的传输和使用环境,其在安全方面有了进一步的加强。

SSH的安全加强,主要面向的是传统远程控制程序明文传输的问题,本质上还是要解决“在不可信通道上传输敏感信息”的这个共性的通信安全问题。要解决这个问题,需要在两个方面进行加强:

  • 会话安全问题 — 对称加密手段

即通信两端,即本地与远程主机之间,所有通讯信息加密问题;

  • 身份安全问题 — 非对称加密手段

即通信两端,即本地与远程主机之间,身份确认的问题;

为达到这些目标,SSH协议的解决方案也和其他针对通讯安全类问题的解决方案一样。充分利用了密码学两大类核心技术手段。利用对称加密手段完成所传递的通讯信息的加密,利用非对称加密手段完成身份的确认,以及对称加密密钥(会话密钥)信息的传递。

设计上,SSH协议采用伺服器/客户端进程模型。对两方进行身份验证,并对它们之间的数据进行加密。

  • 服务端在指定端口监听连接请求。它负责协商安全连接,对连接方进行身份认证,并为客户端生成正确的shell环境。
  • 客户端负责协商安全连接,验证服务器的身份是否与以前记录的信息相匹配,并提供凭证进行身份验证。

运行流程上,SSH协议分为两个步骤,先建立安全会话,再进行身份认证

  • 第一步骤,通信两端必须先协商并建立加密,本质上就是双方平等地参与,生成共享的会话密钥,利用加密来保护未来的沟通;
  • 第二步骤,服务器对客户端进行身份验证,并发现是否应该授予其对服务器的访问权限,解决登录问题;

三、协议实现

SSH协议也仅仅是一种协议标准,协议本身只是规定了一种接口,一种规范,真正应用还需要对其进行特定语言、特定平台的实现。对SSH协议的实现有很多种,既有商业实现,也有开源实现。在Linux系统中,对SSH协议的支持已成为一种标配,使用最为广泛的是一种开源实现 — OpenSSH

SSH协议实现采用伺服器/客户端进程模式。以下以Ubuntu平台为例。

1、运行环境初始准备

服务器一侧,

  • 服务器进程运行在被管理的远程计算机上,等待连接;
  • 服务器进程为sshd,是一个值守进程;
  • 默认开放22端口,对其进行监听;
  • 服务器须先具备密钥对,安装openssh-server软件包时,即会生成服务器初始密钥对,并在系统中自动创建配置文件夹 /etc/ssh/;
  • 配置文件夹 /etc/ssh/
    • /etc/ssh/ssh_host_* :服务器密钥对文件
      • /etc/ssh/ssh_host_dsa_key
      • /etc/ssh/ssh_host_dsa_key.pub
      • /etc/ssh/ssh_host_rsa_key
      • /etc/ssh/ssh_host_rsa_key.pub
    • /etc/ssh/sshd_config:值守进程配置文件,包含服务器各种参数

客户端一侧,

  • 客户端进程运行于本地可及的计算机上,用于登录并管理使用远程主机;
  • 使用ssh程序进行登录;基本格式

    ssh [parameters] [username@]hostname [command]

  • 客户端需安装ssh专用客户端软件,安装openssh-client后,用户主文件夹自动创建配置文件夹 ~/.ssh/

  • 配置文件夹为 ~/.ssh/
    • ~/.ssh/known_hosts:已登录过的远程主机的公钥

2、运行过程

2.1、会话密钥生成阶段

客户端和服务端首先会根据既有基础(服务端公钥),在客户端生成会话密钥,并与服务器共享;过程如下:

* -->   请求连接
* <--   发送服务器公钥,其他信息;客户端将服务器公钥存储在本地 ~/.ssh/known_hosts文件中
* -||   <b>客户端生成会话密钥</b>
* -->   公钥加密后信息(含会话密钥)
* ||-   服务器私钥解密,得到会话密钥

由会话密钥生成过程可见:

  1. 会话密钥生成整个过程本质上是客户端来主导的
  2. 服务器公私钥对是先决条件,发挥了重要作用;
  3. 会话密钥是当次会话随机生成的,无存储必要,被窃也无安全隐患。至此,客户端和服务器只是建立了安全的通信通道,彼此的身份并不透明,还需要通过认证步骤,以确定对方是否是要找(服务)的对象。

生成会话密钥后,以后的会话内容和口令都通过此会话密钥加密发送。实际应用中,通常每过一段时间(如一个小时),服务器和客户端会重新商定会话密钥,以防止会话密钥被暴力破解。

2.2、登录认证阶段

生成会话密钥后,可进行SSH登录认证;SSH提供两种登录认证方式:

1)option 1 密码登录

利用前一阶段生成的会话密钥加密帐号、认证方法、口令,并将其传送给服务器端。服务器端收到后将其解密后,基于本地已有账户密码信息对其判断是否正确。

如正确,成功建立登录连接,否则,向客户端返回认证失败报文,其中包含了可再次认证的方法列表。当登录请求次数达到可允许的尝试上限次数后,服务器端断开本次TCP连接,并限制此帐号连接请求。

由密码登录过程可见:

  1. 在密码登录方式中,客户端是不需要生成公私钥对的;
  2. 使用时每次都需要用户输入密码,不是十分方便;
  3. 容易收到“中间人攻击”威胁;
2)option 2 客户端公钥登录(免密登录)

密码登录保留了传统远程登录使用习惯,比较容易接受,但缺点也比较明显。

为此,SSH提供了公钥登录的方式。显然,这种方式需要客户端也像服务器一样,拥有自己的公私钥对。客户端使用自己特有的公钥,作为自己特定的“身份证明”,登录远程服务器。

* -->   客户端发送自己公钥信息;
* <--   服务端本地是否有这个公钥信息,如有,用该公钥加密随机数,并送回客户端;
        *   判断准则是检查文件~/.ssh/authorized_keys文件中寻找该公钥信息;
* -||   客户端如有对应的私钥,则能解密消息,得到服务端随机数; 
* -->   客户端使用“随机数+会话密钥”得到一个值,将这个值发送回服务端;
* ||-   服务端同样用“会话密钥+随机数”计算。与客户端传回值比对。如匹配,则证明客户端拥有私钥,客户端验证通过。

由客户端公钥登录过程可见:

  1. 公钥登录整个过程本质上是服务器主导的;
  2. 客户端需要公私钥对,并且发挥了重要作用,而该过程中服务器公私钥对没有影响;
  3. 公钥登录过程无需用户输入密码,实现了免密登录,如此,可免除人为交互环节,实现自动化远程登录;

更细粒度的实现过程可考虑抓包进一步分析。

公钥登录应用场景很多,比如,github 的远程登录系统就是使用了 ssh 的公钥免密登录方法。

免密登录配置

为使用公钥登录(免密登录),需要利用openssh提前进行一些配置工作:

(1)服务器,让远程主机配置上支持公钥登录(配置 /etc/ssh/sshd_config 文件)

  • RSAAuthentication yes
  • PubkeyAuthentication yes
  • AuthorizedKeysFile .ssh/authorized_keys
    (服务器的 authorized_keys 文件如未提前创建,客户端操作(3)会自动创建该文件)

(2)客户端,生成客户端公私钥对

ssh-kengen [paremeters]

命令执行后,在客户端用户文件夹 ~/.ssh/中生成公私钥文件。

(3)客户端,将客户端公钥上传服务器

ssh-copy-id user@host

完成上述准备工作,只利用命令

ssh user@host

即可一站式登录。

四、参考材料:

  1. 《Linux Command Line》,chapter 17
  2. 《鸟哥的私房菜(服务器篇)》
  3. http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html
  4. https://mp.weixin.qq.com/s?__biz=MzIxMzU2NTk4NQ==&mid=2247483666&idx=1&sn=b0e306567c6cb2df906cd96b0c6cc59b&chksm=97b5965ca0c21f4aa361ad54655a6fa8b497b7e25106afc50fbe88f78e8c2bf7a44fa6afdc49&mpshare=1&scene=24&srcid=0912UoQhlfjSP2pGK0ZTN0RQ#rd
  5. https://mp.weixin.qq.com/s?__biz=MzI4OTY3NDM0OQ==&mid=2247483672&idx=1&sn=5406a79512dc587f6b6670e467606bb0&chksm=ec2ac41adb5d4d0c7537d432cd50c5169b4cd7bd42be9927b556f6b142805995abf147c1ad39&mpshare=1&scene=24&srcid=0912QSpTQj5OOK9MLd302G3F#rd
  6. https://www.jianshu.com/p/8e5b7aea52b5
  7. https://www.jianshu.com/p/920ad10c654d

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注