LINUX.ORG.RU
решено ФорумAdmin

Почему происходит переотправка TCP-пакетов?

 , ,


1

4

Привет, ребята! Кто-нибудь может навести на мысль почему происходит переотправка TCP-пакетов? UDP-пакеты ходят хорошо. Отправитель и приёмник пакетов находятся на разных континентах земного шара. Отправка и приём сетевых пакетов на обоих концах осуществляются самописной программой, поэтому я смогу её видоизменить, если потребуется.

Снимок экрана «Вайршарка».

Файл «Вайршарка» целиком.

Пишите всё, о чём подумалось.

ИМХО, проще всего сравить дампы, одновременно снятые на обоих концах, чтобы было понятно, есть потери пакетов или нет.

Отправка и приём сетевых пакетов

Самописная программа только для организации тунеля или весь tcp-стек самописный?

mky ★★★★★
()
Ответ на: комментарий от mky

ИМХО, проще всего сравить дампы, одновременно снятые на обоих концах, чтобы было понятно, есть потери пакетов или нет.

Да, спасибо за наводку. Я написал свой канал сетевого обмена данными и сравнил прохождение сетевых пакетов открытым способом и через самонаписанный канал. Похоже на то, что из-за того, что я принимаю и отправляю данные из сетевой карты небольшими частями, то сетевой пакет разрезается на части и поэтому сначала уходит подтверждение «ACK», а следом за ним «PSH, ACK» с повторной отправкой TCP-пакета. Вечерком я попробую увеличить размер чтения и записи данных из сетевой карты и посмотрим изменится ли что-нибудь.

Самописная программа только для организации тунеля или весь tcp-стек самописный?

Всего лишь небольшая программа обмена данными по сети. До способностей Линуса Торвальдса мне еще далеко :-)

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

Вечерком я попробую увеличить размер чтения и записи данных из сетевой карты и посмотрим изменится ли что-нибудь.

Я увеличил размер буфера приёма сетевых пакетов с 2048-ми до 8192-х байт. Переотправок TCP-пакетов стало немного меньше.

Похоже на то, что или сетевая карта, или ядро «Линукса» объединяют разделённые на части IP-пакеты в один большой IP-пакет. В настройках аппаратной сетевой карты значение наибольшего размера сетевого пакета (Maximum Transmission Unit, MTU) у меня равно 1500 байт, а читаю из сокета я пакеты размером до 3750 байт. Тогда какого наибольшего размера может придти объединённый IP-пакет кто-нибудь знает?

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

разделённые на части IP-пакеты в один большой IP-пакет.

Это про дефрагментацию IP-пакета или про что? Несколько подряд IP-пакетов не становятся одним IP-пакетов, у каждого остаётся свой заголовок, где указан, в том числе, размер и т.д.

или сетевая карта, или ядро

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

а читаю из сокета я пакеты

Дак из сокета или из сетевой карты? Какой именно код читает/пишет пакеты?

mky ★★★★★
()
Ответ на: комментарий от mky

Это про дефрагментацию IP-пакета или про что?

Да. Похоже на то, что все дефрагментированные TCP-пакеты принимаются разом. Наверное, это даже хорошо, но тогда непонятно какого наибольшего размера может получиться этот собранный сетевой пакет?

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Pinkbyte

Теоретически TCP-пакет может быть до 64 килобайт размером. Но такого размера пакеты не всем оборудованием будут приняты даже в фрагментированном виде.

Уже хорошо, что гигабайты в фрагментированных TCP-пакетах не передаются.

Причина переотправок TCP-пакетов обнаружена: не проходит TLS-рукопожатие. Мой телефон отправляет запрос «Client Hello», а ответ от сервера «Server Hello» отсутствует. Причем ответа нет ни на моей стороне, ни на стороне зарубежного сервера.

Каким-либо образом возможно передавать и принимать данные в мировой сети без TLS? Если я подключусь не с телефона, а с компа? Или TLS сейчас везде присутствует?

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

