Как перехватить IP-пакеты, идущие к ядру Linux

Мне нужно создать сессию TCP "вручную", без использования функции connect(). Я пытался использовать сокеты RAW. Но в этом случае я получаю только копии входящих IP-пакетов. Исходные входящие пакеты проскальзывают к ядру, и оно генерирует ответный пакет ACK, который повреждает мой протокол.

Далее, вариант 2, я могу написать драйвер интерфейса виртуального eth (модуль ядра) и маршрутизировать входящий трафик на него с помощью iptables. Но на аппарате стоит пропатченное неоригинальное (не ванильное) ядро. Нормальная связка модуля с ядром невозможна.

Вариант 3. Так же пробовал не назначать IP адрес NIC интерфейсу. В этом случае модуль сетевого уровня TCP/IP в ядре не активирован, и можно генерировать и получать произвольные IP-пакеты на канальном (ethernet) уровне, используя тип домена сокета PF_PACKET в функции socket(). Но в это время любые другие приложения, использующие протокол TCP/IP, работать не могут.

Как можно решить эту проблему другими способами?

Было бы неплохо, если бы можно было перехватывать пакеты, идущие от сетевого интерфейса к ядру, то есть перехватывать буфер SKBuf. Но я не знаю, как это реализовать.

"Мне нужно создать сеанс TCP "вручную"" - почему? Что вы планируете реализовать, что TCP еще не обрабатывает для вас? Для меня это звучит как XY-проблема. Чего вы действительно пытаетесь достичь?

Remy Lebeau 17.03.2022 23:02

@Remy Lebeau Мне нужно повторно отправить инкапсулированные TCP-пакеты, поступающие с других хостов, в виде UDP-пакета. Что-то вроде туннеля. Поэтому требуется, чтобы локальная машина действовала только как ретранслятор UDP(TCP-IP) -> IP.

asdo 18.03.2022 08:46

Звучит как довольно странная вещь для реализации. В любом случае, вы можете использовать XDP для перехвата исходного пакета до того, как он достигнет сетевого стека, и таким образом применить инкапсуляцию UDP.

Justin Iurman 18.03.2022 16:15

Включено ли ядро ​​CONFIG_VETH (встроенное или модульное)?

Ian Abbott 18.03.2022 17:12
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
24
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Судя по всему, вы пытаетесь создать туннель. Вместо того, чтобы пытаться захватить существующий интерфейс, правильный способ создать туннель — создать новый интерфейс, используя модуль ядра или TUN/TAP. Однако туннели обычно предназначены для приема трафика, генерируемого на машине, на которой запущено программное обеспечение туннеля, или, по крайней мере, маршрутизируемого через нее. Это означает, что вам также придется настроить ядро ​​для маршрутизации трафика в ваш туннель.

Вы можете создать новый интерфейс как TUN/TAP-интерфейс. Это похоже на виртуальный драйвер Ethernet, за исключением того, что вам не нужно писать новый модуль ядра. Он предназначен для тоннелей (отсюда и название).

Разница между TUN и TAP заключается в том, что TUN-интерфейс — это IP-интерфейс, который получает IP-пакеты от системы IP-маршрутизации ядра, а TAP-интерфейс получает Ethernet-пакеты (которые могут содержать IP-пакеты), поэтому в качестве альтернативы он может быть частью моста ( виртуальный коммутатор Ethernet, который смотрит только на заголовок Ethernet, а не на заголовок IP).

Я думаю, что для вашего сценария вам будет проще всего создать интерфейс TAP, а затем создать мост (виртуальный коммутатор Ethernet) между интерфейсом TAP и интерфейсом, к которому подключен другой хост. Ни одному из них не нужен IP-адрес — ядро ​​​​с радостью пропустит трафик Ethernet-уровня, не пытаясь обработать IP-информацию в пакете. Затем ваше программное обеспечение туннеля может эмулировать хост или туннелировать к реальному хосту, или делать то, что вы хотите.

Или в визуальном виде: Block diagram showing the system described above in a visual form

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

Другие вопросы по теме