URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 5710
[ Назад ]

Исходное сообщение
"Послать tcp/ip пакет"

Отправлено queen , 13-Сен-06 18:43 
как мне послать пакет на локальный интерфейс,
суть в том что libpcap'ом я перехватил пакет, поменял там source IP и хочу теперь его отправить, как мне это сделать?

Содержание

Сообщения в этом обсуждении
"Послать tcp/ip пакет"
Отправлено chip , 14-Сен-06 12:00 
>как мне послать пакет на локальный интерфейс,
>суть в том что libpcap'ом я перехватил пакет, поменял там source IP
>и хочу теперь его отправить, как мне это сделать?

AFAIR, libpcap в некоторых модификациях может отправлять пакеты. Что мешает посмотреть исходные тексты схожих проектов?!

ps: изменить source IP мало, нужно пересчитать checksum.



"Послать tcp/ip пакет"
Отправлено queen , 14-Сен-06 16:31 
>>как мне послать пакет на локальный интерфейс,
>>суть в том что libpcap'ом я перехватил пакет, поменял там source IP
>>и хочу теперь его отправить, как мне это сделать?
>
>AFAIR, libpcap в некоторых модификациях может отправлять пакеты. Что мешает посмотреть исходные
>тексты схожих проектов?!
>
>ps: изменить source IP мало, нужно пересчитать checksum.


ну а вообще каким образом можно отправить ? без lipcap?


"Послать tcp/ip пакет"
Отправлено vic , 14-Сен-06 16:44 
>>>как мне послать пакет на локальный интерфейс,
>>>суть в том что libpcap'ом я перехватил пакет, поменял там source IP
>>>и хочу теперь его отправить, как мне это сделать?
>>
>>AFAIR, libpcap в некоторых модификациях может отправлять пакеты. Что мешает посмотреть исходные
>>тексты схожих проектов?!
>>
>>ps: изменить source IP мало, нужно пересчитать checksum.
>
>
>ну а вообще каким образом можно отправить ? без lipcap?

raw sockets


"Послать tcp/ip пакет"
Отправлено queen , 14-Сен-06 17:20 
>>ну а вообще каким образом можно отправить ? без lipcap?
>
>raw sockets

да что то не выходит...
пытаюсь отправить с sendto
Или ещё как можно?


"Послать tcp/ip пакет"
Отправлено vic , 14-Сен-06 17:39 
>>>ну а вообще каким образом можно отправить ? без lipcap?
>>
>>raw sockets
>
>да что то не выходит...
>пытаюсь отправить с sendto
>Или ещё как можно?

"Послать на локальный интерфейс" и "поменял Source IP". Не ясно что хотите в результате.
Если изменили source IP и пытаетесь отправить в lo этот пакет то кто его там будет ловить при dest IP не локальном (ведь не изменен)?

В общем
Если открыть raw socket и привязать (bind) к конкретному интерфейсу, то в этот интерфейс можно посылать хоть из /dev/urandom.

p.s.
iptables off/on ? :)


"Послать tcp/ip пакет"
Отправлено queen , 14-Сен-06 17:55 
>"Послать на локальный интерфейс" и "поменял Source IP". Не ясно что хотите
>в результате.
>Если изменили source IP и пытаетесь отправить в lo этот пакет то
>кто его там будет ловить при dest IP не локальном (ведь
>не изменен)?
>
>В общем
>Если открыть raw socket и привязать (bind) к конкретному интерфейсу, то в
>этот интерфейс можно посылать хоть из /dev/urandom.
>
>p.s.
>iptables off/on ? :)

объясню немного подробнее, вобщем так
С помощью libpcap ловлю пакет адресованный например на IP 192.168.1.1 порт 80 с IP 192.168.1.2
Меняю 192.168.1.2 на 192.168.1.3, как теперь мне отправить этот пакет не присоединяясь напрямую к 192.168.1.1?
тоесть отправить пакет в одну сторону


"Послать tcp/ip пакет"
Отправлено vic , 14-Сен-06 18:23 
>>"Послать на локальный интерфейс" и "поменял Source IP". Не ясно что хотите
>>в результате.
>>Если изменили source IP и пытаетесь отправить в lo этот пакет то
>>кто его там будет ловить при dest IP не локальном (ведь
>>не изменен)?
>>
>>В общем
>>Если открыть raw socket и привязать (bind) к конкретному интерфейсу, то в
>>этот интерфейс можно посылать хоть из /dev/urandom.
>>
>>p.s.
>>iptables off/on ? :)
>
>объясню немного подробнее, вобщем так
>С помощью libpcap ловлю пакет адресованный например на IP 192.168.1.1 порт 80
>с IP 192.168.1.2
>Меняю 192.168.1.2 на 192.168.1.3, как теперь мне отправить этот пакет не присоединяясь
>напрямую к 192.168.1.1?
>тоесть отправить пакет в одну сторону