Мой телефон отправляет запрос «Client Hello», а ответ от сервера «Server Hello» отсутствует. Причем ответа нет ни на моей стороне, ни на стороне зарубежного сервера.

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

Каким-либо образом возможно передавать и принимать данные в мировой сети без TLS? Если я подключусь не с телефона, а с компа? Или TLS сейчас везде присутствует?

Если речь о веб-сервере - то очевидно можно не использовать TLS. Не будут работать(или будут работать плохо) некоторые технологии(например те же Websocket), да и вообще я бы поверх такого соединения ничего важного не отправлял бы.

Если речь о каком-то другом протоколе/сервисе - надо читать его спецификацию. Есть сервисы, где TLS прибит гвоздями by design из-за безопасности и отломать его не получится(и не должно получаться).

Pinkbyte ★★★★★
()
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от Pinkbyte

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

Да. Мой канал сетевого обмена данными уже успешно обходит все незримые преграды.

Может быть такое, что TLS-сервер не подтверждает запрос «Client Hello» из-за того, что часовой пояс разный на телефоне, с которого изначально этот запрос уходит, и на зарубежном сервере, через который идет этот запрос и где ждут ответ? Похоже на то, что TLS-серверу что-то не нравится в моем запросе и поэтому он не отвечает.

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

Может быть такое, что TLS-сервер не подтверждает запрос «Client Hello» из-за того, что часовой пояс разный на телефоне, с которого изначально этот запрос уходит, и на зарубежном сервере, через который идет этот запрос и где ждут ответ?

Нет. В Linux/Android время хранится в UTC, а сдвиг на часовой пояс делается ТОЛЬКО для отображения клиенту. В Windows чуточку другая история с хранением, но по сути там тоже всё верно.

Похоже на то, что TLS-серверу что-то не нравится в моем запросе и поэтому он не отвечает.

Если есть возможность - сравни дамп трафика с клиента и с сервера. А то(если трафик не внутри VPN-а) возможно благодаря РКН первые TLS-пакеты туда обратно ходят, а потом тупо и пошло рубятся ответные пакеты от забугорного сервера - я такое неоднократно видел.

Pinkbyte ★★★★★
()
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от Pinkbyte

Если есть возможность - сравни дамп трафика с клиента и с сервера.

На зарубежный сервер ответ TLS-сервера «Server Hello» приходит. Я пока не понимаю того, что на зарубежном сервере, у его сетевой карты установлен максимальный размер пакета MTU (Maximum Transmission Unit) = 1500 байт, а на неё приходит ответ TLS-сервера размером 2508 байт с установленным флагом «Не фрагментировать» в свойствах его TCP-пакета. Размер MSS (Maximum Segment Size) при установке TCP-соединения согласован на 1240 байт на сервере.

Разве сетевые пакеты, размер которых превышает MTU с установленным флагом «Не фрагментировать», не должны отбрасываться маршрутизаторами и роутерами по пути следования? Как вообще этот ответ «Server Hello» смог придти мне на сервер?

Если при пробросе этого большого пакета на сетевую карту «wg0», у которой MTU = 1420 байт, я сброшу флаг «Не фрагментировать», то пакет может дойти успешно саморазделившись на части при отправке?

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

Я разделил в своей программе большой IP-пакет с ответом сервера «ServerHello» на два IP-пакета размером в 1420 и 1088 байт, чтобы уложить их в сетевую карту «Вайргарда» с MTU = 1420, и отправляю оба IP-пакета друг за другом в сетевую карту «Вайргарда» «wg0». Пакеты должны отправиться оба друг за другом.

Почему-то программа-обзорщик сетевого трафика «Вайршарк» не отображает первый разделённый сетевой пакет, а отображает только второй. На снимке второй разделённый IP-пакет это пакет с номером 37.

Кто-нибудь может подсказать почему «Вайршарк» не отображает первый разрезанный сетевой пакет? «Вайргардовская» сетевая карта «wg0» умеет соединять разделённые IP-пакеты?

