Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Что происходит при перехвате пакета.

Привет всем, в который раз:)

Собственно суть. Ставлю я  сетевую карту в PROMISK режим, создаю пакетный сокет. Принимаю ВСЕ(которые мне и которые не мне, но проходят через меня) пакеты. Пришел пакет. Без изменений он передается сокету. 
Насколько я понимаю, на сокет приходит копия пакета(или нет?). Что делает OC(unix/linux) с этим пакетом? Она его передает дальше, куда он шел? Если да, то можно это как-то убрать, чтобы я сам решал, пускать этот пакет дальше или нет? И можно как-то перехватывать адресованные мне пакеты и решать, пускать их к приложению или нет?

Это сообщение отредактировал(а) konshyn - 22.10.2013, 11:03
Ответ:
Комедия недопониманий  :smile 


Вопросы к ТС.
Цитата(konshyn @  24.10.2013,  17:40 )
Мой комп будет выступать как маршрутизатор.

Что есть маршрутизатор, и обязательно ли хост с тремя работающими интерфейсами является маршрутизатором?

Цитата(konshyn @  24.10.2013,  17:40 )
Именно ж в этом случае, чтобы на сокет ОСой передался не предназначенный моему компу пакет, нужно поставить его в PROMISC режим. Или я не прав?

Что есть этот самый "неразборчивый режим"? Зачем он нужен? Почему и без него работают маршрутизаторы?

PS В данном случае Вашими пакетами являются все пакеты, у которых MAC-адрес совпадает с MAC-адресом Вашего узла-маршрутизатора - это канальный уровень, даже если конечный пункт доставки пакета (по протоколу IP - это сетевой уровень) не совпадает с Вашим узлом. Именно эти пакеты Вы можете перехватить и изменить.



Цитата(konshyn @  24.10.2013,  17:40 )
Пакет нужно разделить на несколько частей и его части отправить на маршрутизатор другой сети. А там его собрать и отправить адресату. А чтобы знать, пришедший пакет является "моим" и нужно ли его собирать, нужно хотя бы добавить идентификатор. Но там еще 5 полей. Чтобы собрать его правильно.

IP-тунелирование? Зачем делить пакет, MTU не позволяет?


Цитата(konshyn @  24.10.2013,  17:40 )
Тут подкинули идею, настроить IP таблицу, и с определенного IP адреса, с которого должны приходить пакеты, отправлять их на IP "0.0.0.0" или 127.0.0.1, на локальныый хост, в общем.
Но как-то не хочется, можно ли просто запретить?

Простой файервол, поднятый на узле-маршрутизаторе, не поможет?


Цитата(konshyn @  24.10.2013,  17:40 )
Тогда не понимаю, как на мой комп может прийти чужой пакет(не широковещательный), если я не в качестве маршрутизатора выступаю.

Вот поэтому-то и встречный вопрос: "что есть неразборчивый режим?"  :girl_crazy 

Это сообщение отредактировал(а) feodorv - 24.10.2013, 18:32
Вопрос: Отправка перехваченного пакета

Ребят, нужна помощь.

В общем, перехватываю IP пакеты.
Полностью с IP заголовком и инкапсулированными данными.
Но этот же пакет мне нужно самому и отправить. Т.е. я перехватил, а потом его же отправляю

OC настроена на маршрутизацию. Но проходящие пакеты я блокирую. т.е. IPTABLES (FORWARD = DROP)
Создаю сокет для отправки перехваченного пакета так:
Код

sd_send = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);   


потом использую опцию IP_HDRINCL
Код

setsockopt(sd_send, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));


Затем происходит это:

