Хорошие инструменты мониторинга TCP / IP в Linux, которым не нужен root-доступ? - PullRequest
3 голосов
/ 26 августа 2010

Я хочу отлаживать взаимодействия TCP / IP для программы, которую я улучшаю.У меня нет root-доступа (поэтому нет tcpdump и т. Д.), Но приложение работает под моим собственным идентификатором.Я мог бы использовать, например, strace для перехвата системных вызовов, но есть ли альтернативы, которые стоит рекомендовать по этому поводу?Если так, почему - что они предлагают?Предпочтительная командная строка (на моем ПК сейчас не установлен X-сервер :-(), но также интересны графические интерфейсы.

В идеале это будет выглядеть примерно так:

    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 сделали очень полезные предложения ... (хотелось бы, чтобы я принялоба ответа, поскольку они различны и одинаково хороши.) Код, реализующий предложенный Полом перехват LD_PRELOAD, следует:

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

Ответы [ 2 ]

5 голосов
/ 26 августа 2010

Одной из идей, и может быть немного кувалдой, чтобы решить проблему мухи, является использование library interpositioning .По сути, вы оборачиваете системный вызов, подключаетесь и отправляете, чтобы показаться вам хорошей отправной точкой, и записываете параметры, которые вы видели перед передачей данных в реальный вызов.

2 голосов
/ 26 августа 2010

Невозможно перехватить соединения с сокетом, даже если вы используете тот же идентификатор пользователя, что и у программы-жертвы.

Что вам нужно сделать, это

  1. Позвольте вашей собственной программе печатать номера сокетов и т. Д.

  2. Позвольте вашей программе подключиться к другой программе, которая фактически туннелирует подключение к реальному месту назначения. Там вы можете сбросить все данные, отправленные / полученные.

...