думаю проще iptables настроить и не мучаться.


"Послать tcp/ip пакет"
Отправлено queen , 14-Сен-06 18:31 
>думаю проще iptables настроить и не мучаться.
во первых это freebsd и там ipfw
и iptables эту задачу не решит


"Послать tcp/ip пакет"
Отправлено vic , 14-Сен-06 18:45 
>>думаю проще iptables настроить и не мучаться.
>во первых это freebsd и там ipfw
Ok (а я подумал линух). Либо решить посредством (если возможно) ipfw, либо смотреть в сторону divert sockets.
Так как поймать пакет недостаточно, его (оригинал) еще надо не пустить дальше.

>и iptables эту задачу не решит
не пробовал, но судя по man'у извернуться можно.


"Послать tcp/ip пакет"
Отправлено queen , 14-Сен-06 18:53 
>>>думаю проще iptables настроить и не мучаться.
>>во первых это freebsd и там ipfw
>Ok (а я подумал линух). Либо решить посредством (если возможно) ipfw, либо
>смотреть в сторону divert sockets.
>Так как поймать пакет недостаточно, его (оригинал) еще надо не пустить дальше.
>
>
>>и iptables эту задачу не решит
>не пробовал, но судя по man'у извернуться можно.

тут ещё суть в том что пакет должен уйти только в одну сторону с изменённым IP адресом, и чтобы машина кому был отправлен этот пакет ответила на него
у меня проблема возникает при создании raw_sock, sendto не отправляет пакет данных, видимо там нужно что то ещё обработать, я просто уже запутался :)


"Послать tcp/ip пакет"
Отправлено Alexey , 14-Сен-06 20:56 
>>>>думаю проще iptables настроить и не мучаться.
>>>во первых это freebsd и там ipfw
>>Ok (а я подумал линух). Либо решить посредством (если возможно) ipfw, либо
>>смотреть в сторону divert sockets.
>>Так как поймать пакет недостаточно, его (оригинал) еще надо не пустить дальше.
>>
>>
>>>и iptables эту задачу не решит
>>не пробовал, но судя по man'у извернуться можно.
>
>тут ещё суть в том что пакет должен уйти только в одну
>сторону с изменённым IP адресом, и чтобы машина кому был отправлен
>этот пакет ответила на него
>у меня проблема возникает при создании raw_sock, sendto не отправляет пакет данных,
>видимо там нужно что то ещё обработать, я просто уже запутался
>:)
А ipfw fwd не помогает? (только надо фрю до 5 ветки брать - в 5-ой глюк именно в этой функции, мне победить до сих пор не удалось - придется делать dowgrade)


"Послать tcp/ip пакет"
Отправлено queen , 14-Сен-06 21:58 
>А ipfw fwd не помогает? (только надо фрю до 5 ветки брать
>- в 5-ой глюк именно в этой функции, мне победить до
>сих пор не удалось - придется делать dowgrade)
например?
ipfw форвардит пакеты только локально


"Послать tcp/ip пакет"
Отправлено q , 22-Сен-06 00:22 
>>А ipfw fwd не помогает? (только надо фрю до 5 ветки брать
>>- в 5-ой глюк именно в этой функции, мне победить до
>>сих пор не удалось - придется делать dowgrade)
>например?
>ipfw форвардит пакеты только локально

Я данную задачу решал так:
NAT from ipfilter and fastroute option
Значит через rdr-правило соединение приходит на первый интерфейс, я делаю bind на второй интерфейс, смотрю через SIOCGNATL реальный адрес назначения и добавляю map-правило на замену адреса на реальный. А правила фильтра выполняются раньше, чем NAT-правила на outbound-трафике и там стоит отправлять все с первого интерфейса на второй (fastroute), что соответствует условиям map-правила. А у map-правила стоит второй интерфейс в качестве in_ifname, поэтому оно срабатывает и через второй интерфейс уходит соединение. Это true transparent proxy. Все сводится к одному правилу фильтра, одному правилу ната и динамической замене адреса для нужного соединения.  Почему нужен второй интерфейс? Все правила ipf работают на указанном интерфейсе, алиасы интерфейсов не поддерживаются, поэтому для предотвращения взаимного исключения правил используется второй интерфейс.


