什么是X11转发
陈拓翻译 2024/11/11-2024/11/13
原文:https://goteleport.com/blog/x11-forwarding/
《What You Need to Know About X11 Forwarding》
X11转发简介
X11转发是一种SSH协议,它使用户能够在远程服务器上运行图形应用程序并使用其本地显示器和I/O设备与它们交互。开发人员通常依靠它来安全地与跨广泛和异构服务器群的远程机器交互。
尽管X11转发用途广泛,但很少有资料能够准确解释其工作原理。在这篇博文中,我将分享一些见解来回答有关X11和X11转发的常见问题,并介绍与X11转发相关的安全隐患,任何用户理解这些隐患都会受益匪浅。
在这篇博文将回答关于X11和X11转发的常见问题,并涵盖与X11转发相关的安全影响。
什么是 X11?
X11指的是X Window System的第11版,这是互联网早期开发的一种开源图形协议。它提供了一个用于创建自定义GUI(用户图形界面)的基本框架,这些GUI可以在本地和远程显示设备上显示图形。X11的远程功能在互联网早期非常有用,当时的“超级”计算机会处理多个用户在独立工作站(有时是通过远程网络)上的繁重工作。
X11最初是一个相当基础的协议,但在过去的几十年里,它已经被扩展,以包含现代特性,如共享内存扩展,它大大提高了X11的性能。像Wayland这样的新项目正在迅速超越X11并在整个行业中获得关注,但由于X11早期被广泛采用,因此还远未走到生命周期尽头。即使是现在,X11仍然是大多数unix系统的默认图形协议,并且可以轻松安装在任何其他相关的操作系统上。这也促进了X11转发的流行,因为服务器管理员可以期望X11在客户端和服务器机器上均可配置,而几乎不需要额外的工作。X11转发在金融等计算密集型行业中尤其流行,并且仍然被用于高性能计算,因为它最初就是为高性能计算而设计的。
客户端-服务器模型
X11使用客户端-服务器模型,其中X服务器是计算机上用于管理图形显示和输入设备(显示器、鼠标、键盘等)访问的程序,而X客户端是处理图形数据的程序。使用此模型,X客户端应用程序可以与X服务器建立连接,以通过图形原语(graphical primitives)与X服务器的设备进行通信。此客户端-服务器术语在远程场景中可能会造成混淆,因此请记住,在大多数情况下,X服务器在用户的计算机上运行,而X客户端在远程计算机上运行。
X11被设计为网络透明,这样X服务器和X客户端就可以用相同的方式在本地和远程网络上进行通信。这可以通过将X服务器链接到一个公开的TCP地址来实现,而不是以默认的本地回环地址或Unix套接字来实现。然而,X11在默认情况下是不安全的明文协议,因此不建议直接公开X服务器。相反,今天大多数用户在远程运行X11程序时使用X11转发来利用SSH的安全性。
显示
在X11中,显示(display)指的是一组显示设备,X服务器可以直接向这些设备发送和接收图形数据。一个显示通常至少包括一个屏幕、键盘和指针设备。在这种情况下,屏幕并不是指物理显示器,而是一个可以读取原始图形数据的虚拟画布。实际上,单个屏幕可以由多个监视器和其他虚拟显示组成。
X客户端程序使用$DISPLAY变量来确定要连接到哪个X显示,该变量的格式类似于 hostname:display_number.screen_number。X程序可以从这个值推导出 TCP或Unix套接字,以通过X服务器建立与显示的连接。一旦连接被接受,X服务器就会将连接转发到请求的屏幕上。
$DISPLAY变量有一些隐藏的规则,可能会有点令人困惑。首先,显示编号必须始终明确设置,而主机名和屏幕编号分别默认为device_name/unix和0。因此,:0实际上等同于device_name/unix:0.0,这两个值将被视为相同。你也可以使用unix:0来引用device_name/unix:0。
其次,显示关联的tcp或unix套接字导出如下:
- hostname:n->localhost:6000+n
- hostname/unix:n->/tmp/.X11-unix/Xn
安全
X服务器可以通过几种方式控制对其显示的访问,但最常见的一种,也是与 X11 转发唯一相关的,是基于cookie的访问,使用MIT-MAGIC-COOKIE-1协议。在这个协议中,X客户端必须提供一个有效的明文32字节的cookie。如果X服务器识别出所请求显示的cookie,它将根据该cookie允许的权限集合,向客户端提供对显示的访问。不幸的是,这些权限并不细致,而是只分为两类:受信任和不受信任。具有受信任权限的cookie将提供对X服务器的无限制访问,而不受信任的cookie将限制权限,例如限制程序只能访问自己的窗口,并拒绝访问剪贴板。
使用xauth程序,你可以在X服务器中添加和生成cookie,并将它们保存到磁盘上环境变量$XAUTHORITY指定的位置,如果该环境变量未设置,则保存到默认的~/.Xauthority文件中。当你运行一个X程序时,它将从$XAUTHORITY或~/.Xauthority检索所用于请求显示的X身份验证数据,并在连接到X服务器时提供X认证数据以进行身份验证。
你应该知道的一点是,如果X程序无法找到所请求显示的任何X身份验证数据,它将在没有X身份验证数据的情况下形成连接。X服务器仍然会接受该连接,并使用其默认的不安全连接方法。这意味着,X程序有责任强制执行其自己的身份验证和授权,而不是由X服务器来强制执行。因此,xauth通常与其他访问控制系统(例如xhost)一起使用,以防止不受信任的X客户端尝试连接到X服务器。
X程序
现在已经解释了X Window System的每个组件,我们可以看一看当你运行X程序xeyes时它们是如何联系在一起的。
X11 转发如何工作?
了解了X11的基础知识后,我们可以深入探讨X11转发的细节。
X11转发遵循与X11相同的模型,但X客户端到X服务器的连接是通过SSH通道进行隧道传输的。为了实现此流程,SSH服务器将远程X客户端连接代理到SSH客户端,然后,SSH客户端再将其代理到用户的X服务器。
听起来很简单,但SSH服务器和客户端在幕后做了很多工作,以确保SSH会话中的任意X程序能够成功且安全地转发到你的本地X服务器。为了揭示X11转发的这些秘密,我们将首先看看如何从ssh -X过渡到一个完全设置好的X11转发SSH会话。其次,我们将看到在这个会话中运行的X客户端程序是如何与你的本地X服务器通信的。最后,我将解释X11转发如何利用本地和远程X授权来防止远程主机上的任何人访问你的本地X服务器,以及解释不受信任的X11转发(ssh -X)与受信任的X11转发(ssh -Y)有何不同,以保护本地X服务器免受恶意远程用户和黑客的攻击。
X11 转发会话设置
当你输入命令ssh -X remote-user@remote-host时,你的计算机将启动一个新的SSH客户端,并从远程SSH服务器remote-host请求一个SSH会话,就像你省略-X标志时一样。一旦创建了正常的SSH会话,你的SSH客户端将跟着发送一个x11-req SSH请求。如果SSH服务器允许remote-user使用X11转发,那么它将开始为该会话设置X11转发。
SSH服务器将从localhost:6010开始打开一个X服务器代理监听器,并将SSH会话的$DISPLAY设置为相应的套接字localhost:10。因此,在会话中启动的任何 X 程序都会查看$DISPLAY并连接到X服务器代理的TCP套接字。SSH服务器随后就可以拦截X11连接并将其转发到SSH客户端。
一旦服务器向你的SSH客户端发出信号,表明X11转发已成功设置,SSH客户端将发送一个SSH请求pty req,以在远程主机上启动一个新的bash会话,并按常规完成SSH会话设置。
在 X11 转发会话中运行 X 程序
现在我们已经设置好了一个完整的X11转发SSH会话,我们可以看看当你运行像xeyes这样的X程序时会发生什么。由于远程Bash会话已经设置了 $DISPLAY=localhost:10,xeyes将会连接到localhost:6010上的X服务器代理。当SSH服务器接收到这个连接时,它将为该会话创建一个x11 SSH通道,并开始将xeyes连接转发到通道中,发送给SSH客户端。
然后,SSH客户端将连接到你本地的$DISPLAY,并通过这个连接将xeyes连接从 X11 SSH通道转发出去。像往常一样,你的X服务器会将此连接转发到正确的屏幕及其指定的显示设备,从而完成从远程xeyes程序到本地显示和I/O设备的连接。
X11转发 X 权限设置
正如我在上面提到的,到目前为止我们描述的X11转发缺少了一个关键部分。目前,X11转发会话将为任何可以访问远程主机上localhost:6010的X服务器代理的人提供对本地X服务器的访问。远程计算机上的恶意用户可以使用它来转发X程序,该程序可以截取显示器的屏幕快照、捕获鼠标和键盘操作,甚至可以插入X11操作以在开放终端中运行自己的命令。为了避免这种情况,我们需要为SSH客户端提供一种方法来验证来自远程X服务器代理的请求。
为了验证转发的X程序连接,SSH客户端将向原始X11请求x11-req附加X权限协议和cookie。实际上,这个cookie不会用于连接X服务器,因此,SSH客户端只需为MIT-MAGIC-cookie-1协议生成一个随机的伪cookie,并在发送请求之前保存它的记录。在收到伪X身份验证数据后,SSH服务器将其添加到远程X授权文件中,也就是将$DISPLAY=localhost:10添加到用户主目录的~/.Xauthority文件中。
这次当你运行xeyes程序时,它会从~/.Xauthority中检索伪X身份验证数据,并将其附加到X服务器连接上。在通过X11通道隧道传输连接后,SSH客户端将从连接中的初始X11数据中读取X身份验证数据,并决定是否接受该连接。如果接受,SSH客户端会从你的本地的$XAUTHORITY获取真实的X身份验证数据,以替换连接中的伪X身份验证数据。最后SSH客户端会像之前一样将连接转发给你的$DISPLAY。
受信任的 X11 转发ssh -Y
到目前为止解释的X授权设置称为受信任的X11转发,因为你最终是信任远程主机的访问控制来保护对X服务器代理的访问。如果其他人又访问remote-user或root的权限,则他们可以访问/users/remote-user/.Xauthority,并使用它来运行连接到本地X服务器的X程序。这将使你的X服务器面临前面提到的X11攻击。为了保护你的X服务器免受这些攻击,你需要使用不受信任的X11转发。
不受信任的 X11 转发ssh -X
在不受信任的x11转发中,我们在启动X11转发之前会执行一个额外的步骤。在本地计算机上,SSH客户端创建一个新的临时$XAUTHORITY,并使用xauth创建一个新的不受信任的cookie。现在,当SSH客户端从转发的X11连接读取并替换伪X身份验证数据时,它将用这个不受信任的cookie替换伪数据,而不是使用默认的受信任设置。
任何连接到localhost:6010并显示正确的伪X身份验证数据的人都将仅被授予不受信任的访问权限。虽然这确实意味着恶意用户仍可能运行X程序并将其转发到你的X服务器,但任何可能造成破坏的X11权限都将受到限制。它还远非完美的系统,但总体而言,不受信任的转发提供了一个可靠的安全标准,并避免了与受信任的转发相关的更严重的风险。
不幸的是,在Unix操作系统上,受信任的转发实际上是ssh -X的默认行为。造成这种情况的原因有很多,但总结来说,不受信任的权限系统是事后作为插件添加的,而不是内置于X11协议本身。因此,不受信任的转发性能较差,还存在兼容性问题,总体上使用起来也不够直观和直接。虽然性能和兼容性问题在今天很少出现,但20年前当X11转发被添加到OpenSSH时,这是一个大问题。由于这个不幸的历史,你需要在SSH客户端配置文件~/.SSH/config中明确设置ForwardX11Trusted no来启动不受信任的转发,我强烈推荐这样做。如果你确实需要为特定用例使用受信任的转发,那么你仍然可以使用ssh -Y。
译者注:
ssh -X和ssh -Y都用于启用X11转发。但是,-Y是一种相对宽松的信任模式,它允许所有的X11连接请求,这可能会带来一定的安全风险。因为在这种模式下,远程服务器上的应用程序对本地X11服务器有更多的访问权限,可能会导致本地系统受到恶意软件或者被攻击者利用一些X11协议的漏洞进行攻击。而-X选项在安全性上相对更严格。它会尝试对X11协议进行安全封装,通过一些安全扩展来减少潜在的安全风险,比如限制某些可能有安全隐患的X11操作。
ssh -Y被称为受信任的X11转发,因为它信任所有转发的X11连接,而不像-X那样需要额外的认证。
结论
X11转发是一种实用且可靠的工具,可用于在远程机器上安全地运行图形程序。它的设置也相对简单,这对于在广泛且多样化的服务器群中扩展远程图形访问非常重要。在这篇文章中,我们了解了一些鲜为人知的有关X11转发的细节,包括它的工作原理以及如何安全地使用它。