Модуль ядра Linux. Виртуальный сетевой интерфейс.

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение Olej » 04 фев 2013, 15:53

mcrandy писал(а):Для меня это стало первым шагом. Мне удалось выполнить преобразование данных на уровне ядра на одной стороне, затем выполнить обратное преобразование на другой стороне и получить исходное сообщение.
Ну это то как-раз понятно и ожидаемо.

mcrandy
Активист
Сообщения: 18
Зарегистрирован: 21 янв 2013, 12:51
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение mcrandy » 07 фев 2013, 15:31

В настоящий момент мне удалось применить функции шифрования и передать зашифрованное сообщение.
Шифрую все тело вместе с TCP заголовком. И пока пытаюсь расшифровать все это при приеме.

Сразу предвижу проблему. Для того чтобы зашифровать что то, мне нужно сначала выровнять его длину по модулю 8.

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

enc_pkt_len = ((tcp_pktlen/8+(tcp_pktlen%8?1:0))*8);
Это значит что длина передаваемого пакета может увеличиться. И я боюсь представить как на это отреагирует вся сетевая подсистема :-?
И что произойдет, когда пакет превысит размер, установленный MTU?
Хорошо, если где то после моего модуля ядра пакет пройдет проверку и если его размер превысит допустимый MTU, то сработает механизм фрагментации IP.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение Olej » 07 фев 2013, 16:50

mcrandy писал(а):В настоящий момент мне удалось применить функции шифрования и передать зашифрованное сообщение.
Шифрую все тело вместе с TCP заголовком. И пока пытаюсь расшифровать все это при приеме.
А зачем "вместе с TCP заголовком"?
Я так подозреваю, что из-за опасений разрушить контрольную сумму ... которую добавляют некоторые реализации (иногда, не часто) стека TCP/IP, а другие реализации не добавляют (достаточно часто).
mcrandy писал(а): Сразу предвижу проблему. Для того чтобы зашифровать что то, мне нужно сначала выровнять его длину по модулю 8.

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