"Послать tcp/ip пакет"
Отправлено Boris Polevoy , 22-Сен-06 10:16 
>как мне послать пакет на локальный интерфейс,
>суть в том что libpcap'ом я перехватил пакет, поменял там source IP
>и хочу теперь его отправить, как мне это сделать?

если это все делать на C (C++) во FreeBSD есть несколько способов:
netgraph(4) - самая универсальная система, можешь отправлять любые пакеты на любом сетевом уровне.

библиотека /usr/ports/net/libdnet - это попроще, позволяет формировать любые Ethernet кадры, т.е. посылать в сеть вообще что угодно, с любыми MAC, IP - адресами, и не обязательно IP пакеты (например, ARP).

Есть еще похожие вещи, но dnet мне понравилась больше всего, все просто и понятно.


"Послать tcp/ip пакет"
Отправлено q , 22-Сен-06 21:50 
>библиотека /usr/ports/net/libdnet - это попроще, позволяет формировать любые Ethernet кадры, т.е. посылать
>в сеть вообще что угодно, с любыми MAC, IP - адресами,
>и не обязательно IP пакеты (например, ARP).
>
>Есть еще похожие вещи, но dnet мне понравилась больше всего, все просто
>и понятно.


Это не производительно! Всю работу должен делать пакетный фильтр в области ядра. См. выще NAT + fastroute


"Послать tcp/ip пакет"
Отправлено Boris Polevoy , 25-Сен-06 11:03 
>>библиотека /usr/ports/net/libdnet - это попроще, позволяет формировать любые Ethernet кадры, т.е. посылать
>>в сеть вообще что угодно, с любыми MAC, IP - адресами,
>>и не обязательно IP пакеты (например, ARP).
>>
>>Есть еще похожие вещи, но dnet мне понравилась больше всего, все просто
>>и понятно.
>
>
>Это не производительно! Всю работу должен делать пакетный фильтр в области ядра.
>См. выще NAT + fastroute

См. выше условия задачи: перехватил libcap'ом пакет... ;)


"Послать tcp/ip пакет"
Отправлено queen , 25-Сен-06 12:28 
>>>библиотека /usr/ports/net/libdnet - это попроще, позволяет формировать любые Ethernet кадры, т.е. посылать
>>>в сеть вообще что угодно, с любыми MAC, IP - адресами,
>>>и не обязательно IP пакеты (например, ARP).
>>>
>>>Есть еще похожие вещи, но dnet мне понравилась больше всего, все просто
>>>и понятно.
>>
>>
>>Это не производительно! Всю работу должен делать пакетный фильтр в области ядра.
>>См. выще NAT + fastroute
>
>См. выше условия задачи: перехватил libcap'ом пакет... ;)


чот у меня с утра не прёт или хз, как собирать то dnet?
undefined reference to `eth_open'
undefined reference to `eth_send'
undefined reference to `eth_close'


"Послать tcp/ip пакет"
Отправлено queen , 25-Сен-06 12:33 
>чот у меня с утра не прёт или хз, как собирать то
>dnet?
>undefined reference to `eth_open'
>undefined reference to `eth_send'
>undefined reference to `eth_close'


да точно туплю с утра, -ldnet помогло


"Послать tcp/ip пакет"
Отправлено queen , 25-Сен-06 12:39 
>библиотека /usr/ports/net/libdnet - это попроще, позволяет формировать любые Ethernet кадры, т.е. посылать
>в сеть вообще что угодно, с любыми MAC, IP - адресами,
>и не обязательно IP пакеты (например, ARP).
>
>Есть еще похожие вещи, но dnet мне понравилась больше всего, все просто
>и понятно.

пытаюсь отправить пакет, tcpdump пишет
12:40:10.538702 IP0 bad-hlen 0
пакет на уровне ethernet пойман libpcap'ом пытаюсь послать этот же пакет


"Послать tcp/ip пакет"
Отправлено queen , 25-Сен-06 12:55 
>пытаюсь отправить пакет, tcpdump пишет
>12:40:10.538702 IP0 bad-hlen 0
>пакет на уровне ethernet пойман libpcap'ом пытаюсь послать этот же пакет


тьфу не то совсем, прошу прощения, tcpdump вообще ничего не показывает

char dev[] ="rl0";
static eth_t    *dnet_eth;
if ((dnet_eth = eth_open(dev)) == NULL)
                errx(1, "eth_open");

if (eth_send(dnet_eth, packet, sizeof(packet)) != sizeof(packet))
                syslog(LOG_ERR, "couldn't send packet: %m");
eth_close(dnet_eth);

вот примерный код написал, нифига ничего не посылает


