C++ перенаправление iptables с формированием отдельных пакетов

У меня весь трафик с порта 50 перенаправляется на 5050 с помощью

iptables -t nat -A POSTROUTING -p udp --dport 50 -j REDIRECT --to-port 5050

Я слушаю через сокет RAW на 5050 и вижу IP-пакеты от 0.0.0.0:50 до 0.0.0.0:5050. Первоначальный адрес назначения явно отсутствует, так как это похоже на отдельный пакет перенаправления с порта 50 на порт 5050.

Если исходный пакет должен был идти на a.b.c.d:50, как мне получить этот IP-адрес? Как я могу выяснить адрес назначения, на который должно было быть отправлено сообщение, чтобы я мог переслать его туда?

Я ценю вашу помощь.

P.S.: Я не хочу использовать libipq, так как по какой-то причине он не работал, и я не хочу тратить больше времени на то, чтобы заставить его работать.


person SkypeMeSM    schedule 16.10.2010    source источник


Ответы (1)


Сетевой фильтр Linux определяет параметр сокета с именем SO_ORIGINAL_DST в <linux/netfilter_ipv4.h>.

Сначала вам нужно включить переадресацию портов в вашей системе, используя одну из этих команд:

sysctl net.ipv4.ip_forward=1
echo 1 > /proc/sys/net/ipv4/ip_forward

Затем вы можете использовать это:

struct sockaddr_in addr;
socklen_t addr_sz = sizeof(addr);
getsockopt(fd, IPPROTO_IP, SO_ORIGINAL_DST, &addr, &addr_sz);

Я не могу найти SO_ORIGINAL_DST ни на одной справочной странице Linux. Возможно, вам повезет найти официальную документацию на сайте netfilter.

person camh    schedule 16.10.2010
comment
Спасибо за ответ. Нет, это тоже не работает. Это дает my_ip_address:0 . Можем ли мы сделать это по-другому? - person SkypeMeSM; 17.10.2010
comment
@SkypeMeSM: SO_ORIGINAL_DST требует, чтобы вы включили переадресацию портов. Это должно решить вашу проблему. - person jweyrich; 17.10.2010
comment
@jweyrich: Спасибо за ответ. Я сделал это. система (sysctl net.ipv4.ip_forward = 1); addr_len = sizeof (структура sockaddr); getsockopt(sip_socket, IPPROTO_IP_IP, SO_ORIGINAL_DST, &sender_addr, (socklen_t*)&addr_len); cout ‹‹ inet_ntoa(sender_addr.sin_addr) ‹‹ : ‹‹ ntohs(sender_addr.sin_port) ‹‹ endl; - person SkypeMeSM; 17.10.2010
comment
Извините за этот невыровненный код в комментарии. В основном я правильно устанавливаю параметры. Когда пакет получен с a.b.c.d:50 на my_ip:50, он перенаправляется как отдельный пакет с my_ip:50 на my_ip:5050. Использование SO_ORIGINAL_DST дает мне my_ip:0, а мне нужно a.b.c.d:50. - person SkypeMeSM; 17.10.2010
comment
@SkypeMeSM: попробуйте передать SOL_IP вместо IPPROTO_IP. - person jweyrich; 17.10.2010
comment
@SkypeMeSM: еще одна важная вещь заключается в том, что вы должны использовать PREROUTING вместо POSTROUTING, потому что NAT назначения работает только до маршрутизации. - person jweyrich; 17.10.2010
comment
@jweyrich: я использую PREROUTING для пересылки входящих пакетов и POSTROUTING для пересылки исходящих пакетов на новый порт 5050. Это правильно? - person SkypeMeSM; 17.10.2010
comment
Если я ошибаюсь, надеюсь, меня кто-нибудь поправит. Я думаю, что это решение не работает для сокетов без установления соединения, потому что оно является частью модуля conntrack. Смотрите наш разговор здесь: chat.stackoverflow.com/transcript/message/10324#10324 - person jweyrich; 17.10.2010
comment
@SkypeMeSM: только что нашел проект, который может вас заинтересовать. Прочитайте эту конкретную тему: zorp-unoff.sourceforge.net/faq-4 .html#ss4.5 - person jweyrich; 17.10.2010
comment
@jweyrich: Спасибо за ссылку. 'tproxy', похоже, является патчем iptable, который требует, чтобы после установки ядро ​​linux снова скомпилировалось. К сожалению, это не очень удобно для моего приложения. - person SkypeMeSM; 18.10.2010
comment
Можем ли мы каким-то образом использовать IP-маршруты или туннельный интерфейс?? - person SkypeMeSM; 18.10.2010