安装
brew install --cask xquartz
配置
打开 xquartz,新建一个终端,然后执行 xhost + 开放权限。
linux 中 sshd 配置
/etc/ssh/sshd_config 中开启如下配置后重启 sshd:
X11Forwarding yes
使用普通用户连接到远端 linux 中
ssh 命令中添加 -X 参数,未开启 X11Forwarding 时报错信息如下:
longyudeMacBookPro:~ longyu$ ssh -X longyu@debian
X11 forwarding request failed on channel 0
开启后,ssh -X 成功建立隧道,此时 netstat -anp 查看 sshd 相关连接信息,能够发现如下内容:
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 33315/sshd: longyu@
tcp 0 0 192.168.31.197:22 192.168.31.66:51014 ESTABLISHED 33306/sshd: longyu
tcp6 0 0 ::1:6010 :::* LISTEN 33315/sshd: longyu@
sshd 监听本地 6010 端口,接收任意 ipv4、ipv6 地址访问数据来进行 X11 转发。
此时在 ssh 连接成功的终端执行 xclock 命令,然后重新查看端口信息,发现增加如下连接:
tcp6 0 0 ::1:6010 ::1:54714 ESTABLISHED 33315/sshd: longyu@
此条连接建立后,xclock 通过此条通道走已经建立的 ssh 隧道转发 X11 图形界面数据到 MacOS,MacOS 中会自动打开 xquartz,弹出 xclock 的图形界面。
strace 跟踪 X11 客户端程序,过滤到如下 connect 连接调用,与上面的连接匹配:
connect(3, {sa_family=AF_INET, sin_port=htons(6010), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
使用 root 用户打开
当图形界面程序需要使用 root 权限打开时,可以执行 ssh -X root@xxx 连接到 linux 中,然后在终端直接运行相关程序即可。
debian sshd maunal 中的信息
X11 FORWARDING
If the ForwardX11 variable is set to “yes” (or see the description of the -X, -x, and -Y options above) and the user is using X11 (the
DISPLAY environment variable is set), the connection to the X11 display is automatically forwarded to the remote side in such a way that
any X11 programs started from the shell (or command) will go through the encrypted channel, and the connection to the real X server will
be made from the local machine. The user should not manually set DISPLAY. Forwarding of X11 connections can be configured on the com‐
mand line or in configuration files.
The DISPLAY value set by ssh will point to the server machine, but with a display number greater than zero. This is normal, and happens
because ssh creates a “proxy” X server on the server machine for forwarding the connections over the encrypted channel.
ssh will also automatically set up Xauthority data on the server machine. For this purpose, it will generate a random authorization
cookie, store it in Xauthority on the server, and verify that any forwarded connections carry this cookie and replace it by the real
cookie when the connection is opened. The real authentication cookie is never sent to the server machine (and no cookies are sent in
the plain).
If the ForwardAgent variable is set to “yes” (or see the description of the -A and -a options above) and the user is using an authenti‐
cation agent, the connection to the agent is automatically forwarded to the remote side.
注意事项
网上搜索到的一些博客中都提到要设置 DISPLAY 参数,实际测试发现设置了后反而不能正常工作。在我的 debian 机器上查看已经运行的 X11 程序的环境变量,发现普通用户 DISPLAY 变量的值为 localhost:10.0, root 用户的值为 localhost:11.0。
测试表明 ssh 会自动设置 DISPLAY 环境的值,用户不需要单独设置。同时 ssh 设置的值中 ip 并非目的 X11 server 机器的 ip,理解 X11 forwarding 实际是先本地转发到 6010 端口,然后通过已经建立的 ssh 隧道转发到 X11 server 机器上进行显示。
当设置 DISPLAY 为 192.168.44.33:0.0 时,运行 X11 client 程序会执行如下系统调用:
connect(3, {sa_family=AF_INET, sin_port=htons(6000), sin_addr=inet_addr("192.168.44.33")},
确认 xquartz 并不会监听 6000 端口,此 connect 会超时失败,程序终止。在 Mac 上查看到 xquartz 启动参数如下:
/opt/X11/bin/Xquartz :0 -nolisten tcp -iglx -auth /Users/longyu/.serverauth.2603
猜测是 -nolisten tcp 参数的影响,修改 /opt/X11/bin/startx 中的逻辑启用 listen tcp 参数,直接执行 startx 命令,能够看到如下两条监听信息:
X11.bin 3431 longyu 9u IPv4 0xf75fbac47759271d 0t0 TCP *:6000 (LISTEN)
X11.bin 3431 longyu 12u IPv6 0xf75fbac947417cd5 0t0 TCP *:6000 (LISTEN)
此时仍旧设置了 DISPLAY 后 connect 6000 端口成功,随后 connect ip+6010 地址会失败,而 X11.bin 并不会监听 6010 端口,这个 6010 端口网上搜索到可能与 sshd 配置中的 X11DisplayOffset 10 配置有关,暂且打住。