很早之前我就曾写过关于 X11 转发的内容(e.g., Mininet + RYU SDN 开发环境搭建 - Nativus' Space (naiv.fun),但并没有做总结,不是很通用,因此重新再这里重新整理一下 X11 转发相关内容。(水博客)

为了能够让无头(headless) 的远程 Linux 主机显示 Wireshark、Oracle Database Installer 等具有 GUI 的程序,可采用 X11 转发的方式,在本地上显示程序的图像。

X Window System

什么是 X11

要想使用 X11 转发,首先要了解 X Window。X Window System (简写为 X11) 是一种用于位图显示的窗口系统,在类 UNIX 操作系统非常常见。

X11 为 GUI 环境提供了基本的框架,包括在屏幕上绘制和移动图像、监听鼠标键盘的操作等功能。同时 X11 自由度比较高,同样是采用 X11 方案的软件可能外观上有很大差异。

X11 是经典的 C/S 架构,分为 Server 和 Client,并定义了一系列协议用于 C-S 间通信。X Server 负责图形界面的显示和用户的输入,而 X Client 需要连接到 X Server,请求 X Server 绘制图形界面,同时从 X Server 接受用户的输入并做出响应。

在带有桌面环境的系统上,X Server 和 X Client 安装在同一台机器上,但是 X Server 和 X Client 显然可以分别运行在不同的机器上,从而实现在一台机器上运行程序,而在另外一台机器上显示图形界面。

X Server 和 X Client 分不清?

事实上,X Server 就像一个画布,Linux 上的 X Client 就像一个画家。Server 同显示器等硬件打交道,为画家(Client)提供绘图的必要服务。画家处理数据并对用户的做出响应,在画布上展示出来。(参见鸟哥的Linux私房菜)

举个实际的例子:假设此时你正在用一台 Windows 主机通过 SSH 连接到另一台 Linux 主机,要在 Linux 上运行 Wireshark 并把图像显示在 Windows 上,那么 X Server 在 Windows 上,X Client 在 Linux 上。

看上去这有点违反直觉。不过只要记住:在哪里看到画面,哪里就有 X Server。

X11 转发

X11 转发就是使用 SSH 转发 X11 的流量。

正如上文提到的,X Server 可以接受 X Client 的连接并显示出画面,那么如果 X Server 能够被随意连接就出大乱子了。所以很多时候 X Server 是具有认证的,将 X11 的流量暴露在公网上传输也是具有很大风险的。

这时 SSH 的作用就很明显了,SSH 相当于一个隧道,X11流量在其中是加密的,安全性大大提升。同时 SSH 会在远程的 Linux 主机上设置端口转发,这一点后面在操作部分会提到。

操作步骤

X Window System 有多种实现,在 Windows 平台上,常用的 X Server 软件是vcxsrv。也有一些终端软件,内部集成了 X Server(例如 MobaXterm)。

vcxsrv

  1. 在 Windows 上安装 vcxsrv;
  2. 在 Linux 上安装必要的软件包。例如:xorg-x11-xauth(用于 X11 的认证),和 xclock(用于测试 X11 转发是否生效)。
  3. 修改 Linux 主机上的 sshd 参数使之开启 X11 转发;
    打开 /etc/ssh/sshd_config 确保:

    X11Forwarding yes

    重启 sshd 服务。

  4. 打开本地(Windows)上的 XLaunch,启动一个 X Server。记住启动完成后右下角状态栏图标上显示的名称。例如:Leo-Laptop:0.0
  5. SSH 连接主机(Linux),并启用 X11 转发。

    ssh -X username@host
  6. 在主机上查看 $DISPLAY 变量指定转发到的客户端,若未设置则需要手动输入变量的值:

    export DISPLAY="Server Name"

    其中 “Server Name” 是第 3 步中启动的 X Server 的名称,例如 Leo-Laptop:0.0

  7. 启动服务,以 Wireshark 为例:

    sudo -E wireshark &

    或:

    sudo HOME=~ wireshark &

    其中:& 代表在后台执行该命令,不必等待程序退出;

    -E 使得 sudo 指令继承当前用户的环境变量;

    HOME=~ 使得 sudo 执行时设置 HOME 变量为 ~ (当前用户的家目录)。

    之所以要这样做,是因为以 root 身份执行 Wireshark 时,Wireshark 会尝试访问 root 用户的家目录,而 X11 Forwarding 时并没有权限访问 root 的家目录,所以需要我们指定家目录为当前用户的家目录,避免出现权限不足运行出错。

MobaXterm

  1. 安装 MobaXterm 后,确保主页面右上角的 X 图标为彩色(意为已经启动 X Server)。
    MobaXterm-XServer
    MobaXterm-XServer
  2. 连接到服务器后, 检查 X11 转发标志是否为对勾。
    MobaXterm-X11ForwardEnabled
    MobaXterm-X11ForwardEnabled
  3. 如果不是对勾:

    • 首先检查 /etc/ssh/sshd_configX11Forwarding 选项是否为 yes(参见上一节)。
    • 然后检查是否已经安装 xauth 包,方法是运行 xauth 命令,看是否有结果。
    • 其次检查 $DISPLAY 是否已经被设置,如果没有被设置可以尝试自行设置。需要注意的是,默认情况下 DISPLAY=localhost:10.0 就表明通过 X11 转发到远程主机显示。

常见问题

  • 如果需要测试,那么可以尝试安装并运行 xclock,如果 Windows 上出现了一个时钟窗口,则表示转发成功。
  • 关于 SSH 转发 X11,详细的日志可以通过使用 ssh -Xv 命令查看(-v:verbose)。
  • 如果登录远程的 Linux 后,需要切换用户(例如使用 su - username),那么需要将一开始登陆用户家目录下 .Xauthority 拷贝到要切换用户的家目录下,同时设置好权限和拥有者。设置完成后,可以在新的用户下运行 xauth,然后输入 list 命令查看已经具备权限的设备。然后再把 $DISPLAY 变量设置成正确的值。
    (出现该问题的原因是 SSH 只帮刚开始登录的用户设置了 .Xauthority 和恰当的环境变量。)

参考文献