"Послать tcp/ip пакет"
Отправлено Boris Polevoy , 25-Сен-06 14:45 
>char dev[] ="rl0";
>static eth_t    *dnet_eth;
>if ((dnet_eth = eth_open(dev)) == NULL)
>            
>    errx(1, "eth_open");
>
>if (eth_send(dnet_eth, packet, sizeof(packet)) != sizeof(packet))
>            
>    syslog(LOG_ERR, "couldn't send packet: %m");
>eth_close(dnet_eth);
>
>вот примерный код написал, нифига ничего не посылает


packet - это указатель на Ethernet frame, т.е. должны быть указаны корректные адреса,
в кадре указан тип сетевого пакета

/usr/include/net/ethernet.h:
struct  ether_header {
        u_char  ether_dhost[ETHER_ADDR_LEN];
        u_char  ether_shost[ETHER_ADDR_LEN];
        u_short ether_type;
}

ether_type= ETHERTYPE_IP

IP пакет должен быть сформирован верно (адреса, флаги, контрольная сумма).

Вот такой запуск tcpdump поможет в более подробном анализе Ethernet кадров:
tcpdump -XX -v -n -s 256 -i <ifname>


"Послать tcp/ip пакет"
Отправлено kris , 05-Окт-06 23:32 
>packet - это указатель на Ethernet frame, т.е. должны быть указаны корректные
>адреса,
>в кадре указан тип сетевого пакета
>
>/usr/include/net/ethernet.h:
>struct  ether_header {
>        u_char  ether_dhost[ETHER_ADDR_LEN];
>        u_char  ether_shost[ETHER_ADDR_LEN];
>        u_short ether_type;
>}
>
>ether_type= ETHERTYPE_IP
>
>IP пакет должен быть сформирован верно (адреса, флаги, контрольная сумма).
>
>Вот такой запуск tcpdump поможет в более подробном анализе Ethernet кадров:
>tcpdump -XX -v -n -s 256 -i <ifname>

tcpdump ничего не показывает, пробовал даже через ip_send послать ip пакет

ip_t *ip;

if ((ip = ip_open()) == NULL)
printf("error");

if((ip_send(ip,iph, size_ip)) != size_ip)
printf("error 2");

ip_close(ip);


"Послать tcp/ip пакет"
Отправлено Boris Polevoy , 06-Окт-06 10:57 
>>IP пакет должен быть сформирован верно (адреса, флаги, контрольная сумма).
>>
>>Вот такой запуск tcpdump поможет в более подробном анализе Ethernet кадров:
>>tcpdump -XX -v -n -s 256 -i <ifname>
>
>tcpdump ничего не показывает, пробовал даже через ip_send послать ip пакет
>
>ip_t *ip;
>
>if ((ip = ip_open()) == NULL)
>printf("error");
>
>if((ip_send(ip,iph, size_ip)) != size_ip)
>printf("error 2");
>
>ip_close(ip);

Для примера привожу куски реально работающего кода, при передаче tcpdump все показывает.
Попробуй запускать tcpdump на приемной стороне, а так же смотреть на светодиоды активности сети на интерфейсах (коммутаторе). В качестве примера формирования пакетов различных протоколов смотри исходники tcpdump (функции разборки пакетов), там довольно все понятно, в каком поле пакета что должно лежать. Плюс соответствующие RFC по форматам пакетов.

------- открытие интерфейса -------
  if((m_eth= eth_open(m_ifname)) == NULL)
  {
    VLOG(fm_log, 1, "Ошибка eth_open('%s'), errno: %d (%s)", m_ifname, errno,                   strerror(errno));
    return(-1);
  }
--------------

-------- метод передачи кадра через интерфейс ------
  frame.set_mac_addr(m_mac);
  return( eth_send(m_eth, frame.get_raw(), frame.get_size()));
}
--------------


