跳转到内容

OpenSSH/SSH 协议

100% developed
来自维基教科书,开放世界中的开放书籍

OpenSSH 使用 SSH 协议,该协议通过 TCP 连接。通常,每个 TCP 连接都会建立一个 SSH 会话,但如果计划使用多路复用,则可以将多个会话复用到单个 TCP 连接上。当前的安全外壳协议集是 SSH2。它是对旧的、已弃用的 SSH1 协议的重写。它在安全性、性能和可移植性方面都进行了重大改进。现在默认使用 SSH2,并且 SSH1 支持已从客户端和服务器中删除。

SSH 密码身份验证的时序图

安全外壳协议是一个开放标准。因此,它是与供应商无关的,并由互联网工程任务组 (IETF) 维护。当前协议在RFC 4250RFC 4256 中有描述,并由 IETF secsh 工作组进行标准化。SSH2 的总体结构在RFC 4251,安全外壳 (SSH) 协议架构中进行了描述。

SSH 协议由三层组成:传输层、身份验证层和连接层。

SSH-CONNECT – 连接层运行在用户身份验证协议之上。它将许多不同的并发加密通道多路复用到经过身份验证的连接上的逻辑通道中。它允许隧道登录会话和 TCP 转发。它为这些通道提供流控制服务。此外,还可以协商各种特定于通道的选项。此层管理 SSH 会话、会话多路复用、X11 转发、TCP 转发、shell、远程程序执行、调用 SFTP 子系统。
SSH-USERAUTH – 用户身份验证层对客户端到服务器进行身份验证。它使用已建立的连接,并在传输层之上运行。它提供了几种用户身份验证机制。这些包括密码身份验证、公钥或基于主机的身份验证机制、挑战响应、可插拔身份验证模块 (PAM)、通用安全服务应用程序编程接口 (GSSAPI) 甚至加密狗。
SSH-TRANS – 传输层通过 TCP 提供服务器身份验证、机密性和数据完整性。它通过算法协商和密钥交换来实现这一点。密钥交换包括服务器身份验证,并最终导致加密安全连接:它提供完整性、机密性和可选压缩。 [1]

当前协议 SSH2 与已弃用的 SSH1 协议之间的差异之一是 SSH2 使用主机密钥进行身份验证。而 SSH1 使用服务器密钥和主机密钥来进行身份验证。关于协议本身,RFC 4251 [2] 中已经更详细和权威地介绍了这些内容,因此这里无法添加更多内容。

SSH 文件传输协议 (SFTP)

[编辑 | 编辑源代码]

SSH 文件传输协议 (SFTP) 是一种二进制协议,用于提供安全的文件传输、访问和管理。

SFTP 由 Markus Friedl 在 2000 年 11 月 OpenSSH 2.3.0 版本发布时添加到了服务器端。Damien Miller 在 2.5.0 版本发布时为客户端添加了对 SFTP 的支持。从那时起,许多人都在客户端和服务器端添加了功能。

SFTP 不是 FTPS

[编辑 | 编辑源代码]

对于基本的文件传输,只需要在运行 OpenSSH 服务器的机器上拥有一个帐户。SFTP 支持内置于 OpenSSH 服务器软件包中。与旧的 FTP 相比,SFTP 协议从一开始就被设计得尽可能安全,无论是登录还是数据传输。

Samba 是一种互操作性套件,为任何可以使用 SMB/CIFS 协议的客户端提供快速的文件和打印服务。它最常用于本地网络级别的文件共享。
AFS,或称安德鲁文件系统,是一种分布式文件系统,它在地域上分散的机构或一组协作机构之间提供文件共享。值得注意的是,它为所有客户端工作站提供了一组可信服务器和一个同质的、位置透明的文件命名空间。

除非用例要求公开可用的、只读的下载,否则不要尝试使用 FTP。FTP 协议本身固有地不安全。它非常适合只读、公开数据传输。例如,程序 vsftpdproftpd 就服务器软件本身而言是安全的,但协议本身仍然不安全。换句话说,程序本身或多或少是安全的,如果你需要提供只读的、公开可用的下载,那么 FTP 可能是合适的工具。否则,请忘记 FTP。当用户请求“FTP”时,他们通常并不特指 1971 年RFC 114 中描述的旧文件传输协议,而是泛指一种文件传输方法,而解决此问题的方法有很多。这一点尤其正确,因为他们请求的下一部分通常是如何使其安全。术语“FTP”经常被泛化地用来表示任何文件传输实用程序,就像“Coke”这个词在美国南部的一些地方被用来表示任何碳酸饮料,而不只是可口可乐一样。请考虑使用 SFTP,或对于更大的组,甚至 SSHFS、SambaAFS。虽然旧的 FTP 在实现其主要目标方面非常成功,即通过允许网络上任何主机上的用户使用任何合作主机上的文件系统来促进网络计算机的使用,但它无法变得安全。对此无能为力,所以现在是时候克服它了。

