我正在研究如何编写一个简单的基于 X11 unix-socket 的代理。我尝试了各种标准应用程序,并编写了自己的代码,但得到的结果差异很大。出了什么问题?
背景:我的最终目标是为了安全目的实现一个过滤 X11 代理,作为 xpra 和 xephyr 的轻量级替代品。看使用 Firejail 对 Firefox 浏览器进行沙箱处理有关 X11 漏洞的更多信息。
尝试
ssh localhost -X
我们了解并喜爱
ssh
X 转发。效果很好。ssh localhost -R /tmp/.X11-unix/Xnnn:/tmp/.X11-unix/X0
ssh
还可以转发套接字,并且 X 转发可以很好地处理它们。 (注意,您必须手动设置DISPLAY=:nnn
。)socat UNIX-LISTEN:/tmp/.X11-unix/Xnnn,fork UNIX-CONNECT:/tmp/.X11-unix/X0
socat
是一个本质上被设计为套接字代理的程序。然而通过它转发 X11 是不稳定的。 (注意,您必须手动设置DISPLAY=:nnn
。)socat UNIX-LISTEN:/tmp/.X11-unix/Xnnn UNIX-CONNECT:/tmp/.X11-unix/X0
它不需要
socat
在每个连接上进行分叉,而是可以只处理一个连接,然后终止。这允许 Firefox 工作,但不允许 Okular 或 keepassx 工作,并且在任何情况下都不实用,因为我需要一个持续运行的代理-
该应用程序为每个传入连接启动一个线程,并且仅将数据从代理套接字转发到服务器套接字,反之亦然。结果是一样的
socat fork
我编写的一个 Haskell 应用程序用于转发套接字,但只接受一个连接
与上面相同,只是它只接受一个连接。结果与
socat
no相同fork
,值得怀疑。
结果
我使用基本 X 应用程序(xterm
、、、、)、Firefox、Firefox测试了每个代理尝试xeyes
,xclock
xev
奥库拉和keepassx
。结果如下,有效时为✓,无效时为空白。对于不起作用的组合,应用程序只是“挂起”,没有输出,也没有任何迹象表明它正在执行任何操作。
ssh -X |
ssh -R |
socat fork |
socat 不fork |
哈斯克尔应用程序 | Haskell 应用程序,只有一个接受 | |
---|---|---|---|---|---|---|
基本X | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
火狐浏览器 | ✓ | ✓ | ✓ | ✓ | ||
奥库拉 | ✓ | ✓ | ||||
保持密码 | ✓ | ✓ |
问题
最大的问题是为什么行不通socat
而ssh
行?socat
唯一的工作是转发套接字,所以我很惊讶它的性能不如ssh
,此外它还有其他工作。我发现openssh的socket转发的来源socat
但这对我来说太复杂了,无法理解为什么它会以不可行的方式起作用。
我是否应该在套接字代理应用程序中编写一些我可能错过的明显内容?
是否有一个简单的(几百行)套接字代理的示例源代码可以成功转发 X 我可以学习? openssh 的代码库太大了。
当 Firefox 停止接受新连接时,为什么socat
我的应用程序突然开始与 Firefox 一起使用?
答案1
一个或多个 X 扩展(我认为 DRI 是其中之一)通过 unix 域套接字发送文件描述符,并且使用send
/recv
不会代理这些文件描述符。相反,您必须使用sendmsg
/recvmsg
并发送所有 CMsg 数据。
这很好地解释了您发现的结果。我不认为socat
代理文件描述符(其代码中没有调用sendmsg
),并且 haskell 应用程序也不代理。我不明白为什么ssh -R
有效。
当我尝试编写本地 X11 代理时,我自己也被这个问题难住了。我最终通过弄乱它的源代码来解决这个问题,xtrace
它成功地代理了unix连接。