我可以像 tcpdump 一样监控本地 unix 域套接字吗?

我可以像 tcpdump 一样监控本地 unix 域套接字吗?

我想在不干扰原始连接的情况下监视unix套接字上的响应,并将它们传送到脚本进行处理。

我知道如何使用 tcpdump 执行 tcp 连接,但我似乎找不到本地 unix 套接字的解决方案。

这可能吗?

答案1

有人声称可以通过创建一个应用程序来做到这一点,该应用程序充当两个套接字之间的网关并记录所有流动的数据。因此,您无法点击套接字,但如果您可以重新启动服务并对其进行调整以使用此应用程序,您将能够看到所有流量。

以下是该帖子的链接:Unix 套接字嗅探器

还有另一种方法需要您找到附加到套接字的进程 ID,然后使用 lsof 找到套接字的文件描述符,然后使用 strace 点击文件描述符。

如果您可以停止使用套接字的任何客户端/服务器并重新配置它,我会始终推荐第一种方法,第二种方法比较棘手并且需要您点击当前进程,这在某些应用程序上可能会导致它崩溃。

希望有人能用另一种方式启发我们:)

祝你好运

答案2

您可以使用socat。

sudo mv /path/to/sock /path/to/sock.original
sudo socat -t100 -x -v UNIX-LISTEN:/path/to/sock,mode=777,reuseaddr,fork UNIX-CONNECT:/path/to/sock.original

上面发生了什么:首先将原始套接字移动到 sock.original。Socat 在原始位置创建一个新的套接字(“UNIX-LISTEN”),并将所有内容转发到原始位置(“UNIX-connect”)。-v 告诉 socat 还将输出打印到 STDERR。

答案3

您也可以尝试在套接字两侧的某个进程上使用 strace,因为这可以让您查看写入/读取的内容。我发现在我的生产环境中,我没有 socat,但有 strace。

对于任何有用的目的来说,将 -s 设置为大值是必须的。

答案4

虽然有点晚了,但我修改了一个 systemtap 脚本,它可以为无法转发来自监听进程的套接字流量的人执行此操作。使用时请自担风险,我只针对 Red Hat Enterprise Linux 7 进行了测试,但我们引用的结构是通用的,并且(希望)不会发生太大变化:

/*
 * watch_unix_socket.stp
 *
 * This is a simply more modern version of the script found here:
 * https://sourceware.org/systemtap/wiki/WSunixSockets
 *
 * The first argument is the location of the file descriptor for a UNIX socket.
 * To find this address, for example, for the Docker socket run:
 *
 * # lsof 2>&1 | awk '/docker.sock/ {print $7}' | grep -v '0t0' | sort -u
 * 0xffff8ed0b4eb1800
 *
 * And use that address to run this systemtap script:
 * 
 * # stap watch_unix_socket.stp 0xffff8ed0b4eb1800
 */

probe begin {
    printf("Watching input into socket 0x%x...\n", $1);
}

probe kernel.function("unix_stream_sendmsg") {
    if ($sock->sk != $1) {
        printf("%d %s is accessing %p\n", pid(), execname(), $sock->sk);
        printf("====================\n");

        len = 0
        for (i = 0; i < $msg->msg_iovlen; i++) {
            len += $msg->msg_iov[i]->iov_len;
        }
    
        printf("%d [", len);
        for (i = 0; i < $msg->msg_iovlen; i++) {
            printf("%s", user_string_n($msg->msg_iov[i]->iov_base, $msg->msg_iov[i]->iov_len));
        }

        printf("] [");
        for (i = 0; i < $msg->msg_iovlen; i++) {
            printf("%s", user_string_n($msg->msg_iov[i]->iov_base, $msg->msg_iov[i]->iov_len));
        }

        printf("]\n\n");
    }
}

我会持续更新我的页面上的 Github Gist

相关内容