再说一次,问题在于 FTP 协议本身。 [3] 使用 FTP 时,数据、密码和用户名都是未加密地来回发送的。 [4] 客户端子网、服务器子网或两者之间的任何子网上的任何人都可以“嗅探”使用 FTP 时的密码和数据。通过额外的努力,可以将 FTP 包裹在 SSL 或 TLS 中,从而创建 FTPS。但是,将 FTP 隧道化到 SSL/TLS 上非常复杂,而且不是最佳解决方案。

不幸的是,由于名称混淆以及包裹 FTP 在 SSL 中以提供 FTPS 这种复杂、挑剔的任务所产生的大量帖子和讨论,这种错误的方式仍然经常出现在有关文件传输的网络搜索中。相比之下,简单的、相对无痛的解决方案消失了,因为很少需要发布如何执行这些操作。此外,一个简单的解决方案可以用很少的几行甚至一个答案来概括。因此,网络上仍然有很多关于“保护”FTP 的讨论,而关于使用 SFTP 的讨论却很少。本书希望打破这一恶性循环:困难的任务意味着大量的讨论和噪音,大量的讨论和噪音意味着强大的网络存在感,强大的网络存在感意味着较高的 Google 排名。

SFTP 工具非常普遍,但可能被认为是理所当然的,因此被忽视。SFTP 工具易于使用,并且比旧的 FTP 客户端功能更强大。事实上,在可用性方面已经取得了很大的进步。并不缺乏用于传输文件的常见、基于 GUI 的 SFTP 客户端:Filezilla、Konqueror、Dolphin、Nautilus、Cyberduck、Fugu 和 Fetch 位居榜首,但还有更多。大多数是免费软件。再说一次,这些 SFTP 客户端非常易于使用。例如,在 Konqueror 中,只需输入 sftp 服务器的 URL,其中服务器名称或地址为 xx.yy.zz.aa。

sftp://xx.yy.zz.aa

如果需要从特定目录开始,则也可以指定该目录。

sftp://xx.yy.zz.aa/var/www/pictures/

值得了解的一个特殊客户端是sshfs。使用sshfs作为SFTP客户端,另一台机器可以作为您机器本地文件系统上的一个开放文件夹访问。通过这种方式,您通常用来处理文件的任何程序,例如LibreOffice、Inkscape或Gimp,都可以通过该文件夹访问远程机器。

FTP 背景

[编辑 | 编辑源代码]

FTP 诞生于 1970 年代。它是久经考验的功臣,但来自一个时代,那个时代如果你在网络上,你就应该在那里,如果有问题,通常可以通过简短的电话或一两封电子邮件解决。它以未加密的方式发送登录名、密码和所有数据,供任何人拦截。FTP 客户端可以使用被动或主动模式连接到 FTP 服务器。FTP 的主动和被动模式[5] 使用两个端口,一个用于控制,一个用于数据。在 FTP 主动模式下,客户端与 FTP 服务器建立连接后,它允许服务器发起传入连接以进行数据传输。在 FTP 被动模式下,客户端与 FTP 服务器建立连接后,服务器会响应有关数据传输的第二个端口的信息,然后客户端发起第二个连接。FTP 现在最相关的应用是匿名 FTP,它仍然非常适合无需登录即可进行只读下载。FTP 仍然是传输只读数据的途径之一,就像使用网络(HTTP 或 HTTPS)或 Bittorrent 等 P2P 协议一样。因此,除了 FTP 之外,还有其他选择可以提供只读下载。最近,对于小文件,首选 HTTPS;对于大文件或大量文件,首选 Bittorrent。

使用 tcpdump 显示 FTP 活动

[编辑 | 编辑源代码]

可以通过工具tcpdump来演示旧协议 FTP 如何不安全。它可以显示在匿名 FTP 会话期间(或任何 FTP 会话)网络上发生了什么。查看tcpdump的手册页以了解各个参数的说明,下面的用法示例显示了从客户端到服务器以及反之的第一批 FTP 或 FTP-Data 数据包。

