dadv: (chuck)
[personal profile] dadv

При использовании mpd для организации pptp/l2tp-туннелей чаще всего применяют MPPC и MPPE для компрессии и шифрования трафика туннеля. При этом mpd использует ядерную netgraph-ноду ng_mppc, реализующую нужные алгоритмы. У кода в этой ноде есть одно ужасное свойство. Из-за переупорядочивания или потери сжатых туннельных пакетов у алгоритмов может произойти срыв синхронизации, что приводит к необходимости сторонам произвести re-keying: пересоздать криптографические ключи. Код ng_mppc считает эту процедуру настолько "тяжелой" в смысле загрузки CPU, что при накоплении определенного количества ошибок тупо отключает работу этого туннеля. Внешне это выглядит так: туннель установлен, системные интерфейсы выглядят "как живые", только вот полезный трафик по туннелю ходить перестаёт совсем и требуется переустановка туннеля для возобновления нормальной работы - до следующего срыва. При этом в dmesg попадает сообщение такого вида:

ng_mppc_decompress: too many (4094) packets dropped, disabling node 0xc7020900!

Такое "решение" было мотивировано "защитой от DoS" в 2000-м году, из которого растут ноги этого кода. Не стану обсуждать разумность такого решения в то время, но теперь, когда FreeBSD почти всегда работает на машинах с безумными мегагерцами и гигагерцами, хотелось бы более стабильной работы туннелей.

Попалась мне пара машин под FreeBSD с mpd, которые устанавливают между собой l2tp-туннель, который через несколько секунд после начала работы стабильно воспроизводит эту проблему. Сделал патч для ng_mppc.c, который вводит новый sysctl net.graph.mppe_max_rekey (а так же loader tunnable) со значением по умолчанию 1000 - тот самый порог, после которого непатченная нода ng_mppc прекращает работать. Если присвоить этому sysctl отрицательное значение, то код перестанет блокировать свою работу по достижении порога, а только будет писать в лог указанное выше сообщение. Вместо блокирования туннеля в этом случае mpd производит сброс протокола CCP в туннеле и работа его продолжается, а в логе mpd на одной стороне появляется строка (если, конечно, включено логирование ccp):

CCP: SendResetReq #3 link 0 (Opened)

На второй стороне туннеля:

CCP: rec'd Reset Request #3 (Opened)

Провел тест: запустил ping длинными пакетами по 10 пакетов в секунду, поймал момент превышения порога - в момент сброса CCP потерялось 4 пакета, то есть заминка в работе туннеля составила около 0.4 секунды, вместо полной блокировки.

Если у вас нода ng_mppc.ko подгружается динамически при старте mpd (а не вкомпилирована статически в ядро), то net.graph.mppe_max_rekey=-1000 нужно писать в /boot/loader.conf, а не в /etc/sysctl.conf, так как в момент обработки sysctl.conf при загрузке системы переменной net.graph.mppe_max_rekey ещё не будет существовать. loader.conf задаёт для неё значение по умолчанию, которое ng_mppc использует при своей инициализации.

Применять патч:

fetch http://www.grosbein.net/freebsd/patches/ng_mppc.c.diff
cd /usr/src
patch < /path/to/ng_mppc.c.diff

После этого, если ng_mppc статически собирается с ядром, нужно пересобрать ядро. А если он подгружается динамически, то делаем так:

cd sys/modules/netgraph/mppc
make obj depend && make all install

После чего можно выгрузить модуль командой kldunload ng_mppc (предварительно остановив mpd, если он запущен) и загрузить его заново: kldload ng_mppc.

Update: обновил патч (URL тот же). Вместо одного sysctl net.graph.mppe_max_rekey вводится три:

  • net.graph.mppe.block_on_max_rekey - блокировать ноду по достижению порога ошибок (1) или нет (0), по умолчанию не блокировать (то есть, с примененным патчем никаких настроек для исправления проблемы делать не надо);
  • net.graph.mppe.log_max_rekey - писать ли в лог сообщения о достижении порога (1) или нет (0), по умолчанию 1;
  • net.graph.mppe.max_rekey - задаёт порог (1000 по умолчанию, как и без патча).

Update: Патч принят в основное дерево и даже бекпортирован в 10-STABLE, 9-STABLE и 8-STABLE. Будет в 9.3 и в 10.1. Спасибо Александру Мотину (mav).

Date: 2013-09-13 05:15 (UTC)
From: [identity profile] blacklion.livejournal.com
У меня давно зреет тот же вопрос.

Date: 2013-09-18 20:02 (UTC)
From: [identity profile] dadv.livejournal.com
Разродился PR'ом: http://www.freebsd.org/cgi/query-pr.cgi?pr=182212

Date: 2014-06-05 10:41 (UTC)
From: [identity profile] dadv.livejournal.com
Commited & MFC'd вплоть до восьмерки.

Profile

dadv: (Default)
Choose your future

July 2024

M T W T F S S
12 34567
891011121314
15161718192021
22232425262728
293031    

Tags

Style Credit

Powered by Dreamwidth Studios