[Решено] recvfrom не принимает воспроизводимые UDP пакеты

Для новичков как вообще в Linux, так и в конкретной теме, к которой относится вопрос.

Модератор: Bizdelnick

MiK13
Сообщения: 1311
ОС: Linux Debian

[Решено] recvfrom не принимает воспроизводимые UDP пакеты

Сообщение MiK13 »

Когда-то для проверки передачи информации по UDP написал две программы:
send_udp -- читает целые числа, формирует из них массив из char или short и отправляет по UDP.
view_udp -- по recvfrom читает данные и печатает их по заданному формату.
В основном проблем не было. Но вот написал такой скрипт:

Код: Выделить всё

for((N=0;N<100;N++)) ; do
  echo $N $N $N $N $N $N $N $N $N $N $N $N $N $N $N $N $N $N $N $N | send_udp_w 255.255.255.255 12321 b
  sleep 0.1
done
Запускаю его и команда view_udp 12321 0:%hd .20 показывает передаваемые данные.
tcpdump тоже показывает.
Потом я эти данные записываю в файл командой tcpdump -n -w/dev/shm/t1.cap udp and port 12321 и воспроизвожу их командой
tcpreplay -i enp3s0 /dev/shm/t1.cap
tcpdump показывает, что UDP пакеты в сети есть, а view_udp ничего не выводит.

В чём может быть причина?
Последний раз редактировалось MiK13 14.09.2026 17:12, всего редактировалось 1 раз.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3360
ОС: Gentoo

Re: recvfrom не принимает воспроизводимые UDP пакеты

Сообщение ormorph »

Если IP сервера и клиента принадлежат одной и той же машине, то ни чего не получится, ядро будет блокировать raw-сокеты идущие на локальном компе. Если передавать на другой комп, то всё получится.
Спасибо сказали:
MiK13
Сообщения: 1311
ОС: Linux Debian

Re: recvfrom не принимает воспроизводимые UDP пакеты

Сообщение MiK13 »

ormorph писал(а):
11.09.2026 18:32
Если IP сервера и клиента принадлежат одной и той же машине, то ни чего не получится, ядро будет блокировать raw-сокеты идущие на локальном компе. Если передавать на другой комп, то всё получится.
Проверю в понедельник на работе на двух компьютерах,

Но,, с другой стороны, когда программа send_udp отправдяет UDP пакеты (на 255.255.255.255) их видит (на том же компьютере) и view_udp, и tcpdump.
Но когда эти же пакеты отправляет tcpreplay, их почему-то видит только tcpdump.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3360
ОС: Gentoo

Re: recvfrom не принимает воспроизводимые UDP пакеты

Сообщение ormorph »

MiK13 писал:
12.09.2026 20:52
Но,, с другой стороны, когда программа send_udp отправдяет UDP пакеты (на 255.255.255.255) их видит (на том же компьютере) и view_udp, и tcpdump.
Но когда эти же пакеты отправляет tcpreplay, их почему-то видит только tcpdump.
Потому что пакеты доходят до интерфейса, а вот до сервера уже ядро не передаёт их. Так же себя ведёт следующий код на python как и с tcpreplay и работает быстрее.
Spoiler

Shell

from scapy.all import rdpcap, sendp

packets = rdpcap('test.db')
sendp(packets, iface="enp2s0")
print(f"Успешно отправлено пакетов: {len(packets)}")
На другой комп передать можно а вот на одном и том же компе нет. Просто send_udp отправляет сообщение через обычный сокет, а вот tcpreplay через raw soket, man raw. Судя по всему ядро знает что отправлено через raw вот и блокирует. Но если отправить на другой комп, то пакеты уже будут серверной стороной обработаны по другому, так как он не знает что было отправлено через raw.
Как вариант можно отправить через обычный сокет, тогда отправка пройдёт:
Spoiler

Shell

import socket
from scapy.all import rdpcap, IP, UDP

SERVER_PORT = 1060
INTERFACE = b"lo"
SERVER_ADDR = "127.0.0.1"
PCAP_FILE = "test.db"

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, INTERFACE)
packets = rdpcap(PCAP_FILE)
packets_sent = 0

