1 问题描述

首先说一下问题。

今天同事和我讨论了在内网穿透时无法使用x11的问题。具体是这样的,办公室有台服务器(docker容器)使用公司内网,在办公室中内网直接使用x11是可以的(如运行xclock)。从家里(外网)访问该服务器是使用ngrok内网穿透转发了ssh端口到云主机上,此时(也就是内网穿透)无法运行x11程序。

ngrok内网穿透
内网
公网
办公室服务器
云主机
办公室电脑
家里电脑

(我原先以为docker容器是无法使用x11程序的,但同事说是可以的,而且通过内网正常运行)

2 正常的情况

在 ssh 配置 x11 转发且生效后,查询本机的 DISPLAY(打卡MobaXterm直接有显示)
在这里插入图片描述

然后在linux上只有两个步骤:

# 设置 DISPLAY 环境变量
export DISPLAY=10.xx.xx.xx:0.0
# 运行 x11 程序
xclock

运行效果
在这里插入图片描述

3 问题思考

将服务器的x11程序界面转发到本地显示,必然是用了网络传输,可以使用 netstat 命令来看x11程序开启时新建了什么端口的连接
在这里插入图片描述
我开了两个x11应用(xclock和xedit),可以看到新增的两个都是到了本机的6000端口(xserver当DISPLAY为 ip:0.0 时使用的端口)上。

其次,设置 DISPLAY 时是直接使用IP,意味着X程序是直接连接的该IP,由于使用内网穿透时,服务器是无法直接连接到本机电脑的,所以使用netstat查看时状态一直都是SYN_SENT,无法建立连接。

那么,是否我将本地电脑的6000端口转发到服务器上,然后在服务器上设置DISPLAY 为 localhost:0.0,运行x11程序时就使用localhost的6000端口,而由于这个端口是转发本地电脑的,因此就相当于将数据转到了本机上。

4 问题解决

按以上思路,将本地6001端口转发到服务器,下图是使用MobaXterm的tunnel(测试时本机端口被其他程序占用了,这里以6001端口做示例)
在这里插入图片描述
开启转发后,即可运行x11程序

# 设置 DISPLAY 环境变量   1.0 对应端口 6001
export DISPLAY=localhost:1.0
# 运行 x11 程序
xclock

在这里插入图片描述

5 其他小记

  1. x11端口变更:默认 DISPLAY=IP:0.0 使用端口 6000,DISPLAY=IP:1.0 使用端口6001,以此类推
  2. docker 可以直接运行x11程序,之前一直误解以为在容器中无法运行,对X理解太浅。
  3. MobaXterm自带xserver,在运行时自动启动xserver。xshell、vscode不带xserver,需要通过其他工具先启动xserver后才能按以上方式运行x11程序。
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