Привет, всем!Я программирую под unix совсем немного времени... Возникла проблема, решение которой, теперь я думаю под силу человеку, знающему функционирование обработки сетевых потоков.
Вот вкратце суть моей задачи. На узле А нужно ловить все пакеты, направленные в определенную сеть, отсекать эти пакеты и пересылать их на узел B. Т.е. на узле А нужно ловить нужные пакеты, инкапсулировать их в UDP пакеты и пересылать на узел B. А на узле B нужно "отпустить" этот пакет будто он сам пришел на узел В и дальше он идет обычными средствами туда, куда и направлялся.
Я использую ubuntu 10. Для перехвата пакетов использую iptalbes/libipq.
Инкапсулирую перехваченный пакет как он пришел (без его изменения). А потом на узле получив пакет, пытаюсь "положить" его на дальнейшую обработку. Для этого я использую библиотеку libnet.1. Открываю сокет int libnet_open_raw_sock(int protocol);
2. Записываю полученный пакет int libnet_write_ip(int sock, u_char *packet, int len);
Wireshark перехватывает этот пакет. Т.е. вроде бы он записался нормально. Но система как будто НЕ ОБРАБАТЫВАЕТ эти пакеты. Пакеты в систему падают, wireshark их ловит, но система на них не реагирует.
Вот тут у меня и вопрос. Можно ли так делать? Я отправляю перехваченный пакет на узел B.
(т.е. я отправляю m->payload, где m - это объект ipq_packet_msg_t). А на узле B просто записываю в raw_sock эти данные. Сколько байт получил на узле А, столько же и записал в raw_sock на узле B.Есть тут какие-нибудь противоречия? Почему система их не обрабатывает?
Я решил, что система не обрабатывает эти пакеты, потому что я на узле А перехватываю ICMP пакеты пинга узла B, передаю эти пакеты в инкапсулированном виде на узел В. На узле B вторая программа ожидает эти пакеты, "разворачивает" их из UDP и "отпускает" на обработку путем записи в raw_sock. Но пинги назад не возвращаются!! Хотя wireshark перехватил пакет, который пришел в систему с пингом...Очень надеюсь на вашу помощь!
Спасибо!
Чисто на всякий случай, если задача не состоит в том чтобы научится программированию TCP/IP под линукс, то прочитайте про туннели.
Из общих соображений:1)ты какие пакеты вообще "ловишь"?
Если tcp то левая система и не будет "реагировать" на левый пакет. Потомучто соединение надо еще и установить.
2)если ты не меняешь dst ip то система также не должна на них "реагировать"
>Из общих соображений:
>
>1)ты какие пакеты вообще "ловишь"?
>Если tcp то левая система и не будет "реагировать" на левый пакет.
>Потомучто соединение надо еще и установить.
>2)если ты не меняешь dst ip то система также не должна на
>них "реагировать"На узле А ловлю пакеты, направляющиеся в сеть, где узел С
На узле В этот пакет перехватывается моей программой, инкапсулируется в UDP и отправляется на узел С. А на узле С я извлекаю данные из полученного UDP пакета и записываю эту посл-ть байт в сокет. Т.е. после этого система должна обрабатывать пакет будто он сам пришел сюда. Если это ее пакет, то отреагировать соответствующим образом, если не к ней адресовался, то она также как обычно сама разбирается что с ним делать.Уже понятнее объяснил, что хочу сделать?
Очень надеюсь на вашу помощь!
Давайте, я попробую абстрагироваться от моей задачи и описать конкретно суть проблемы ;)Будем рассматривать только одну машину. Будем ловить все пакеты поступающие на данный узел.
Это будем делать с помощью iptables/libipq (кусок кода ниже). Потом с помощью библиотеки libnet я записываю перехваченный пакет КАК ЕСТЬ в сокет. (кусок кода см. ниже).Wireshark ловит этот "возрожденный" пакет. Но система его будто не обрабатывает. Потому что это например я тестил пингом эту машину и она не отвечает на пинги. Т.к. фактически пакеты не были обработаны системой.
Вот код, отвечающий за перехват пакета:
int status;
unsigned char buf[66000];
struct ipq_handle *h;h = ipq_create_handle(0, PF_INET);
if (!h)
Die(h);status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
if (status < 0)
Die(h);do{
status = ipq_read(h, buf, BUFSIZE, 0);
if (status < 0)
Die(h);switch (ipq_message_type(buf)) {
case NLMSG_ERROR:
fprintf(stderr, "Received error message %s\n",
strerror(ipq_get_msgerr(buf)));
break;case IPQM_PACKET: {
ipq_packet_msg_t *m = ipq_get_packet(buf);// m содержит перехваченный пакет.
// отбрасываем оригинальный пакет
status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL);// вызываем функцию отправки перехваченного пакета
result = ResendPacket(m->payload, m->data_len);Код, отвечающий за отправку перехваченного пакета:
int PacketSend::ResendPacket(const u_char * raw_data,
u_short data_len)
{
int network, c;printf("packet injection in the network! thrhu raw socket\n");
network = libnet_open_raw_sock(IPPROTO_RAW);
if (network == -1)
{
libnet_error(LIBNET_ERR_FATAL, (char *)"Can't open network.\n");
return 1;
}c = libnet_write_ip(network, (u_char *)raw_data, data_len);
if (c < data_len)
{
libnet_error(LN_ERR_WARNING, (char *)"libnet_write_ip only wrote %d bytes\n", c);
return 1;
}
else
{
printf((char *)"construction and injection completed, wrote all %d bytes\n\n", c);
}if (libnet_close_raw_sock(network) == -1)
{
libnet_error(LN_ERR_WARNING, (char *)"libnet_close_raw_sock couldn't close the
interface");
return 1;
}return (c == -1 ? EXIT_FAILURE : EXIT_SUCCESS);
}
Жду ваших ответов! Спасибо.
>Давайте, я попробую абстрагироваться от моей задачи и описать конкретно суть проблемы
>;)а можно узнать почему тунелинг обычный не устраивает?
не пытаешься ли ты решить уже решенную задачу?
ты уэ по полной тогда абстагируйся - изложи по пунктам КОНКРЕТНУЮ ЗАДАЧУ - без А и Б.
Есть мнение что NulNu прав )
>ты уэ по полной тогда абстагируйся - изложи по пунктам КОНКРЕТНУЮ ЗАДАЧУ
>- без А и Б.
>Есть мнение что NulNu прав )Да, возможно мне бы и подошел туннелинг. Но так и быть, придется полность абстрагироваться :))
Задача следующая: на узле А пехватывать пакеты направляющиеся в сеть N.
В конфигурационном файле программы должны быть установлены 1 или несколько адресов из сети N (на самом деле это несколько интерфейсов на одной машине). Пакеты будут инкапсулироваться в UDP и по определенному алгоритму весов этих интерфейсов, пакеты будут отправляться на все эти интерфейсы поочередно (на каждый интефейс будет приходиться заданный процент всего потока).Возможно, туннелингом мне удастся решить инкапсуляцию и переброс пакетов в другую сеть, но я не смогу распределить нагрузку по интерфейсам...
Жду ваших ответов! Спасибо!
извините....что отвлекаю -- но если вы хорошо поищете -- то "Всё уже придумано за нас" (С) Народная Мудрось
>извините....что отвлекаю -- но если вы хорошо поищете -- то "Всё уже
>придумано за нас" (С) Народная МудросьНу так подскажи к чему клонишь?
>>извините....что отвлекаю -- но если вы хорошо поищете -- то "Всё уже
>>придумано за нас" (С) Народная Мудрось
>
>Ну так подскажи к чему клонишь?клоню к протоколу который поддерживает multihoming
>>>извините....что отвлекаю -- но если вы хорошо поищете -- то "Всё уже
>>>придумано за нас" (С) Народная Мудрось
>>
>>Ну так подскажи к чему клонишь?
>
>клоню к протоколу который поддерживает multihomingСпасибо, за multihoming. ;)
Насколько я понял, multihoming позволяет конфигурировать локальные интерфейсы.
Могу ли я с помощью мультихоминга отправлять поток пакетов с чередованием на интерфейсы адресата? Мне нужно в процентном соотношении отправлять поток данных на интерфейсы.
Скажем, 10% на 1й интерфейс, 40% на 2ой, а все остальное на 3й интерфейс.
Подскажите, дайте ссылки, если я что не так понимаю...Спасибо. Жду ваших ответов!
>[оверквотинг удален]
>Спасибо, за multihoming. ;)
>Насколько я понял, multihoming позволяет конфигурировать локальные интерфейсы.
>Могу ли я с помощью мультихоминга отправлять поток пакетов с чередованием на
>интерфейсы адресата? Мне нужно в процентном соотношении отправлять поток данных на
>интерфейсы.
>Скажем, 10% на 1й интерфейс, 40% на 2ой, а все остальное на
>3й интерфейс.
>Подскажите, дайте ссылки, если я что не так понимаю...
>
>Спасибо. Жду ваших ответов!а такое можно сделать (и будет более правильно) например с помощью advanced routing (lartc) + openvpn на udp -- т.е. создать openvpn туннель , трафик самого openvpn'а раскладывать по разным каналам с помощью netfilter+ip route. Нужный нам трафик заворачивать в туннель.
это всё без использования multihoming'а, я как понял ничего хорошего ты так и не нашел/понял.
Удачи.