for pkt in packets:
if pkt.haslayer(IP) and pkt.haslayer(UDP) and pkt[UDP].dport == SERVER_PORT:
payload = bytes(pkt[UDP].payload)
sock.sendto(payload, ("SERVER_ADDR", SERVER_PORT))
packets_sent += 1

print(f"Успешно доставлено на локальный сервер: {packets_sent} пакетов.")
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3360
ОС: Gentoo

Re: recvfrom не принимает воспроизводимые UDP пакеты

Сообщение ormorph »

Посмотрел точнее этот вопрос. Тут как раз дело в том, что нельзя сгенерировать нормальный дамп пакетов, на локальном компе. Что нибудь да будет не то, контрольная сумма mac и т.п. Это можно посмотреть по выводу perf и dropwatch. Ни какие виртуальные интерфейсы тут не помогают. Как результат ядро делает проверку и блокирует эти пакеты, так как они не проходят проверку. Если передаёшь на другой комп, то все данные дампа соответствуют и это можно воспроизвести. Т.е. применение raw сокетов на локальной машине не получится, так как данные передаваемые ими не пропустит ядро.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3360
ОС: Gentoo

Re: recvfrom не принимает воспроизводимые UDP пакеты

Сообщение ormorph »

Хм, даже если со всеми данными в полученном pcap файле с помощью tcpdump всё будет нормально, ядро всё равно заблокирует пакет на локальной машине. Так как raw socket отсылает готовые сигнатуры с обратным адресом. Ядро начинает сравнивать данные и видит что они исходят от локального интерфейса, при этом в очереди отправлений этот адрес отсутствует, как результат ядро блокирует такой пакет, который рассматривается как подмена адреса. При передаче на удалённую машину такого не происходит. Единственный метод реализовать это на локальной машине, это реализовать отправку через обычный сокет. Пример уже есть выше на python. Его можно переписать, что бы конечный адрес и порт определялся автоматически из дампа pcap, пакет scapy позволяет полностью разобрать это.
Спасибо сказали:
MiK13
Сообщения: 1311
ОС: Linux Debian

Re: recvfrom не принимает воспроизводимые UDP пакеты

Сообщение MiK13 »

Попросил племянника помочь разобраться.
Он прислал ответ (видимо от OpenCode):
Причин две, и каждая сама по себе достаточна.
1. tcpreplay не доставляет пакеты локальному стеку. Он пишет кадры в PF_PACKET-сокет интерфейса, и они уходят в провод. Для ядра это исходящие кадры, а не входящие, поэтому локальный UDP-сокет их никогда не получит. tcpdump снимает пакеты с интерфейса в обе стороны и поэтому их видит. При живом send_udp_w broadcast-пакет ядро само дублирует на локальный приём, поэтому view_udp на той же машине его показывает.
Это совпадает с ответом
ormorph писал(а):
11.09.2026 18:32
Если IP сервера и клиента принадлежат одной и той же машине, то ни чего не получится, ядро будет блокировать raw-сокеты идущие на локальном компе. Если передавать на другой комп, то всё получится.
Попытался принять на другом компьютере -- тоже не получилось. Это оказалось из-за второй причины:
В t1.pcap битые UDP-контрольные суммы. Сетевая карта считает контрольную сумму сама (TX checksum offload), а tcpdump захватывает исходящий пакет до этого.
Через man tcpreplay-edit узнал, что есть опция -C, которая исправляет контрольные суммы.
Запустил её с этой опцией -- view_udp на локальном компьютере по-прежнему не показывает. А на другом показывает.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3360
ОС: Gentoo

Re: [Решено] recvfrom не принимает воспроизводимые UDP пакеты

Сообщение ormorph »

MiK13 писал:
14.09.2026 17:11
Он пишет кадры в PF_PACKET-сокет интерфейса,
Я про то и сказал, оно работает с raw сокетами(необработанные), это то же самое, т.е. пакеты направляются сразу на интерфейс(труба, канал) минуя сетевой сетевой стек ядра.
MiK13 писал:
14.09.2026 17:11
Это оказалось из-за второй причины:
У меня сразу всё прошло нормально на другую машину. Странно что это понадобилось, если дамп сгенерировался нормально то этого не должно было потребоваться. Ну да ладно.
Спасибо сказали: