良好的Linux TCP/IP监控工具,不使用';不需要根访问权限?

良好的Linux TCP/IP监控工具,不使用';不需要根访问权限?,linux,debugging,sockets,networking,tcp,Linux,Debugging,Sockets,Networking,Tcp,我想为我正在增强的程序调试TCP/IP交互。我没有root访问权限(因此没有tcpdump等),但该应用程序在我自己的id下运行。我可以使用strace等工具拦截系统调用,但是否有值得推荐的替代方案?如果是,为什么-他们提供什么?首选命令行(我的电脑上现在没有安装X服务器:-(),但对GUI也很好奇 理想情况下,它会这样说: app listening on port <portA> app listening on port <portB> client conne

我想为我正在增强的程序调试TCP/IP交互。我没有root访问权限(因此没有tcpdump等),但该应用程序在我自己的id下运行。我可以使用strace等工具拦截系统调用,但是否有值得推荐的替代方案?如果是,为什么-他们提供什么?首选命令行(我的电脑上现在没有安装X服务器:-(),但对GUI也很好奇

理想情况下,它会这样说:

app listening on port <portA> app listening on port <portB> client connection #1 accepted on listening port <portA> to local port <portC> from remote <hostX:portXA> app sent #1 <number> bytes "<data dump...>" app received from client #1 <number> bytes "<data dump...>" client #1 closed connection 应用程序侦听端口 应用程序侦听端口 侦听端口到本地端口的客户端连接#1已接受 远在 已发送应用程序#1字节“” 从客户端接收的应用程序#1字节“” 客户端#1关闭连接 我自己会把一个拼凑在一起,但太多的轮子无法重新创造

提前谢谢

更新:paulrubel和ypnos都提出了非常有用的建议…(希望我能接受这两个答案,因为它们是不同的,同样好)。实现Paul建议的LD_预加载拦截的代码如下:

// TCP comms trace library
//   as per http://www.jayconrod.com/cgi/view_post.py?23

#define _GNU_SOURCE

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <dlfcn.h>


typedef ssize_t (*Recv)(int s, void* buf, size_t len, int flags);

ssize_t recv(int s, void* buf, size_t len, int flags)
{
    static Recv real = NULL;

    if (!real)
        real = (Recv)dlsym(RTLD_NEXT, "recv");

    fprintf(stderr, "> recv(s '%d', buf %p, len %lld, flags %d)...\n",
            s, buf, len, flags);
    ssize_t result = real(s, buf, len, flags);
    fprintf(stderr, "< recv(s '%d', buf %p, len %lld, flags %d) return %lld\n",
            s, buf, len, flags, result);

    return result;
}

typedef ssize_t (*Send)(int s, const void* buf, size_t len, int flags);

ssize_t send(int s, const void* buf, size_t len, int flags)
{
    static Send real = NULL;

    if (!real)
        real = (Send)dlsym(RTLD_NEXT, "send");

    fprintf(stderr, "> send(s '%d', buf %p, len %lld, flags %d)...\n",
            s, buf, len, flags);
    ssize_t result = real(s, buf, len, flags);
    fprintf(stderr, "< recv(s '%d', buf %p, len %lld, flags %d) return %lld\n",
            s, buf, len, flags, result);

    return result;
}

typedef int (*Connect)(int s, const struct sockaddr* serv_addr, socklen_t addrlen);

int connect(int s, const struct sockaddr* serv_addr, socklen_t addrlen)
{
    static Connect real = NULL;

    if (!real)
        real = (Connect)dlsym(RTLD_NEXT, "connect");

    fprintf(stderr, "> connect(s %d, sockaddr %p, addrlen %d)\n",
            s, (void*)serv_addr, addrlen);
    int result = real(s, serv_addr, addrlen);
    fprintf(stderr, "< connect(s %d, sockaddr %p, addrlen %d) return %d\n",
            s, (void*)serv_addr, addrlen, result);

    return result;
}

typedef int (*Accept)(int s, const struct sockaddr* serv_addr, socklen_t* addrlen);

int accept(int s, struct sockaddr* serv_addr, socklen_t* addrlen)
{
    static Accept real = NULL;

    if (!real)
        real = (Accept)dlsym(RTLD_NEXT, "accept");

    fprintf(stderr, "> accept(s %d, sockaddr %p, addrlen %p)\n",
            s, (void*)serv_addr, addrlen);
    int result = real(s, serv_addr, addrlen);
    fprintf(stderr, "< accept(s %d, sockaddr %p, addrlen %p -> %d) return %d\n",
            s, (void*)serv_addr, addrlen, *addrlen, result);

    return result;
}
//TCP通信跟踪库
//依照http://www.jayconrod.com/cgi/view_post.py?23
#定义GNU源
#包括
#包括
#包括
#包括
typedef ssize_t(*Recv)(int s,void*buf,size_t len,int标志);
ssize\u t recv(整数s、空*小单位、大小长度、整数标志)
{
静态Recv real=NULL;
如果(!real)
real=(Recv)dlsym(RTLD_NEXT,“Recv”);
fprintf(stderr,“>recv(s'%d',buf%p,len%lld,flags%d)…\n”,
s、 buf、len、旗帜);
ssize_t结果=实(s、buf、len、标志);
fprintf(stderr,“send(s'%d',buf%p,len%lld,flags%d)…\n”,
s、 buf、len、旗帜);
ssize_t结果=实(s、buf、len、标志);
fprintf(stderr,“connect(s%d,sockaddr%p,addrlen%d)\n”,
s、 (无效*)服务地址,地址);
int result=real(s,serv_addr,addrlen);
fprintf(stderr,“接受(s%d,sockaddr%p,addrlen%p)\n”,
s、 (无效*)服务地址,地址);
int result=real(s,serv_addr,addrlen);
fprintf(stderr,“%d)返回%d\n”,
s、 (无效*)服务地址,地址,*地址,结果);
返回结果;
}

即使您使用与受害者程序相同的用户id运行,也无法拦截套接字连接

你需要做的是

  • 让您自己的程序打印插座号等

  • 让您的程序连接到另一个程序,该程序实际上通过隧道连接到真正的目的地。在那里,您可以转储所有发送/接收的数据


  • 有一个想法,可能有点像打苍蝇的大锤,就是使用。基本上,你包装了一个系统调用,连接并发送,这对你来说似乎是一个很好的起点,并记录在将数据传递给真正的调用之前看到的参数。

    2是个好主意,谢谢。1在我的特殊情况下,它太复杂了-整个想法是为了得到一些数据与程序无关的东西,因为我不太信任它。更一般地说,像strace和gdb这样的程序作为控制进程启动(或附加到正在运行的程序),并且似乎做类似的事情,所以我怀疑你关于“无法拦截”的说法是否正确。感谢您的帮助和想法。在程序调用write()之前,您可以告诉调试器查看输出缓冲区变量,如果这也算是拦截。但是,除此之外,您在内核空间中,如果不是root,则无法调试内核空间。strace只在内核空间的边界上运行,并且在内核中对此有特定的支持。如果您找到任何用于“套接字调试”的内核接口,告诉我。我所知道的都没有。我非常喜欢tcpdump,所以我有以下建议:从另一台机器上进行交互,在那里你可以运行tcpdump(甚至wireshark),或者要求通过sudo运行tcpdump。@stefaanv:很好的建议,但是在一家(大银行)公司环境我有Buckley的机会在任何共享框上都能找到它…如果有人愚蠢到可以ftp到该框上,那么就很容易嗅探密码。如果我有自己的UNIX工作站,那么可能会有机会。这是一个非常好的建议。我实现了它(虽然很长,但会增加上面的问题).仅供参考/我已决定接受ypnos的回答,因为他获得的选票较少,所以我会公平对待你们的帮助。我已经向你们两位表示感谢,并相信你们就是上面的代码。再次感谢。