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-12 22:14 (UTC)
From: [identity profile] dmarck.livejournal.com
Женя! Вот почему вы все свои наработки не анонсируете как следует, а? ;)

где, скажем, пост в -net@?

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

Date: 2013-09-13 05:46 (UTC)
From: [identity profile] chin-smoker.livejournal.com
Вы Бог!

Date: 2013-09-13 07:37 (UTC)
From: [identity profile] spiage.livejournal.com
Жень, с Праздником!!!

Date: 2013-09-18 20:00 (UTC)
From: [identity profile] dadv.livejournal.com
Делалось ночью и был очень уставший, чтобы ещё писать по-английски. Да и первоначальная версия патча самому не очень нравилась. Подрихтовал и закинул в PR: http://www.freebsd.org/cgi/query-pr.cgi?pr=182212

Date: 2013-09-18 20:02 (UTC)
From: [identity profile] dadv.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: 2013-09-19 15:17 (UTC)
From: [identity profile] dmarck.livejournal.com
Ура, спасибо!

Date: 2013-12-01 09:39 (UTC)
From: [identity profile] svat.livejournal.com
Спасибо за пост + патч!
Столкнулся с аналогичной проблемой, решение применил, будем посмотреть... :)

Date: 2013-12-22 20:37 (UTC)
From: [identity profile] dadv.livejournal.com
> Спасибо за пост + патч!
> Столкнулся с аналогичной проблемой, решение применил, будем посмотреть... :)

И как результат?

Date: 2013-12-23 06:54 (UTC)
From: [identity profile] svat.livejournal.com
Результат - положительный.
За прошедший период эффект "зависания" проявился только один раз, и то без характерных для этого случая сообщений в логах mpd-сервера. Хотя до применения патча эффект проявлял себя стабильно пару-тройку раз в неделю.
Списал на "подземный стук", особо не разбираясь, т.к. с хостом в это время случались и другие нештатные ситуации.

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

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

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