------- часть метода формирования кадра UDP пакета -------
  union              // буфер кадра
  {
...
    struct // UDP пакет (RFC 768)
    {
      struct ether_header hdr;
      struct ip           ip;
      struct udphdr       udp;
      uint8_t             data[1];
    } __packed udp;
...
   uint8_t raw[ETHER_MAX_LEN - ETHER_CRC_LEN];   // сырой Ethernet кадр (без контрольной суммы)
  } m_frame;

  // формирование кадра

  struct pseudo_udp_hdr {
    in_addr_t src;
    in_addr_t dst;
    uint8_t zero;
    uint8_t proto;
    uint16_t length;
  } __packed *pseudo;

  // зануление заголовков
  memset(m_frame.raw, 0, sizeof(m_frame.udp));

  // UDP заголовок + данные
  m_frame.udp.udp.uh_sport = htons(sport);
  m_frame.udp.udp.uh_dport = htons(dport);
  m_frame.udp.udp.uh_ulen =  htons(sizeof(m_frame.udp.udp) + data_size);

  if(data_size)
    memcpy( m_frame.udp.data, data, data_size);

  // псевдозаголовок для контрольной суммы (заполняется на месте IP заголовка перед UDP пакетом)
  pseudo = (struct pseudo_udp_hdr *) ( (uint8_t *)(&m_frame.udp.udp) - sizeof(*pseudo)) ;
  pseudo->src = src.s_addr;
  pseudo->dst = dst.s_addr;
  pseudo->proto = IPPROTO_UDP;
  pseudo->length = htons(sizeof(m_frame.udp.udp) + data_size);

  m_frame.udp.udp.uh_sum = ip_checksum((uint8_t *)pseudo, sizeof(*pseudo) + sizeof(m_frame.udp.udp) + data_size);

  // IP заголовок
  memset(pseudo, 0, sizeof(*pseudo));

  m_frame.udp.ip.ip_v = IPVERSION;
  m_frame.udp.ip.ip_hl = 5;  // 20/4
  m_frame.udp.ip.ip_len = htons(sizeof(m_frame.udp.ip) + sizeof(m_frame.udp.udp) + data_size);
  m_frame.udp.ip.ip_id = htons(get_number());
  m_frame.udp.ip.ip_ttl = 255;
  m_frame.udp.ip.ip_p = IPPROTO_UDP;
  m_frame.udp.ip.ip_src.s_addr = src.s_addr;
  m_frame.udp.ip.ip_dst.s_addr= dst.s_addr;
  m_frame.udp.ip.ip_sum = ip_checksum((uint8_t *) &m_frame.udp.ip, sizeof(m_frame.udp.ip));

  m_size = sizeof(m_frame.udp.hdr) + sizeof(m_frame.udp.ip) + sizeof(m_frame.udp.udp) + data_size;

  // заполенение Ether заголовка
  m_frame.udp.hdr.ether_type= htons(ETHERTYPE_IP);

--------------


"Послать tcp/ip пакет"
Отправлено som , 09-Окт-06 12:53 
с eth_send то всё работает
не получается через ip_send

"Послать tcp/ip пакет"
Отправлено Boris Polevoy , 10-Окт-06 10:51 
>с eth_send то всё работает
>не получается через ip_send

посмотри, что делает внутри ip_send() и задай вопрос: нужна ли она вообще?
ip_open -> socket(AF_INET, SOCK_RAW, IPPROTO_RAW)
ip_send -> sendto
ip_close -> close

Совершенно бесполезные накрывашки.
eth_send делает гораздо больше работы, поэтому я использовал ее.
Если не получается отправлять пакет через SOCK_RAW, то проблема в коде, а не в libdnet.
Код в форум. ;)


"Послать tcp/ip пакет"
Отправлено som , 10-Окт-06 12:36 
>>с eth_send то всё работает
>>не получается через ip_send
>
>посмотри, что делает внутри ip_send() и задай вопрос: нужна ли она вообще?
>
>ip_open -> socket(AF_INET, SOCK_RAW, IPPROTO_RAW)
>ip_send -> sendto
>ip_close -> close
>
>Совершенно бесполезные накрывашки.
>eth_send делает гораздо больше работы, поэтому я использовал ее.
>Если не получается отправлять пакет через SOCK_RAW, то проблема в коде, а
>не в libdnet.
>Код в форум. ;)
чёрт, не глянул в сорцы dnet'a, не думал что через RAW сокеты отправляет
исходник слишком большой :)
я тут пытаюсь с libpcap'ом отправить, но он отправляет через сетевой интерфейс, eth_send от dnet'a также, а мне нужно чтобы пакет посылался напрямую...



"Послать tcp/ip пакет"
Отправлено Boris Polevoy , 10-Окт-06 15:56 
>чёрт, не глянул в сорцы dnet'a, не думал что через RAW сокеты
>отправляет
>исходник слишком большой :)
>я тут пытаюсь с libpcap'ом отправить, но он отправляет через сетевой интерфейс,
>eth_send от dnet'a также, а мне нужно чтобы пакет посылался напрямую...
>

Напрямую это как? Прямо из буфера твоего процесса через DMA в память контроллера?
Придется затачивать драйвер специально для этого, отучать его работать с остальным стеком, убирать из него все очереди пакетов. Смысл? Цепочка вызовов от sendto(), ip_output(), до начала копирования в сетевой контроллер не такая уж большая, система mbuf'ов довольно оптимизирована. Что ты ждешь от сетевой подсистемы?