enc_pkt_len = ((tcp_pktlen/8+(tcp_pktlen%8?1:0))*8);
Это значит что длина передаваемого пакета может увеличиться.
Совсем не очевидно почему это так... Это зависит от того метода шифрования который вы выбрали?
И "выравнивание" вовсе не эквивалентно "изменение длины" - вы можете делать своё шифрование не по месту, а в промежуточном буфере, выровненном на 8.
А если так боитесь за производительность, и хотите это делать по месту (прямо в буфере сокета), то поищите другой алгоритм шифрования.
mcrandy писал(а): И я боюсь представить как на это отреагирует вся сетевая подсистема :-?
Это плохие эксперименты :-(
mcrandy писал(а): И что произойдет, когда пакет превысит размер, установленный MTU?
Хорошо, если где то после моего модуля ядра пакет пройдет проверку и если его размер превысит допустимый MTU, то сработает механизм фрагментации IP.
Вы решили это делать на сетевом уровне (L3), и я не думаю, что после этого отработает какой-то механизм, производящий сегментацию - IP пакет уже сформирован, сегментация под MTU (если она была нужна) уже сделана. Хотя MTU - это параметр, задаваемый вам с уровня L2, из характеристик интерфейса. Можете попробовать установить меньшее значение MTU для сетевого интерфейса (настройками, конфигурацией), чтобы иметь запас относительно реальных возможностей оборудования.

mcrandy
Активист
Сообщения: 18
Зарегистрирован: 21 янв 2013, 12:51
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение mcrandy » 09 фев 2013, 13:11

А зачем "вместе с TCP заголовком"?
Я так подозреваю, что из-за опасений разрушить контрольную сумму ... которую добавляют некоторые реализации (иногда, не часто) стека TCP/IP, а другие реализации не добавляют (достаточно часто).
Да, в первую очередь из за контрольной суммы. Я был уверен что она всегда включена. Ведь как тогда установить целостность полученного пакета?
Совсем не очевидно почему это так... Это зависит от того метода шифрования который вы выбрали?
И "выравнивание" вовсе не эквивалентно "изменение длины" - вы можете делать своё шифрование не по месту, а в промежуточном буфере, выровненном на 8.
А если так боитесь за производительность, и хотите это делать по месту (прямо в буфере сокета), то поищите другой алгоритм шифрования.
А я и шифрую в отдельном буфере, но потом я делаю memcpy() обратно в пространство пакета. И он все равно увеличится.
Вы решили это делать на сетевом уровне (L3), и я не думаю, что после этого отработает какой-то механизм, производящий сегментацию - IP пакет уже сформирован, сегментация под MTU (если она была нужна) уже сделана. Хотя MTU - это параметр, задаваемый вам с уровня L2, из характеристик интерфейса.
Логично. Тогда я думаю смогу и сам вызвать функции фрагментации.
Можете попробовать установить меньшее значение MTU для сетевого интерфейса (настройками, конфигурацией), чтобы иметь запас относительно реальных возможностей оборудования.
Интересная идея, тоже стоит попробовать.

mcrandy
Активист
Сообщения: 18
Зарегистрирован: 21 янв 2013, 12:51
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение mcrandy » 09 фев 2013, 13:57

На данный момент получилось у меня и расшифровать принятый пакет.
Но я шифровал только маленький поток информации - 1 килобайт. Т.е. только один пакет.

Вот так можно изобразить пространство пакета:
Изображение

Packet data - это сам пакет. В зависимости от того на каком уровне в данный момент находится skb, в этом пространстве записана различная информация, включая заголовки разных уровней и сами данные*

Изображение

Вот так выглядит это пространство после прохождения skb через протокол IP.

Изображение

Далее skb проходит через мой модуль ядра и я шифрую пакет:

Изображение

crypt header - мой заголовок. в нём 2 поля: флаг, по которому я определяю что пришел зашифрованный пакет и длина исходного tcp пакета.
headroom и tailroom - свободное пространство переда пакетом и после него соответственно.
Пока пакет был меньше, чем разрешает MTU (<1500) все было нормально, мне всегда хватало tailroom, чтобы поместить в skb увеличенный на 6 байт пакет после шифрования и добавления криптозаголовка.
Но когда появляется пакет, равный по размеру MTU - 1500 байт, то tailroom у него всегда 0. И мне не хватает места...
Я находил разные функции для увеличения, резервирования пространства headroom, но нет ни одной для tailroom...
Я пока в раздумии что с этим делать...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение Olej » 09 фев 2013, 14:17

mcrandy писал(а):Да, в первую очередь из за контрольной суммы. Я был уверен что она всегда включена. Ведь как тогда установить целостность полученного пакета?
Нет, во многих реализациях TCP/IP стека контрольная сумма именно TCP не подсчитывается и не контролируется (из соображений скорости?).
Но это не значит, что можно рассчитывать на её наличие или отсутствие.
mcrandy писал(а): А я и шифрую в отдельном буфере, но потом я делаю memcpy() обратно в пространство пакета. И он все равно увеличится.
Не понимаю!
Большинство алгоритмов криптографирования (даже если вам нужна такая высокая криптостойкость) построены как алгоритмы шифрования байтового потока. И непонятно, почему в них при входном сообщении длины N должны вырабатываться выходные сообщения длины >N? Конечно, могут быть алгоритмы, которые меняют длину ... но зачем выбирать такие алгоритмы?

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение Olej » 09 фев 2013, 14:27

mcrandy писал(а): crypt header - мой заголовок. в нём 2 поля: флаг, по которому я определяю что пришел зашифрованный пакет и длина исходного tcp пакета.
Зачем? Совершенно непонятно!

1. Зачем флаг зашифрованного пакета? Ведь у вас другой сетевой интерфейс, отличающийся по IP (!) от того интерфейса, который соответствует физическому устройству. Шифрованные пакеты, приходящие на интерфейс физического устройства, будут восприниматься как мусор (на уровне структуры TCP пакета) и уничтожаться. То же самое будет происходить на любом стороннем сетевом интерфейсе недоброжелателя, от которого вы шифруете данные. Когда же TCP-поток направлен (по IP!) на интерфейс для приёма шифрованных данных - они будут благополучно расшифровываться.

2. А "длина исходного tcp пакета" мне вообще совершенно непонятно... :-o
mcrandy писал(а): headroom и tailroom - свободное пространство переда пакетом и после него соответственно.
Пока пакет был меньше, чем разрешает MTU (<1500) все было нормально, мне всегда хватало tailroom, чтобы поместить в skb увеличенный на 6 байт пакет после шифрования и добавления криптозаголовка.
Но когда появляется пакет, равный по размеру MTU - 1500 байт, то tailroom у него всегда 0. И мне не хватает места...
Я находил разные функции для увеличения, резервирования пространства headroom, но нет ни одной для tailroom...
Какие функции для увеличения headroom?

P.S. Вопрос из любопытства:
- а почему вы стали сразу рассматривать собственное шифрование на уровне TCP/IP стека,
- не изучалась возможность использования чего-то из существующих механизмов secure IP?

mcrandy
Активист
Сообщения: 18
Зарегистрирован: 21 янв 2013, 12:51
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение mcrandy » 14 фев 2013, 11:51

Не понимаю!
Большинство алгоритмов криптографирования (даже если вам нужна такая высокая криптостойкость) построены как алгоритмы шифрования байтового потока. И непонятно, почему в них при входном сообщении длины N должны вырабатываться выходные сообщения длины >N? Конечно, могут быть алгоритмы, которые меняют длину ... но зачем выбирать такие алгоритмы?
Не я выбираю алгоритм шифрования. В последствии я должен сделать возможность конфигурирования для выбора алгоритма шифрования из userspace.
Но пока я использую ГОСТ-28147-89. И перед тем как подать блок данных в функцию шифрования, я должен выровнять его по модулю 8.
P.S. Вопрос из любопытства:
- а почему вы стали сразу рассматривать собственное шифрование на уровне TCP/IP стека,
- не изучалась возможность использования чего-то из существующих механизмов secure IP?
Собственно по этой же причине и создаем собственное шифрование... Необходимо применять отечественные алгоритмы :-(
Зачем? Совершенно непонятно!

1. Зачем флаг зашифрованного пакета? Ведь у вас другой сетевой интерфейс, отличающийся по IP (!) от того интерфейса, который соответствует физическому устройству. Шифрованные пакеты, приходящие на интерфейс физического устройства, будут восприниматься как мусор (на уровне структуры TCP пакета) и уничтожаться. То же самое будет происходить на любом стороннем сетевом интерфейсе недоброжелателя, от которого вы шифруете данные. Когда же TCP-поток направлен (по IP!) на интерфейс для приёма шифрованных данных - они будут благополучно расшифровываться.
Да, пожалуй флаг лишний... Но "местные" криптографы сказали что у меня все равно будет какая то служебная информация и собственный заголовок точно потребуется. Так что пока я записал хоть какой то заголовок.
2. А "длина исходного tcp пакета" мне вообще совершенно непонятно...
В функцию, которая дешифрует блок данных я должен подать исходную длину блока.

mcrandy
Активист
Сообщения: 18
Зарегистрирован: 21 янв 2013, 12:51
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение mcrandy » 14 фев 2013, 12:15

Дело в том, что мне все равно придется как то увеличивать пакет. Сейчас общался с "местным" криптографом и он сказал что у нас должна быть возможность подписи, помимо шифрования, а это значит что надо каждый пакетик подписывать, а на приемной стороне проверять подпись. Для этого нужно пересылать много служебной информации (не меньше 200 байт на каждую посылку) :-o

Поэтому я хочу сейчас понять, возможно ли как то увеличивать пересылаемый пакет? Или за ранее уменьшить его максимальный размер для последующего увеличения? Или увеличить, а потом раздробить механизмом ip fragmentation?

На сколько я понимаю, при отправке буфер сокета skb создается где то на уровне TCP или выше и именно в этот момент, на основе MTU рассчитывается размер области в skb для пакета.
Я попробовал уменьшить mtu до 1400 через конфигурацию интерфейса, но пользы мне это не принесло. Уменьшился как и пакет, так и область под него в skb.
Какие функции для увеличения headroom?
Функции для работы с skb.
Например skb_realloc_headroom(skb, newheadroom) - создает новый skb c начальной областью равной newheadroom и копирует данные старого skb в новый.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Модуль ядра Linux. Виртуальный сетевой интерфейс.

Непрочитанное сообщение Olej » 14 фев 2013, 18:04

mcrandy писал(а):Дело в том, что мне все равно придется как то увеличивать пакет. Сейчас общался с "местным" криптографом и он сказал что у нас должна быть возможность подписи, помимо шифрования, а это значит что надо каждый пакетик подписывать, а на приемной стороне проверять подпись. Для этого нужно пересылать много служебной информации (не меньше 200 байт на каждую посылку) :-o

Поэтому я хочу сейчас понять, возможно ли как то увеличивать пересылаемый пакет?
Описывайте что у вас будет получаться (?).
Я тоже подключусь.

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 4 гостя