OpenSSH
OpenSSH使用SSH协议通过TCP连接
通常,每个SSH会话会通过一个TCP连接建立,但如果预先规划,可以在一个TCP连接上复用多个会话。目前使用的Secure Shell协议是SSH2,它是对已废弃的SSH1协议的重写,包含了在安全性、性能和可移植性方面的重要改进。默认协议现在是SSH2,SSH1的支持已经从客户端和服务器中移除。
SSH密码认证的序列图
Secure Shell协议是一个开放标准,因此它是供应商中立的,并由互联网工程任务组(IETF)维护。目前的协议描述见于RFC 4250至RFC 4256,由IETF的secsh工作组进行标准化。SSH2的整体结构在RFC 4251中有所描述,名为《Secure Shell(SSH)协议架构》。
SSH协议由三层组成:传输层、认证层和连接层。
- SSH-CONNECT — 连接层运行在用户认证协议之上。它将许多不同的并发加密通道复用到经过认证的连接中的逻辑通道上。它支持登录会话的隧道化和TCP转发,提供流控制服务,并可协商各种特定通道的选项。该层管理SSH会话、会话复用、X11转发、TCP转发、Shell、远程程序执行以及调用SFTP子系统。
- SSH-USERAUTH — 用户认证层负责将客户端认证到服务器。它使用已建立的连接并运行在传输层之上。它提供多种用户认证机制,包括密码认证、公钥或基于主机的认证机制、挑战-响应机制、可插拔认证模块(PAM)、通用安全服务API(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(Andrew文件系统)是一种分布式文件系统,提供机构级的文件共享,适用于地理上分布广泛的机构或合作机构之间。它提供了一套受信任的服务器,并为所有客户端工作站提供一个均匀的、位置透明的文件名空间。
除非用例要求公开、只读的下载,否则无需担心尝试调试FTP。问题不在于FTP协议本身,而是FTP本身固有的不安全性。它非常适合只读、公开的数据传输。例如,程序vsftpd和proftpd在服务器软件本身上是安全的,尽管协议本身仍不安全。换句话说,程序本身大体上是没问题的,如果你需要提供只读、公开可用的下载,那么FTP或许是合适的工具。否则,忘记FTP吧。几乎总是,当用户要求“FTP”时,他们并不特别指代1971年在RFC 114中描述的旧文件传输协议,而是指某种通用的文件传输方式,而这个问题有很多解决方法。尤其是,因为他们接下来的要求通常是如何让它变得安全。“FTP”这一名称经常被错误地用作任何文件传输工具,就像“Coke”在美国南部某些地区指代任何碳酸软饮料,而不仅仅是可口可乐。可以考虑使用SFTP,或者对于较大的团队,使用SSHFS、Samba或AFS。虽然旧的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是上世纪70年代的产物。它是一种经过验证的工作马,但它的出现年代是在当时,如果你在网络上,就意味着你应该在那里,并且如果遇到问题,通常可以通过简短的电话或几封电子邮件解决。它发送登录名、密码和所有数据都是未加密的,任何人都可以拦截。FTP客户端可以以被动模式或主动模式连接到FTP服务器。FTP的主动模式和被动模式都使用两个端口,一个用于控制,另一个用于数据传输。在FTP的主动模式中,客户端连接到FTP服务器后,服务器会发起一个传入连接进行数据传输。而在FTP的被动模式中,客户端连接到FTP服务器后,服务器会返回一个关于数据传输的第二个端口的信息,客户端会发起第二个连接。FTP目前主要与匿名FTP相关,依然适用于不需要登录的只读下载。FTP仍然是传输只读数据的一种方式,类似于使用网页(HTTP或HTTPS)或像Bittorrent这样的P2P协议。因此,除了FTP之外,还有其他选择可供提供只读下载。近年来,对于小文件更倾向于使用HTTPS,对于大文件或大批量文件则使用Bittorrent。
使用tcpdump展示FTP活动
可以通过工具 tcpdump 演示旧的FTP协议是不安全的。它可以显示在匿名FTP会话期间,或者实际上任何FTP会话期间,网络上发生了什么。查看tcpdump的手册页可以了解各个参数的解释,下面的使用示例展示了从客户端到服务器以及反向传输的第一个FTP或FTP数据包。
以下输出显示了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..@.@.....1.[.X.....G.r. ........l..... ."......USER anonymous
:18:36.073192 IP server.ftp > desk.55227: tcp 0 E..4jX@.7.3.[.X...1..... ...G.r#........... ....."..
:18:36.074019 IP server.ftp > desk.55227: tcp 34 E..VjY@.7.3.[.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..@.@.....1.[.X.....G.r# ..)....gv..... .".w....PASS user@example.net
:18:42.162692 IP server.ftp > desk.55227: tcp 23 E..KjZ@.7.3.[.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的好背景资料可以在FTP和FTPS的请求注释(RFCs)中找到。在这些资料中,SFTP甚至HTTPS是更好的匹配,且大多已经取代了FTPS。有关SFTP客户端的信息,请参考客户端应用部分。
权限分离
权限分离是将一个进程分割成多个子进程,每个子进程仅拥有足够的权限来访问系统中的必要部分,以完成其工作。权限分离的目标是将任何潜在的破坏隔离开,防止受损的进程访问系统的其他部分。其基本原则是最小权限原则,即每个进程只有完成任务所需的最少权限,既不多也不少。目前的流程如下所示:[6]
sshd [监听]
|
执行
|
sshd-session [权限分离监控]
| |
| 执行
| |
| sshd-auth: [网络无权限]
|
fork (认证完成后)
|
sshd-session [认证后无权限]
首先,一个特权二进制文件监听来自客户端的连接。
$ 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”账户执行一个无特权的进程(如下所示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辅助二进制文件,供权限分离监控进程调用。
权限分离自OpenSSH 3.3版本起成为默认配置。[7] 从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
这就是旧版权限分离方法的工作过程。