= Сообщение: 326 из 10753 ====================================== RU.UNIX.BSD = От : Eugene Grosbein 2:5006/1 26 Sep 13 02:56:13 Кому : All 26 Sep 13 02:56:13 Тема : kern/182212: mppc/mppe в FreeBSD FGHI : area://RU.UNIX.BSD?msgid=grosbein.net+213a717e = Кодировка сообщения определена как: CP866 ================================== Ответ: area://RU.UNIX.BSD?msgid=grosbein.net+ad930e23 ============================================================================== Привет!
При использовании 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!
4094 в случае переупорядовичивания пакетов и меньшее число при потерях. Такое "решение" было мотивировано "защитой от DoS" в 2000-м году, из которого растут ноги этого кода.
Попалась мне пара машин под FreeBSD с mpd, которые устанавливают между собой l2tp-туннель, который через несколько секунд после начала работы стабильно воспроизводит эту проблему, если не включать опцию l2tp dataseq из-за переупорядочивания UDP-пакетов на трассе. Сделал патч для ng_mppc.c, который вводит три новых sysctl:
net.graph.mppe.block_on_max_rekey - блокировать ноду по достижению порога ошибок (1) или нет (0), по умолчанию не блокировать (то есть, с примененным патчем никаких настроек для исправления проблемы делать не надо);
net.graph.mppe.log_max_rekey - писать ли в лог сообщения о достижении порога (1) или нет (0), по умолчанию 1;
net.graph.mppe.max_rekey - задаёт порог (1000 по умолчанию, как и без патча).
Вместо блокирования mpd производит сброс протокола CCP в туннеле и работа его продолжается, а в логе mpd на одной стороне появляется строка (если, конечно, включено логирование ccp):
CCP: SendResetReq #3 link 0 (Opened)
Hа второй стороне туннеля:
CCP: rec'd Reset Request #3 (Opened)
Провел тест: запустил ping длинными пакетами по 10 пакетов в секунду, поймал момент превышения порога - в момент сброса CCP потерялось 4 пакета, то есть заминка в работе туннеля составила около 0.4 секунды, вместо полной блокировки.