X11转发在docker

时间:2017-06-08 07:33:49

标签: authentication docker x11-forwarding

首先:我已经阅读了关于SO的类似问题的答案,但没有一个有效。

情况:

  • 带有GUI的App正在Arch Linux下的docker容器(CentOS 7.1)中运行。 (机器A)
  • 机器A连接有显示器。
  • 我想通过Arch Linux客户端计算机上的X11转发访问此GUI。 (机器B)

什么有效:

  • GUI在机器A上本地工作(将/tmp/.X11-unix安装在Docker容器中)。
  • X11转发任何在docker外部运行的应用程序(X11转发已设置并正常运行,以便非docker使用)。
  • 我甚至可以在远程登录时切换用户,将.Xauthority文件复制到其他用户,X11转发也可以。

一些设置信息:

  • Docker网络已经“桥接”。
  • 容器可以到达主机(防火墙已打开)。
  • DISPLAY变量在容器中设置(到host-ip-addr:10.0,因为sshd正在侦听的TCP端口6010)。
  • X转发端口(6010)的数据包从容器到达主机(tcpdump已检查)。

什么行不通:

  • 转发Docker应用程序的X11
  • 错误:

X11 connection rejected because of wrong authentication.

xterm: Xt error: Can't open display: host-ip-addr:10.0

我尝试的事情:

  • 在计算机B上使用ssh -Y选项启动客户端ssh
  • "X11ForwardTrusted yes"放在机器B上的ssh_config中
  • 机器B上
  • xhost +(允许任何客户连接)
  • Host *放在机器B上的ssh_config中
  • X11UseLocalhost no放在机器A的sshd_config中(允许非本地主机客户端)
  • 在机器A的登录用户中使用xauth add在容器中添加X身份验证令牌
  • 只需将.Xauthority文件从工作用户复制到容器
  • 即可
  • 使shure .Xauthority文件具有正确的权限和所有者

我怎样才能禁用所有X安全资料并使其正常工作?

甚至更好:我怎样才能让它与安全性一起工作?

是否至少有一种方法可以启用大量调试以查看问题的确切位置?

5 个答案:

答案 0 :(得分:6)

好的,事情就是这样:

1)登录远程计算机

2)检查使用echo $DISPLAY

设置的显示

3)运行xauth list

4)复制与DISPLAY

对应的行

5)输入您的泊坞容器

6)xauth add <the line you copied> *

7)使用export DISPLAY=<ip-to-host>:<no-of-display>

设置DISPLAY

*到目前为止还不错?

这不是什么新鲜事......但是这是扭曲: 由xauth list为登录用户打印的行看起来像这样(在我的情况下):

<hostname-of-machine>/unix:<no-of-display> MIT-MAGIC-COOKIE-1 <some number here>

因为我使用桥接docker设置,X转发端口不在本地侦听,因为sshd没有在容器中运行。将上面的行更改为:

<ip-of-host>:<no-of-display> MIT-MAGIC-COOKIE-1 <some number here>

实质上:删除/unix部分。

<ip-of-host>是运行sshd的IP地址。

如上所述设置DISPLAY变量。

所以错误是环境变量中的DISPLAY名称与xauth list / .Xauthority文件中的条目“不相同”,客户端因此无法正确验证

我切换回不受信任的X11转发设置。

然而,sshd_config文件中的X11UseLocalhost no设置很重要,因为接收连接将来自“不同”的机器(docker容器)。

答案 1 :(得分:1)

非常感谢@ Lazarus535
我发现对我来说,将以下内容添加到我的docker命令中是可行的:
--volume="$HOME/.Xauthority:/root/.Xauthority:rw"
我发现了这个窍门here
编辑:
正如拉撒路正确指出的那样,您还必须设置--net=host选项以使此工作有效。

答案 2 :(得分:1)

这在任何情况下均有效。

如果没有安装xhost。然后,在bash中

export DISPLAY=:0.0
xhost +local:docker

在此之后,使用docker run来运行您的-e DISPLAY=$DISPLAY命令(或您正在运行的任何docker命令)

答案 3 :(得分:0)

它通常通过https://stackoverflow.com/a/61060528/429476

起作用

但是,如果您使用与ssh -X使用的用户不同的用户身份运行docker到服务器中,然后复制Xauthority仅有助于卷映射文件。

示例-我与alex用户一起进入服务器。然后在su -root之后运行docker并收到此错误

X11 connection rejected because of wrong authentication.

复制.XAuthoirty文件并像https://stackoverflow.com/a/51209546/429476一样映射它后,就可以正常工作

cp /home/alex/.Xauthority .

docker run  -it --network=host --env DISPLAY=$DISPLAY  --privileged  \
 --volume="$HOME/.Xauthority:/root/.Xauthority:rw"  \