Код

    struct iphdr    ip;
    struct sockaddr_in  sin;
    
    memset((void*)&sin, 0, sizeof(struct sockaddr_in));
    memcpy((void*)&ip, tmp_move_element->pack, sizeof(struct iphdr));
    
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = ip.daddr;
    
    struct in_addr ad_in;
    printf("Длина заголовка - %d, ", (ip.ihl * 4));
    printf("Длина пакета - %d\n", ntohs(ip.tot_len));
    ad_in.s_addr = ip.saddr;
    printf("IP адрес отправителя - %s\n", inet_ntoa(ad_in));
    ad_in.s_addr = ip.daddr;
    printf("IP адрес получателя - %s\n", inet_ntoa(ad_in));
    
    
    int rezult = sendto(sd_send, tmp_move_element->pack, ntohs(ip.tot_len), 0, (struct sockaddr *)&sin, sizeof(struct sockaddr));
    if (rezult < 0)
    {                                       
....


в итоге rezult возвращает сколько байт он отправил, но! wireshark не показывает, что пакет был отправлен, он просто не видит этого пакета 

Выручайте, литература не помогла мне разобраться с сырыми сокетами и отправкой собственных пакетов. Уже больше двух месяцев переодически пытался разобраться, но все тщетно... Раньше не горело, сейчас горит.

Ответ:
Цитата(xvr @  26.11.2013,  13:52 )
Так поделитесь с остальными, в чем было дело  smile  


IP пакеты(чистые, т.е. заголовок IP и инкапсулированные данные) перехватывать в linux нельзя. По крайне мере я не нашел как это делается.
Я создавал ПАКЕТНЫЙ сокет:
Код

eth0_recv = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
 

т.е. в моем сообщении был полностю eth-кадр: [ethernet заголовок[ip заголовок[..дальнейший стек и данные]]];
для отправки IP пакета сырой сокет использовал с опцией IP_HDRINCL;
ну, и в коде, который написал выше, и в своей программе я делал одно и то же.
копировал IP заголовок, чтобы определить структуру sockaddr_in для функции sendto, т.к. семейство и адрес получателя указывать обязательно
т.е. функция sendto отправляет пакет на тот адрес, который указан в структуре sockaddr_in, и соответственно, ядро само заменит это поле в ip-пакете на адрес, который указан в структуре, а все остальное, кроме, вроде как чек-суммы - останется в том виде, как был заполнен пакет.

Код

        memcpy((void*)&ip, recv_msg [color=blue]+ ETH_HLEN[/color], sizeof(struct iphdr));

        ad_in.s_addr = ip.daddr;
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = ip.daddr;
        
        tc_error = sendto(sd_send, recv_msg, ntohs(ip.tot_len), 0, (struct sockaddr *)&sin, sizeof(struct sockaddr));

В моем recv_msg хранится eth-кадр, а нужно было отправлять IP-пакет, т.е. заголов ethernet нужно было убрать(первые 14 байт в пакете все портили)

Код

tc_error = sendto(sd_send, recv_msg ((( + ETH_HLEN))), ntohs(ip.tot_len), 0, (struct sockaddr *)&sin, sizeof(struct sockaddr));

то, что нужно было исправить, а точнее просто добавить, я взял в тройные круглые скобки. 

P.S. Как редактировать в теге [code] не знаю:(

P.P.S. будьте внимательнее, господа  :boast 
Вопрос: Robocraftgame.com - разбор пакетов: как шифровать\дешифровать пакеты между клиентом-сервером

Всем привет!

Есть замечательная игра
Хочу научиться шифровать\дешифровать пакеты между клиентом-сервером.
Пакеты отлавливаю без труда, юзаю WP507F

Предполагаю, что обмен данными идёт в XML формате, который каким-то способом либо запакован, либо сериализирован.
Информации мало в какую сторону копать, но вот что накопал:

Пакет для разбора:
Код Code
1
95D55265747269657665556E6C6F636B65644375626573930B1A933D9F0B414456700B4FBFB2710B517DE57B0B629FAFEC0B68988A630B8098BA0F0B85083D670B88D7A0E00BA02038360BAAD44D340BAE95D4A50BBDEE823C0BC65A64860BE0A9599F0BE9B04FD90BF93B52A90BFC718DAD0BE23C17C9E463346366353636302D386132612D343232322D623234372D376165313261373136343765
в виде

Открыв пакет в hex редакторе составляющие пакета,
00х95-пологаю тип пакета
01хD5-длина пакета
02х-22х-заголовок пакета в ASCII
23х-х119 - дальше идёт зашифрованное тело пакета, которое хотелось бы как-то расшифровать
120х-155х - какой-то token, возможно ключь к дешифрации. Этот токен есть в конце всех пакетов, естественно везде он разный по значению, одинаковый по длине.

На этом форуме нащел сообщение [ссылка на форум]
начал копать файл из каталога с игрой, он частично обфусцирован
нащел клиент за 2013 год, там этот немного меньше обфусцирован пологаю взаимоотношение с сервером в старой версии не сильно отличается от новой.


Итак, заглядываем внутрь в биоблитеку, первое что на что упал взгляд - на сериализации может ими можно как-то дешифровать тело пакета?

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


Я в сетевом программировании увы профан, и вообще только учусь пока изучаю с++, но мне важен сам алгоритм, а не кодинг, помогите кто чем может !!!
Ответ: Насчёт подмены пакетов и токенов - сервер хавает удачно сохранёные пакеты даже месячной давности...
Вопрос: Просмотр пакета перехваченного через снифер

Здравствуйте уважаемые! Я недавно начал самостоятельно изучать сокеты. Пошарив в интернете я нашел такой вот код более менее в нем разобрался только появился вопрос? Я точно не понял один момент. а конкретно: как расшифровать пакет?
посмотреть что в нем? то есть увидеть его содержимое. Я так понял что содержимое пакета будет в одном из полей структуры IPHeader.. Разъясните этот момент если не сложно. Данный код работает у меня без ошибок.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <conio.h>
#include <stdio.h>
#include <winsock2.h>
 
#define MAX_PACKET_SIZE    0x10000
#define SIO_RCVALL         0x98000001
#pragma comment (lib,"ws2_32.lib")
// Буфер для приёма данных
char Buffer[MAX_PACKET_SIZE]; // 64 Kb
 
                              //Структура заголовка IP-пакета
 
typedef struct IPHeader {
    UCHAR   iph_verlen;   // версия и длина заголовка
    UCHAR   iph_tos;      // тип сервиса
    USHORT  iph_length;   // длина всего пакета
    USHORT  iph_id;       // Идентификация
    USHORT  iph_offset;   // флаги и смещения
    UCHAR   iph_ttl;      // время жизни пакета
    UCHAR   iph_protocol; // протокол
    USHORT  iph_xsum;     // контрольная сумма
    ULONG   iph_src;      // IP-адрес отправителя
    ULONG   iph_dest;     // IP-адрес назначения
} IPHeader;
 
char src[10];
char dest[10];
char ds[15];
unsigned short lowbyte;
unsigned short hibyte;
 
void main()
{
    WSADATA     wsadata;   // Инициализация WinSock.
    SOCKET      s;         // Cлущающий сокет.
    char        name[128]; // Имя хоста (компьютера).
    HOSTENT*    phe;       // Информация о хосте.
    SOCKADDR_IN sa;        // Адрес хоста
    IN_ADDR sa1;        //
    unsigned long        flag = 1;  // Флаг PROMISC Вкл/выкл.
 
                                    // инициализация
    WSAStartup(MAKEWORD(2, 2), &wsadata);
    s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    gethostname(name, sizeof(name));
    phe = gethostbyname(name);
    ZeroMemory(&sa, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = ((struct in_addr *)phe->h_addr_list[0])->s_addr;
    bind(s, (SOCKADDR *)&sa, sizeof(SOCKADDR));
 
    // Включение promiscuous mode.
    ioctlsocket(s, SIO_RCVALL, &flag);
 
    // Бесконечный цикл приёма IP-пакетов.
    while (!_kbhit())
    {
        int count;
        count = recv(s, Buffer, sizeof(Buffer), 0);
        // обработка IP-пакета
        if (count >= sizeof(IPHeader))
        {
            IPHeader* hdr = (IPHeader *)Buffer;
            //Начинаем разбор пакета...
 
            strcpy(src, "Пакет: ");
            CharToOemA(src, dest);
            printf(dest);
            // Преобразуем в понятный вид адрес отправителя.
            printf("From ");
            sa1.s_addr = hdr->iph_src;
            printf(inet_ntoa(sa1));
 
            // Преобразуем в понятный вид адрес получателя.
            printf(" To ");
            sa1.s_addr = hdr->iph_dest;
            printf(inet_ntoa(sa1));
 
            // Вычисляем протокол. Полный список этих констант
            // содержится в файле winsock2.h
            printf(" Prot: ");
            if (hdr->iph_protocol == IPPROTO_TCP) printf("TCP ");
            if (hdr->iph_protocol == IPPROTO_UDP) printf("UDP ");
 
            // Вычисляем размер. Так как в сети принят прямой порядок
            // байтов, а не обратный, то прийдётся поменять байты местами.
            printf("Size: ");
            lowbyte = hdr->iph_length >> 8;
            hibyte = hdr->iph_length << 8;
            hibyte = hibyte + lowbyte;
            printf("%s", itoa(hibyte, ds, 10));
 
            // Вычисляем время жизни пакета.
            printf(" TTL:%s", itoa(hdr->iph_ttl, ds, 10));
            printf("\n");
 
        }
    }
 
    closesocket(s);
    WSACleanup();
}
Ответ:
Сообщение от Jaxmackey
Не понимаю где и как настраивается это смещение?
Младшие четыре бита первого 8-битного байта IP пакета
содержат размер IP-заголовка в этом пакете.
Этот размер указывается в 32-ух битных словах.
То бишь берем число из этих четырех бит и множим на 32.
Получаем смещение от начала IP заголовка до начала данных.
В начале данных IP-пакета у нас лежит TCP заголовок.
В нем в седьмом 16-ти битном слове младшие 4 бита
обозначают размер заголовка данного TCP пакета.
Оно также указано в 32-ух битных словах.
Так что множим это значение на 32 и получаем смещение до данных TCP.
Вопрос: Отправить пакет с интерфейса без ip-адреса

Доброго вечера.

Есть несколько вопросов, на которые я пока что не смог найти ответ.

Есть сетевой интерфейс. У него есть свой mac-адрес, но отсутствует ip-адрес (это обязательное условие). Карточка подключена кабелем напрямую к другой карточке (к другому компу). Как можно отправить свои созданные пакеты с этого интерфейса, просто отправить в никуда, к примеру широковещательный(вообще желательно широковещательный, т.е. dest mac-адрес FF:FF:FF:FF:FF:FF). 
И как можно принимать пакеты с такого же интерфеса (без ip-адреса).

Вот то, что я пытался сделать (вкратце):
Код

int sock
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 
дальше формировал пакет(ethernet-frame). вот такой он получился (по байтам в 16 с/с):
FF FF FF FF FF FF 64 66 B3 01 80 DD 08 00 45 00 00 20 00 00 00 00 FF 11 05 74 C0 A8 01 84 AD C2 46 6A 13 56 13 56 00 0C 5A F7 54 65 73 74

FF FF FF FF FF FF - destination mac-адрес
64 66 B3 01 80 DD - source mac-адрес
08 00 - означает, что в eth-фрейм вложен ip пакет.
45 - первая цифра - версия ip-протокола, вторая цифра - размер ip-заголовка в байтах.
00 - то, что не имеет значение в данном случае (тип службы и что-то еще)
00 20 - размер ip-пакета (без eth-заголовка) в байтах, вместе с ip-заголовком. 0x20 = 32 байта. 20 байт заголовок ip, 8 байт заголовок udp, 4 байта - данные.
00 00 - идентификатор пакета
00 00 - флаги/смещение
FF - время жизни
11 - номер вложенного протокола, в данном случае - UDP
05 74 - контрольная сумма ip-заголовка
C0 A8 01 84 - source ip-адрес (192.168.1.132)
AD C2 46 6A - dest ip-адрес (173.194.70.106)
13 56 - порт отправителя
13 56 - порт получателя
00 0C - длина датаграммы
5A F7 - контрольная сумма udp
54 65 73 74 - собственно данные  - слово "T e s t" (без пробелов)

заполняю структуру
Код

struct sockaddr_ll s_ll;
memset(&s_ll, 0, sizeof(s_ll));
s_ll.sll_ifindex = 0; // в моем случае индекс интерфейса = 0
s_ll.sll_family = AF_PACKET;
memcpy(s_ll.sll_addr, source_mac, 6);  //source_addr содержит FF:FF:FF:FF:FF:FF
s_ll.sll_halen = htons(6); 

//и отправляю
send_bytes = sendto(sock, buff, length_buff, (struct sockaddr *)&s_ll, sizeof(s_ll));


perror выводит ошибку: sendto() failed: Network is down

И еще раз напишу, а то к концу прочтения можно забыть, что у меня не получается:
Есть сетевой интерфейс. У него есть свой mac-адрес, но отсутствует ip-адрес (это обязательное условие). Карточка подключена кабелем напрямую к другой карточке (к другому компу). Как можно отправить свои созданные пакеты с этого интерфейса, просто отправить в никуда, к примеру широковещательный(вообще желательно широковещательный, т.е. dest mac-адрес FF:FF:FF:FF:FF:FF). 
И как можно принимать пакеты с такого же интерфеса (без ip-адреса).

Если кто-то знает или есть догадки, как это можно сделать, поделитесь, пожалуйста.

P.S. Если светофор, который описывает побайтово пакет, напрягает кого-то, напишите - исправлю. Спасибо
Ответ:
Цитата(tzirechnoy @  11.2.2014,  21:14 )
А что говорит на этот интэрфейс ip link ? 


Он как раз говорил о том, что state DOWN

Цитата(tzirechnoy @  11.2.2014,  22:01 )
Да что там, собственно. Чтобы отправлять пакеты через AF_PACKET, SOCK_RAW -- не требуется ip-адрес, но интэрфейс должэн быть UP. 


Вы правы, сработало. Спасибо


UPD: Но теперь другая проблема. Wireshark видит, что пакет отправляется. А на другой машине, wireshark не видит этот пакет.

UPD2: Все видит. Это я в своих интерфейсах запутался. Утро:(

tzirechnoy, Спасибо  :thank_you2

Это сообщение отредактировал(а) konshyn - 12.2.2014, 10:08
Вопрос: Переподключить пакет nuget

Привет!

Использую Visual Studio.

Через Управление пакетами NuGet... скачал и установил нужный пакет. Ссылка в проект тоже добавилась. Потом закрыл Студию, не сохраняясь. Открыл через какое-то время, хочу добавить снова этот же пакет. Зашел опять в управление пакетами, ищу нужный, но там слева вверху стоит зеленая галка и говорится, что пакет установлен. Я, не долго думая, в том же диалоговом окне на вкладке Установленные пакеты удалил его. Пробую опять добавить - все равно говорит, что пакет установлен. Удаляю папку packages из папки решения. Все равно "пакет установлен".

Вопрос: как переподключить этот пакет?
Ответ:
Сообщение от V0fka
Потом закрыл Студию, не сохраняясь
Наверное, именно в этом и крылась причина возникших проблем. У меня с NuGet-пакетами никогда подобного поведения не возникало - успешно добавлял и работал как с чужими пакетами, так и со своими.
Вопрос: Объединение Tcp пакетов по сессии в файл

Я использую библиотеку libpcap для снифа пакетов. Подскажите как лучше организовать архитектуру приложения, чтобы собрать tcp пакеты каждой сессии в один файл. Имеется ввиду реализация протокола http, грубо говоря. То есть слушаем интерфейс, приходят пакеты. Выбираем из них те которые привязаны к конкретному соединению и собираем в файл. Допустим был гет запрос на выдачу файла hello-world. Он был отправлен нам в 10 пакетах, но помимо них было еще 100500 других. Необходимо выделить именно эти 10 и записать их в файл. С остальными соединениями так же. Идея в целом такая слушаем трафик и сохраняем его во временных файлах(аналог браузера).
Ответ:
Сообщение от vxg
То что содержит пакет вы не узнаете если не разберёте протокол а сам трафик легко слить в файл - пакеты не обезличенные у них есть адрес и порт вот по ним и сливайте
Я это понимаю, поэтому и прошу подсказать как лучше организовать саму архитектуру приложения. Боюсь за то что во время выполнения callback придет новый пакет, а функция не успеет выполниться, в итоге либо пакет потеряется либо система затормозится(не мог точно сказать как произойдет). Если писать в файл, то его надо открыть, записать, закрыть. После отдельным потоком(процессом) обрабатывать(моё мнение). Можно держать в памяти и порциями скидывать на диск, после чего обрабатывать. Вот и пытаюсь узнать, как лучше организовать саму архитектуру приложения(потоки, семафоры, мьютексы, отображение файла в память). Может есть какие то готовые библиотеки выборки из дампа пакетов.
Вопрос: Особенность с интерфейсом 127.0.0.1 в плане безопасности от пакетов извне

Здравствуйте)

Пишу программу, которая обращается к другой моей программе на локальном ПК по адресу 127.0.0.1.
Я где-то читал, что если открыть сокет на интерфейсе 127.0.0.1 вместо 0.0.0.0 (INADDR_ANY), то на него может прийти пакет ТОЛЬКО с этого же логического интерфейса Loopback, пакет ИЗВНЕ будет отброшен.

В плане безопасности, так правда ли это, что таким образом никакой пакет снаружи из сети не придёт, если открыть порт на интерфейсе 127.0.0.1 ?

Вот примерный код для наглядности того, что я написал:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//Создание сокета для UDP и получение идентификатора на него.
int handle_winsock;
handle_winsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 
//Указание параметров для сокета при привязке. Ожидание на указанном порту для всех IP.
sockaddr_in address_listen;
address_listen.sin_family = AF_INET;
 
 
 
//Для приёма пакета извне... ????
  //address_listen.sin_addr.s_addr = htonl(INADDR_ANY);
 
//Для приёма пакета только с локального ПК... ????
  //int ta = 127, tb = 0, tc = 0, td = 1;
  //address_listen.sin_addr.s_addr = htonl((ta << 24) | (tb << 16) | (tc << 8) | td);
 
 
 
address_listen.sin_port = (1234 >> 8) | (1234 << 8); //Порт 1234.
 
//Перевод сокета handle_winsock в неблокирующий режим.
DWORD nonBlocking = 1;
ioctlsocket(handle_winsock, FIONBIO, &nonBlocking);
 
//Связывание сокета.
int status_bind;
status_bind = bind(handle_winsock, (sockaddr*)&address_listen, sizeof(sockaddr_in));
Ответ: Кстати, написал тестовую программу, сервер повесил на 127.0.0.1, далее
клиента весил сначала на 0.0.0.0, пакет дошёл,
затем клиента перевесил на 127.0.0.1, пакет дошёл,
затем клиента перевесил на внешний IP, пакет НЕ дошёл,
похоже фильтрация есть)
Вопрос: Как изменить, пересчитать хэш пакета и отправить его в порт в модуле linux?

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#define __KERNEL__
#define MODULE
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/netfilter.h>
    #include <linux/netfilter_ipv4.h>
    #include <linux/skbuff.h>
    #include <linux/udp.h>
    #include <linux/ip.h>
    #include <net/ip.h>
    #include <linux/inet.h>
static struct nf_hook_ops netfilter_ops_in; /* NF_IP_PRE_ROUTING */
static struct nf_hook_ops netfilter_ops_out; /* NF_IP_POST_ROUTING */
/* Function prototype in <linux/netfilter> */
unsigned int main_hook(unsigned int hooknum,  
                  struct sk_buff *skb,
                  const struct net_device *in,
                  const struct net_device *out,
                  int (*okfn)(struct sk_buff*))
{
struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
 
if (htonl (in_aton("192.168.0.1")) == htonl(iph->saddr)){
**printk(KERN_ALERT "поймал пакет  \n");** ---- тут условие, по которому я ловлю пакеты
 
}
return NF_ACCEPT; /* Allow ALL Packets */
}
int init_module()
{
        netfilter_ops_in.hook                   =       main_hook;
        netfilter_ops_in.pf                     =       PF_INET;
        netfilter_ops_in.hooknum                =       0;
        netfilter_ops_in.priority               =       NF_IP_PRI_FIRST;
        netfilter_ops_out.hook                  =       main_hook;
        netfilter_ops_out.pf                    =       PF_INET;
        netfilter_ops_out.hooknum               =       4;
        netfilter_ops_out.priority              =       NF_IP_PRI_FIRST;
        nf_register_hook(&netfilter_ops_in); /* register NF_IP_PRE_ROUTING hook */
        nf_register_hook(&netfilter_ops_out); /* register NF_IP_POST_ROUTING hook */
return 0;
}
void cleanup_module()
{
nf_unregister_hook(&netfilter_ops_in); /*unregister NF_IP_PRE_ROUTING hook*/
nf_unregister_hook(&netfilter_ops_out); /*unregister NF_IP_POST_ROUTING hook*/
}
Подскажите, какими мне методами изменить адрес назначения пакета, пересчитать хэш и отправить его в порт?
Ответ: Отвечу на свой вопрос, может кому пригодится.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#define __KERNEL__
#define MODULE
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <linux/inet.h>
#include <linux/in.h>
 
static struct nf_hook_ops netfilter_ops_in; /* NF_IP_PRE_ROUTING */
static struct nf_hook_ops netfilter_ops_out; /* NF_IP_POST_ROUTING */
/* Function prototype in <linux/netfilter> */
static uint16_t csum(uint16_t* buff, int nwords) {
    uint32_t sum;
    for (sum = 0; nwords > 0; nwords--)
            sum += *buff++;
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
 
    return ((uint16_t) ~sum);
}
unsigned int main_hook(unsigned int hooknum,  
                  struct sk_buff *skb,
                  const struct net_device *in,
                  const struct net_device *out,
                  int (*okfn)(struct sk_buff*))
{
    struct ethhdr *eth;
    struct tcphdr *tcph = (struct tcphdr *)(skb_network_header((skb)) + ip_hdrlen((skb)));
    struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
    eth = (struct ethhdr*)skb_mac_header(skb);
    user_data = (unsigned char *)((unsigned char *)tcph + (tcph->doff * 4));
    tail = skb_tail_pointer(skb);
    printk(KERN_ALERT "----------------ВХОДЯЩИЙ ПАКЕТ---------------------");
    printk(KERN_ALERT "INFO: CHECKSUM IP old: %u.\n",iph->check);
    iph->check = 0;// старую хэш сумму зануляем
    printk(KERN_ALERT "INFO: CHECKSUM IP=0: %u.\n",iph->check);
    iph->saddr = in_aton("192.168.95.129");//меняем ip адрес
    iph->check = csum((uint16_t*) iph, (iph->ihl << 1));// считаем хэш
    printk(KERN_ALERT "INFO: CHECKSUM IP NEW: %u.\n",iph->check);   
    printk(KERN_ALERT "INFO: Source IP Address: %pI4.\n",&iph->saddr);
    printk(KERN_ALERT "INFO: Source PORT: %u.\n",htons((unsigned short int) tcph->source));
    printk(KERN_ALERT "INFO: Destination IP Address: %pI4.\n",&iph->daddr);
    printk(KERN_ALERT "INFO: DEST PORT: %u.\n",htons((unsigned short int) tcph->dest));
    printk("src mac %pM, dst mac %pM\n", eth->h_source, eth->h_dest);
    printk(KERN_ALERT "поймал пакет от: %pI4.\n",&iph->saddr);
    return NF_ACCEPT;
}
 
int init_module()
{
    netfilter_ops_in.hook                   =       main_hook;
    netfilter_ops_in.pf                     =       PF_INET;
    netfilter_ops_in.hooknum                =       0; // какую функцию будем ловить NF_IP_PRE_ROUTING или другую
    netfilter_ops_in.priority               =       NF_IP_PRI_FIRST;
    nf_register_hook(&netfilter_ops_in); /* register NF_IP_PRE_ROUTING - функция срабатывает как только мы получаем пакет,
даже если он проходящий. Если мы хотим иметь доступ ко всем пакетам,проходящим через наш интерфейс, то мы должны использовать эту функцию.  */
    printk(KERN_ALERT "----------------я тут---------------------");
return 0;
}
void cleanup_module()
{
    nf_unregister_hook(&netfilter_ops_in); /*unregister NF_IP_PRE_ROUTING hook*/
}
Вопрос: Передача пакетов на IP и порт

Хочу узнать как средствами Delphi сделать передачу пакетов на IP:Port с установкой объёма пакетов и скоростью их передачи а также выбором HTTP TCP UDP
Ответ: Jake Morgan, не надо оперировать понятие "пакеты". Они имеют несколько иное значение, чем вы в него вкладываете, подозреваю. Если вы отправите файл в 20 МБ - это сколько пакетов вы отправите?

Отправку по HTTP - это вам надо поднять свой сервер (либо найти уже существующий и тренироваться на нем) и с помощью idHTTP (допустим, у нас будет переменная HTTP класса TidHTTP) делать

Delphi
1
result := HTTP.Get('http:\\ya.ru');
Пока вы не сформулируете точно поставленную задачу мы так и будем ходить вокруг да около. Хотите регулировать скорость отправки? В прошлом посте расписано. Хотите делать общение через TCP с помощью IP-адреса и порта? Пожалуйста, адреса и порта как раз достаточно для подключения. Хотите задать объем пакета? Едва ли. TCP эту задачу берет на себя и справляется без вас. Отправлять маленькими пакетами, конечно, можно, но рационально ли? Да и при приеме он все равно склеит эти маленькие пакеты в один большой, а время на отправку увеличите. А большие он в любом случае будет дробить, и вы с этим ничего не поделаете.