我在一个嵌入式平台(mipsel架构,Linux 2.6内核)上,我需要监控两个闭源进程(路由器固件)之间的IPC,以便对某个事件(由于DSL重新连接而导致的动态IP更改)做出反应。到目前为止,我通过strace发现,只要IP发生变化,DSL守护进程就会向绑定到特定文件名的UNIX域套接字中写入一条特殊消息。此消息被另一个守护进程使用。
现在这是我的需求:我想监视通过特定UNIX域套接字的数据流,并在检测到某个消息时触发一个事件(调用shell脚本)。我尝试用inotify监视文件名,但它对套接字文件不起作用。我知道我可以一直运行strace,过滤它的输出并对过滤后的日志文件中的变化做出反应,但这将是一个过于沉重的解决方案,因为strace确实会减慢系统的速度。我也知道我可以通过cron轮询IP地址更改,但我想要一个看门狗,而不是轮询解决方案。我感兴趣的是,是否有一种工具可以专门监视UNIX域套接字,并对以预定义方向流过的特定消息作出反应。我想象类似于inotifywait的东西,即工具应该等待某个事件,然后退出,因此我可以对该事件做出反应并循环再次启动工具,等待下一个相同类型的事件。
是否有任何现有的Linux工具能够做到这一点?或者有一些简单的C代码,我可以在我的平台上编译一个独立的二进制文件(uClibc,而不是glibc)?我不是一个C专家,但能够运行一个makefile。使用二进制从shell是没有问题的,我知道足够的shell编程。
我处理这个话题已经有一段时间了,实际上并没有去测试我的一个熟人,Denys Vlasenko, Busybox的维护者,几个月前向我提出了一个解决方案。因为我刚刚查看了我在StackOverflow上的账户,又看到了这个问题,让我和你分享一下他的见解。也许它对某人有帮助:
我可以提出一个相对简单的方法:我假设你有一个正在运行的服务器应用程序,它打开了一个Unix域监听套接字(比如,
/tmp/some.socket
),客户端程序连接到它并与服务器通信。
- rename
/tmp/some.socket
->/tmp/some.socket1
- 创建一个新的套接字/tmp/some.socket
- 监听新的客户端连接
- 对于每个这样的连接,打开另一个连接到
/tmp/some.socket1
到原始服务器进程- 通过产生的套接字对(这样做的代码与telnetd服务器所做的非常相似)泵送数据(客户机<->服务器),直到从任何一方退出。
当您在泵送数据时,可以很容易地查看它,保存它,甚至可以在需要时修改它。
缺点是每次重新启动原始服务器程序时都需要重新启动此嗅探程序。
这与Celada的回答相似。也要感谢他!不过,丹尼斯的回答更具体一些。
我反问:
这听起来很粗糙,是的,因为重新启动的必要性,但可行。我不是一个C程序员,我一直想知道如果你知道a命令行工具,它可以进行传递和协议处理或基于事件的触发为我工作。我们项目组的一个人进来了我想谁能破解一点C二进制,但我不确定他是否喜欢做这件事。如果有预制件,我更喜欢。它能甚至可以使用BusyBox applet(组合)来完成?
丹尼斯又回答:
您需要使用
CONFIG_FEATURE_UNIX_LOCAL=y
构建busybox。作为拦截服务器运行如下命令:
busybox tcpsvd -vvvE local:/tmp/socket 0 ./script.sh
script.sh是一个简单的直通连接给"原始服务器":
#!/bin/sh busybox nc -o /tmp/hexdump.$$ local:/tmp/socket1 0
作为一个例子,我添加了十六进制日志到文件(
-o FILE
选项)。通过运行模拟的"原始服务器"来测试它:
busybox tcpsvd -vvvE local:/tmp/socket1 0 sh -c 'echo PID:$$'
和连接到"拦截服务器":
echo Hello world | busybox nc local:/tmp/socket 0
您应该看到"PID:19094"消息,并且有一个新的
/tmp/hexdump.19093
文件使用转储的数据。两个tcpsvd进程也应该打印一些日志(它们在-vvv
verbose下运行)。如果需要更复杂的处理,请替换
script.sh
中的nc调用使用自定义程序。
我认为没有任何东西可以让您清晰地嗅探UNIX套接字流量。以下是一些选项:
- 安排发送方进程连接到您正在监听的的另一个套接字。还可以作为客户端连接到原始套接字。在接收数据时,注意您想要注意的数据,并将所有内容传递给原始套接字。
- 使用netlink套接字(
RTM_NEWADDR
,RTM_NEWLINK
等)监视系统的IP地址变化。 - 将
ip monitor
作为外部进程运行,当它写关于添加的&在标准输出中删除IP地址。