-v /tmp/.X11-unix:/tmp/.X11-unix --rm <dockerimage>

有关在此处https://unix.stackexchange.com/a/604284/121634

接线的更多详细信息

答案 4 :(得分:0)

一些澄清的评论。主机是A,本地机器是B

我编辑了这篇文章,以指出我认为理论上应该可行但尚未经过测试的东西,以及我知道可行的东西

以非交互方式运行 docker

如果您的 docker 不是交互式运行并运行 sshd,您可以使用 jumphosts 或 proxycommand 并指定要运行的 x11 客户端。您应该不要与容器共享您的 Xauthority 文件,并且共享 -e DISPLAY 可能对未来的 ssh 会话没有影响

由于您本质上有两个 sshd 服务器,因此以下任一服务器都可以立即使用

如果你的openssh-client版本大于7.3,可以使用下面的命令

ssh -X -J user-on-host@hostmachine,user-on-docker@dockercontainer xeyes

如果您的 openssh 客户端较旧,则语法改为 (谷歌说代理命令中不需要 -X,但我很怀疑)

ssh -X -o ProxyCommand="ssh -W %h:%p user-on-host@hostmachine" user-on-docker@dockermachine xeyes

或者 ssh -X 进入主机,然后 ssh -X 进入 docker。

在上述任何一种情况下,您都应该不要与容器共享 .Xauthority

在 ssh 会话中以交互方式运行 docker

最简单的方法是设置 --net=host 和 X11UseLocalhost yse。 如果您的 docker 正在运行 sshd,您可以在本地计算机上打开第二个 ssh -X 会话并使用上述 jumphost 方法。 如果您在 ssh 会话中启动它,您可以 -e DISPLAY=$DISPLAY 或在您进入时将其导出。如果您附加到未使用此行的现有容器,您可能必须将其导出。

将这些 docker args 用于 --net 主机和 x11uselocalhost 是 ssh -X 到主机

   -e DISPLAY=$DISPLAY
   -v $HOME/.Xauthority:/home/same-as-dash-u-user/.Xauthority
   -u user

接下来是对一切工作原理和其他尝试方法的解释

关于 Xauthority

ssh -X/-Y 在 hosts Xauthority 文件中设置会话密钥,然后设置监听端口,在该端口上放置使用会话密钥的 x11 代理,并将其转换为与上的密钥兼容你的本地机器。根据设计,.Xauthority 密钥在您的本地机器和主机之间会有所不同。如果您使用 jumphosts/proxycommand 主机和容器之间的密钥将再次彼此不同。如果您改为使用 ssh 隧道或直接 X11 连接,则必须与容器共享主机 Xauthority,在与容器共享 .Xauthority 的情况下,每个用户只能有一个活动会话,因为新会话将使通过修改主机 .Xauthority 使其仅适用于该会话的 ssh x11 代理

X11UserLocalhost 没有理论##

即使 X11UseLocalhost 没有导致 x 服务器侦听通配符地址,但使用 --net 主机我无法将容器显示重定向到 localhost:X.Y 其中 x 以及为什么来自主机 $DISPLAY

X11UseLocalhost 是的,很简单

如果您选择 X11UseLocalhost yes,则主机上的 DISPLAY 变量变为 localhost:X:Y,这会导致 ssh x11 代理仅侦听本地主机端口 x。

如果 X11UseLocalhost 为 no,则主机上的 DISPLAY 变量变为主机的主机名:X:Y,这会导致 xerver 侦听 0.0.0.0:6000+X 并导致 xclients 通过网络访问指定的主机名.

这是理论上的,我还没有访问远程主机上的 docker 来测试这个

但这是简单的方法。我们通过将 DISPLAY 变量重定向到始终为 localhost 来绕过它,并执行 docker 端口映射以将数据从容器上的 localhost:X+1.Y 移动到主机上的 localhost:XY,其中 ssh 正在等待转发 x 流量回到本地机器。 +1 使我们不知道运行 --net=host 或 --net=bridge 设置容器端口需要在 dockerfile 中指定公开并使用 -p 命令发布端口。

手动设置所有内容,无需 ssh -X

这仅适用于 --net 主机。这种方法无需 xauth 即可工作,因为我们直接通过管道连接到本地机器上的 unix 域套接字

ssh 到主机不带 -X

ssh -R6010:localhost:6010 user@host
start docker with -e DISPLAY=localhost:10.1 or export inside

在本地机器上的另一个终端

socat -d -d TCP-LISTEN:6010,fork UNIX-CONNECT:/tmp/.X11-unix/X0

在原始终端运行 xclients

如果容器是 net --bridged 并且您不能使用 docker 端口,请在容器上启用 sshd 并使用 jumphosts 方法