下面的输出显示了从tcpdump输出中摘录的部分,该输出捕获了 FTP 客户端和 FTP 服务器之间的数据包,每行一个数据包。

$ sudo tcpdump -q -s 0 -c 10 -A -i eth0 \
"tcp and (port ftp or port ftp-data)"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
… 
:18:36.010820 IP desk.55227 > server.ftp: tcp 16 E..D..@[email protected].[.X.....G.r. ........l..... ."......USER anonymous 
:18:36.073192 IP server.ftp > desk.55227: tcp 0 [email protected].[.X...1..... ...G.r#........... .....".. 
:18:36.074019 IP server.ftp > desk.55227: tcp 34 [email protected].[.X...1..... ...G.r#....Y...... ....."..331 Please specify the password. 
:18:36.074042 IP desk.55227 > server.ftp: tcp 0 E..4..@.@..+..1.[.X.....G.r# ..)........... ."...... 
:18:42.098941 IP desk.55227 > server.ftp: tcp 23 E..K..@[email protected].[.X.....G.r# ..)....gv..... .".w....PASS [email protected] 
:18:42.162692 IP server.ftp > desk.55227: tcp 23 [email protected].[.X...1..... ..)G.r:........... .....".w230 Login successful.
… 
:18:43.431827 IP server.ftp > desk.55227: tcp 14 E..Bj\@.7.3.[.X...1..... ..SG.rF.....j..... ....."..221 Goodbye.

正如在第 3 行和第 7 行中看到的那样,服务器的文本等数据是可见的。在第 1 行和第 5 行中,用户输入的文本是可见的,在这种情况下,它包括用于登录的用户名称和密码。幸运的是,该会话是匿名 FTP,它是只读的,用于下载。匿名 FTP 是发布下载资料的一种非常有效的方式。对于匿名 FTP,用户名始终是 "anonymous",密码是用户的电子邮件地址,并且服务器的数据始终是只读的。

如果您已经安装了 OpenSSH 服务器包,则无需进一步配置服务器即可开始使用 SFTP 进行文件传输。虽然相比而言,FTPS 比 FTP 安全得多。如果您想要远程远程登录访问,那么应该避免使用 FTP 和 FTPS。避免使用它们的一个非常重要的原因是节省工作量。

关于 FTPS

[编辑 | 编辑源代码]

FTPS 是通过 SSL 或 TLS 隧道化的 FTP。FTP 的目标是鼓励使用远程计算机,这与网络一起取得了成功。FTPS 的目标是保护登录和传输,这是使用旧协议保护文件传输的必要步骤。但是,由于 SFTP 的部署非常容易,而且大多数系统现在都包含图形和基于文本的 SFTP 客户端,因此对于大多数情况而言,FTPS 实际上可以被认为是过时的。

您可以在 FTP 和 FTPS 的请求 for Comments (RFC) 中找到一些很好的背景资料。在那里,SFTP 甚至 HTTPS 更加匹配,并且在很大程度上取代了 FTPS。请参阅有关客户端应用程序的部分,了解可用的 SFTP 客户端。

特权分离

[编辑 | 编辑源代码]

特权分离是指将进程分成多个子进程,每个子进程只对系统中的特定部分拥有足够的访问权限,以执行其工作。特权分离的目标是将任何损坏隔离,并防止损坏的进程访问系统的其他部分。其基本原则是最小特权,即每个进程只有完成任务所需的特权,不多也不少。目前是这样的[6]

sshd [listener]
   |
 exec
   |
sshd-session [privsep monitor]
  |      |
  |    exec
  |      |
  |    sshd-auth: [net unpriv]
  |
 fork (after auth completes)
  |
sshd-session [postauth unpriv]

首先,一个特权二进制文件监听传入连接。

$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root      2460     1 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)

连接开始后,它会被传递给一个单独的特权监控器二进制文件(在下文中显示为 PID 46495),该二进制文件以 'sshd' 帐户在非特权 exec 下执行(在下文中显示为 PID 96923)以处理身份验证。

$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root      2460     1 sshd: /usr/sbin/sshd [listener] 1 of 10-100 startups (sshd)
root     46495  2460 sshd-session: fred [priv] (sshd-session)
sshd     96923 46495 sshd-auth: fred [net] (sshd-auth)

'sshd' 拥有的 fork 被终止,如果身份验证成功,一个新的进程由已验证的帐户拥有,从监控器中分叉(在下文中显示为 PID 94635)以处理会话本身。

$ ps -a -x -w -o user,pid,ppid,args | grep '[s]shd'
root      2460     1 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups (sshd)
root     46495  2460 sshd-session: fred [priv] (sshd-session)
fred     94635 46495 sshd-session: fred@ttyp1 (sshd-session)

这是一个正在进行的工作,未来的发展可能会将身份验证后的非特权进程移入一个单独的二进制文件。便携式版本可能会获得一个 PAM 帮助程序二进制文件,它将由特权分离监控器调用。

自版本 3.3[7] 起,特权分离成为 OpenSSH 的默认设置。从版本 5.9 开始,特权分离进一步对特权分离子进程可以执行的系统调用施加强制限制。其目的是防止被入侵的特权分离子进程被用来攻击其他主机,无论是通过打开套接字进行代理,还是通过探测本地内核攻击面。[8] 自版本 6.1 起,这种沙箱已成为默认设置。

OpenSSH 特权分离的时序图

9.8 之前的旧特权分离

[编辑 | 编辑源代码]

OpenSSH 中的特权分离是通过使用多个级别的访问权限(有些级别较高,有些级别较低)来运行sshd(8)及其子系统和组件来实现的。SSH 服务器 ➊ 最初使用特权进程 ➋,然后创建一个非特权进程 ➌ 来处理网络流量。用户经过身份验证后,会创建另一个非特权进程 ➍,该进程拥有已验证用户的特权。请参阅 "OpenSSH 特权分离的时序图"。正如在图中看到的那样,总共运行了四个进程来创建一个 SSH 会话。一个进程(服务器)保持运行,监听新连接并生成新的子进程。

$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1' 
USER       PID  PPID STAT   STARTED  COMMAND
root      1473     1 I     05:44:01  sshd: /usr/sbin/sshd [listener] 0 of 10-10

正是这个特权进程监听来自客户端的初始连接。在这里,它正在等待并监听端口 22。

$ netstat -ntlp | awk '/sshd/ || NR<=2'
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1473/sshd       
tcp6       0      0 :::22                   :::*                    LISTEN      1473/sshd

在初始连接建立后,在等待用户 'fred' 的密码身份验证时,一个特权监控器进程监督 'sshd' 用户的非特权进程,该进程处理与远程用户的客户端的联系。

$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1' 
USER       PID  PPID S  STARTED COMMAND
root      1473     1 S 05:44:12 sshd: /usr/sbin/sshd [listener] 1 of 10-10
root      9481  1473 S 14:40:37 sshd: fred [priv]   
sshd      9482  9481 S 14:40:37 sshd: fred [net]

然后,在身份验证完成后,为用户 'fred' 建立一个会话后,会创建一个新的特权监控器进程来监督以用户 'fred' 身份运行的进程。此时,以用户 'sshd' 身份运行的另一个进程已经消失。

$ ps -ax -o user,pid,ppid,state,start,command | awk '/sshd/ || NR==1' 
USER       PID  PPID S  STARTED COMMAND
root      1473     1 S 05:44:12 sshd: /usr/sbin/sshd [listener] 0 of 10-10
root      9481  1473 S 14:40:37 sshd: fred [priv]   
fred      9579  9481 S 14:42:02 sshd: fred@pts/30

再次强调,这是针对旧的特权分离方法。


参考资料

[编辑 | 编辑源代码]
  1. "OpenSSH 手册页". OpenSSH. 检索于 2011-02-17.
  2. "RFC 4251:安全 Shell (SSH) 协议体系结构". 2006. 检索于 2013-10-31.
  3. "为什么您需要停止使用 FTP". JDPFu.com. 2011-07-10. 检索于 2012-01-09.
  4. Manolis Tzanidakis (2011-09-09). "停止使用 FTP!如何安全地传输文件". Wazi. 检索于 2012-01-09.
  5. Jay Ribak (2002). "主动 FTP 与被动 FTP,权威解释". Slacksite.com. 检索于 2020-03-20.
  6. "9.8 中的 sshd 二进制文件拆分?". openssh-unix-dev 邮件列表. 2024-07-17. 检索于 2024-07-30.
  7. Nils Provos (2003). "特权分离的 OpenSSH". 密歇根大学. 检索于 2011-02-17.
  8. "OpenSSH 5.9 版本说明". OpenSSH. 2011-09-06. 检索于 2012-11-17.

 

华夏公益教科书