在 Linux 下将 TCP 流量重定向到 UNIX 域套接字

Posted

技术标签:

【中文标题】在 Linux 下将 TCP 流量重定向到 UNIX 域套接字【英文标题】:Redirecting TCP-traffic to a UNIX domain socket under Linux 【发布时间】:2011-01-10 02:39:44 【问题描述】:

假设有一个旧版 Linux 应用程序正在侦听 UNIX 域套接字 /tmp/foo

除了通过 UNIX 域套接字机制与这个遗留应用程序通信之外,我还希望能够通过端口 1234 上的 TCP 连接连接到它。

绑定到 TCP 端口 1234 然后将所有传入连接重定向到 UNIX 域套接字/tmp/foo 的最简单方法是什么?

【问题讨论】:

【参考方案1】:

原来socat 可以用来实现这一点:

socat TCP-LISTEN:1234,reuseaddr,fork UNIX-CLIENT:/tmp/foo

并增加了一点安全性:

socat TCP-LISTEN:1234,bind=127.0.0.1,reuseaddr,fork,su=nobody,range=127.0.0.0/8 UNIX-CLIENT:/tmp/foo

这些示例已经过测试并按预期工作。

【讨论】:

socat,netcat,无论哪种方式。您甚至可以将stunnel 包裹起来以增加复杂性! 如果有人想用它来共享 docker 套接字,他应该删除 su=nobody 部分 要共享 docker 套接字,只需通过传递 -H tcp://127.0.0.1:4321 告诉 Docker 守护进程侦听本地端口(请注意,它允许任何可以打开到 @987654327 的连接的人访问 docker 守护进程@. 没有 uid/gid 检查或任何东西,但 netcat/socat 方法也是如此) @swordofpain 你知道如何用 Docker for Mac 做到这一点吗?我启用了“登录时自动启动 Docker”,并且首选项中似乎没有选项可以监听套接字而不是 Unix 套接字。 AFAIK,Docker for Mac 虚拟化了一个 linux 内核来做容器的工作。 OSX 的内核并没有涉及,真的。这意味着 docker 守护进程正在 VM 内运行,并且必须在那里完成配置。尽管可能他们提供的任何前端都可能已经通过 API 与守护进程对话,这意味着应该已经有一个监听套接字。主要区别在于它不会在 localhost 上侦听,而是在 VM 的虚拟网络接口上侦听,您必须在其中找到 IP 地址。希望这会有所帮助。【参考方案2】:

最简单?可能是 Netcat(又名nc):

nc -l 1234 | nc -U /tmp/foo

第一个命令在端口 1234 上侦听传入连接,并将结果数据通过管道传输到第二个命令。第二个连接到 Unix 域套接字/tmp/foo,并将其输入写入该套接字。请注意,这只会接受一个连接,并在该连接断开后立即退出。如果您想继续侦听更多连接,请使用-k 选项:

nc -lk 1234 | nc -U /tmp/foo

您可以通过在一个终端中为该套接字设置一个侦听器来测试它是否有效:

nc -lUk /tmp/foo

并在另一个中写给它:

nc localhost 1234

socat 和recommended by knorv 一样,功能更强大,但使用起来更复杂。

【讨论】:

好像ubuntu下的nc(量子)不支持unix套接字:( @gucki 真的吗?您没有nc -U 选项吗?我没有要测试的 Quantal 机器,但在 Precise nc 上有 -U 选项,我在评论中所说的效果很好。你试过我写的吗?如果您发现nc 不适合您,我建议您尝试socat;它可以比nc 做更多的事情,对它的工作方式进行更细粒度的控制,但要弄清楚如何使用它有点复杂。 是的,我刚刚再次测试(netcat 1.10-40):nc -l 1234 | nc -U /tmp/foo 给出了nc: invalid option -- 'U'nc -h for helpsocat 工作正常 :) @gucki 看起来 Ubuntu 上有两个 nc 包。 netcat-traditionalnetcat-openbsdnetcat-openbsd 是我安装的,似乎比netcat-traditional 有更多的功能。您可以同时安装它们,ncnetcat 符号链接到一个或另一个。 这种方法的问题是生成的管道是单向的。如果我们期望监听 unix 域套接字的进程得到响应,那么通过 TCP 套接字进行通信的唯一方法是socat,它将把响应转发回给我们。【参考方案3】:

您应该能够绑定到 TCP 1234,为 /tmp/foo 获取套接字 fd,并使用 select 调用来“侦听”1234 和 /tmp/foo 上的数据。任何写入 1234 的数据,您都重写为 /tmp/foo,反之亦然。

您现在充当代理并来回传输数据。

这里有一个可能有帮助的网页:http://osr507doc.sco.com/en/netguide/dusockC.io_multiplexing.html

【讨论】:

【参考方案4】:

除了@knorv 的answer:加上xinetd,它可以像守护进程一样工作

# cat /etc/xined.d/mysrv
service mysrv

 disable = no
 type = UNLISTED
 socket_type = stream
 protocol = tcp
 wait = no
 server = /usr/bin/socat
 server_args = STDIN UNIX-CLIENT:/tmp/mysocket.sock
 bind = 127.0.0.1
 port = 1234

【讨论】:

【参考方案5】:

没有尝试过:但看起来 'lighttpd' 可以为你做到这一点:

http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxyCore

【讨论】:

不幸的是 lighttpd 对于发帖者想要的东西来说太过分了。 这真的适用于任意 TCP 而不仅仅是 HTTP 吗?

以上是关于在 Linux 下将 TCP 流量重定向到 UNIX 域套接字的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 下将 domain.com 重定向到 WWW.domain.com?

如何在不重新加载页面的情况下将用户重定向到 redux saga 上的另一个页面

在没有 SSL 的情况下将 https 重定向到 http - IIS 7

在不使用经典 RPyC 的情况下将 RPyC 的标准输出重定向到本地客户端

如何在不重新加载页面的情况下将服务器端重定向到其他页面并仍将 URL 保留在 Nextjs 应用程序中?

Linux:rinetd的安装部署以及端口转发