Снимок экрана «Вайршарка»

Файл «Вайршарка»

Enthusiast ★★★
() автор топика
Последнее исправление: Enthusiast (всего исправлений: 1)
Ответ на: комментарий от peregrine

мало информации. смотри что на приём приходит, не только на отсылку, может РКН замедляет и половина пакетов не доходит и по отсутствию ответа пакеты летят повторно.

Выяснилось, что «вайргардовская» сетевая карта не умеет соединять разделенные IP-пакеты. Я увеличил MTU = 8192 на ней и трехкилобайтные ответы сервера «ServerHello» стали проходить. Однако повторные отправки TCP-пакетов сохранились. В причине этого я еще разбираюсь. Я попробую уменьшить MTU = 1380 на «вайргардовских» клиентах. Возможно, что сетевые пакеты при прохождении по сети разделяются и соединяются и поэтому возникают задержки доставки данных. Посмотрим.

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

Кто-нибудь знает каким образом можно увеличить выдержку времени между повторными отправками пакетов TCP?

0,45 секунды - к пользователю приходит ответ сервера «ServerHello».

1,30 секунды - ответ от пользователя с подтверждением получения «TCP ACK» отправляется на сервер.

0,79 секунды - сервер, не дождавшись ответа пользователя, повторно отправляет «TCP Retransmission - ServerHello».

Каким-то образом можно увеличить выдержку времени между переотправками TCP-пакетов в «Терминале»?

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

Судя по тому, что оно считается динамически [1] оно тебе не нужно и ты решаешь проблемы не на том уровне (вместо правки своего софта пытаешься под него подогнать Ядро).

[1] https://unix.stackexchange.com/questions/210367/changing-the-tcp-rto-value-in...

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

Судя по тому, что оно считается динамически [1] оно тебе не нужно и ты решаешь проблемы не на том уровне (вместо правки своего софта пытаешься под него подогнать Ядро).

Спасибо за совет. Конечно, лучше изменить выдержку времени в настройках сетевого сокета. Я подумаю над этим. Сначала проверить бы сетевой обмен в целом.

А я и не смогу, наверное, изменить выдержку времени в своём прикладном ПО. Я же принимаю сетевые пакеты с внешнего устройства, передаю их на свой сервер по защищённому каналу связи, а затем отдаю их по назначению на другой внешний сервер. То есть мой сервер не отправляет повторные ответы «ServerHello», а это делает внешний для меня сервер-ответчик из мировой сети. Тоже самое и мой телефон сам по себе шлёт запросы «ClientHello» и я вряд ли смогу изменить сетевые настройки этих запросов из своего ПО. Я же беру и отдаю уже готовые сетевые пакеты, а не порождаю их.

Тогда и выдержку времени переотправки TCP-пакетов нет смысла менять на сервере. Переотправляет-то TCP-пакет не мой сервер, а внешний для меня сервер назначения. Я смогу лишь отбрасывать «лишние» переотравки TCP-пакетов между телефоном и внешним сервером-ответчиком.

Enthusiast ★★★
() автор топика
Последнее исправление: Enthusiast (всего исправлений: 4)
Ответ на: комментарий от Enthusiast

С переотправкой TCP-пакетов я разобрался. Дело было в том, при установке TLS-соединения сервер назначения отправлял ответный сетевой пакет «ServerHello» большего размера, чем запросный пакет «ClientHello» с установленным флагом «Не разделять/Don’t fragment».

На моём сервере исходящие ICMP-сообщения отключены и поэтому эти большие входящие для сервера пакеты «ServerHello» превышали размер максимального IP-пакета (MTU) и отбрасывались сервером. Передоговора между серверами не было из-за отключенных ICMP-сообщений и уменьшения сетевых пакетов на дальнем сервере с последующей переотправкой не происходило. Задача решилась увеличением MTU до 8192 байт на ближнем сервере, сбросом флага «Не разделять/Don’t fragment» на входящих сетевых пакетах и уменьшением MTU до 1280 байт на клиентах «Вайргарда». Последнее действие сделано для того, чтобы при прохождении между континентами сетевые пакеты укладывались в стандартный MTU = 1500 байт со всеми «ускорениями» и не разделялись/соединялись для ускорения их прохождения между узлами мировой вычислительной сети.

