2010-08-26 63 views
3

我想为我正在增强的程序调试TCP/IP交互。我没有root权限(所以没有tcpdump等),但该应用程序运行在我自己的ID下。我可以使用例如strace来拦截系统调用,但是还有其他值得推荐的选择吗?如果是这样,为什么 - 他们提供什么? 。者优先命令行(安装在我的电脑现在:-(没有X服务器),但好奇的GUI太好的Linux TCP/IP监视工具不需要root权限?

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

 
    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 

会刮伤一个一起自己,但太多的车轮重新定位为是....

在此先感谢

更新:既paulrubel和ypnos取得了非常有益的建议......(希望我能接受两个答案,因为他们是不同的同样好)。执行Paul建议的LD_PRELO的代码AD拦截如下:

// 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; 
} 
+0

我非常喜欢tcpdump,所以我有以下建议:从可以运行tcpdump(甚至wireshark)的其他机器进行交互,或者要求能够通过sudo运行tcpdump。 – stefaanv 2010-08-27 07:35:07

+0

@stefaanv:很好的建议,但是在一家大银行的公司环境中,我有可能在任何共享的盒子上获得这个机会。如果有人傻到可以在盒子上ftp,就太容易嗅探密码。希望我有我自己的UNIX工作站,那么也许会有机会。 – 2010-08-27 09:31:17

回答

2

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

你需要做的是

  1. 让自己的程序打印插座数量等

  2. 让你的程序连接到其实隧道真正的目的地的连接另一个程序。在那里你可以转储所有发送/接收的数据。

+0

2是个好主意,谢谢。 1在我的特殊情况下太复杂了 - 整个想法是让程序独立于程序,因为我不太相信它。更一般地说,像strace和gdb这样的程序作为控制进程启动(或者附加到正在运行的程序),并且似乎也做了类似的事情,所以我怀疑你说“没有办法拦截” 。感谢您的帮助和想法。 – 2010-08-26 10:56:49

+1

那么你可以随时告诉你的调试器在你的程序调用write()之前观察输出缓冲区变量,如果这也算作你的拦截器。然而,除了这个调用之外,你在内核空间中,你不能以root身份调试内核空间。 strace只是在内核空间的边界运行,并且在内核方面有特定的支持。如果你发现任何“套接字调试”的内核接口,告诉我。没有我知道的。 – ypnos 2010-08-26 12:38:36

5

一个想法,它可能有点大锤扑打一只苍蝇的解决方案,就是使用libraryinterpositioning。你基本上包装了一个系统调用,connect和sendto对你来说似乎是一个很好的起点,并且在将数据传递给真正的调用之前记录看到的参数。

+0

这是一个非常好的建议。我实现了它(尽管时间很长,但会增加上述问题)。 – 2010-08-27 09:45:01

+0

只是供参考/已决定接受ypnos的答案,因为他得到的选票较少,所以它甚至会出现问题,因为我同样重视您的帮助。我已经为你们+1了,并且重申了上面的代码。非常感谢。 – 2010-08-27 10:05:26