Остались ещё два вопроса, которые решены, но, наверное, могли бы быть решены лучше.

  1. При приёме дальним сервером сетевых пакетов, которые предназначены для ближнего сервера, дальний сервер отвечает ICMP-пакетом с сообщением, что порт недоступен. Сейчас я просто отключил все исходящие ICMP-сообщения на дальнем сервере таким образом:
#!/bin/bash
sysctl --write net.ipv4.icmp_msgs_per_sec=0

Как-то можно отключить только ICMP-сообщения, что порт недоступен, а остальные ICMP-сообщения оставить? Сетевым фильтром «Iptables» отбрасывать? Это не даст лишнюю нагрузку на процессор в сравнении с теперешним способом отключения всех ICMP-сообщений?

  1. Чтобы при передаче сетевых пакетов с ближнего сервера на дальний сервер и пробросе их с дальнего сервера по назначению дальний сервер не сбрасывал TCP-соединение, отправляя по адресу назначения пакеты «TCP-RST» (дальний сервер не понимал, что TCP-пакеты пробрасываются сквозь него и решал, что это какие-то чужие пакеты и сбрасывал TCP-соединение), мне пришлось отбрасывать эти пакеты сетевым фильтром «Iptables» таким образом:
#!/bin/bash
iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP

Мне бы не хотелось следить и переоткрывать TCP-соединения ближнего сервера на дальнем сервере. Каким-то образом возможно сделать так, чтобы дальний сервер не сбрасывал чужое TCP-соединение, которое проходит сквозь него? То есть чтобы не загружать сетевой фильтр отбросом пакетов «TCP-RST» на дальнем сервере?

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

В итоге «Ютуб» работает в 4К@60 c HDR. Ближний сервер-шлюз работает на «Малине - 3» под «Убунтой - 24.04». Размер MTU опытным путём я увеличил до 1380 байт, чтобы «Ютуб» слал пакеты побольше без их разделения по пути следования.

Enthusiast ★★★
() автор топика
Ответ на: комментарий от Enthusiast

увеличением MTU до 8192 байт

:facepalm: спроси у gpt брат, не мучай лорчик; если ты имеешь пакеты больше mtu значит, кто-то по дороге к тебе включил tso\gso offload, того админа отпинать по жопе

anonymous
()
Ответ на: комментарий от anonymous

:facepalm: спроси у gpt брат, не мучай лорчик; если ты имеешь пакеты больше mtu значит, кто-то по дороге к тебе включил tso\gso offload, того админа отпинать по жопе.

Между континентами сетевые IP-пакеты у меня идут размером MTU = 1500 байт. Я увеличил размер MTU = 8192 байт на сетевой карте «Вайргарда» из-за того, что при программной обработке входящих сетевых данных из сокета в моём ПО все разделённые IP-пакеты вычитываются уже в собранном виде. То есть два разделённых IP-пакета каждый по 1500 байт читаются единым IP-пакетом размером 3000 байт из сетевого сокета. Насколько я понял, ядро «Линукса» не позволяет читать разделённые сетевые пакеты. Именно из-за этого я увеличил размер MTU = 8192 байта, чтобы эти собранные IP-пакеты влезли в сетевую карту «Вайргарда», которая сама не умеет разделять эти уже собранные сетевые пакеты и отбрасывает их, если размер сетевого IP-пакета превышает размер MTU на сетевой карте «Вайргарда». Такой «крупняк» приходит лишь при установке и подтверждении TLSv3-соединения, а остальные TCP-пакеты приходят лишь чуть более значения MSS (Maximum Segment Size), которое выставляется клиентом «Вайргарда» чуть более клиентского MTU = 1380 байт.

Enthusiast ★★★
() автор топика