пятница, 19 декабря 2008 г.

Обновление OpenVPN до версии 2.1

Зачем это понадобилось? Раньше на маршрутизаторе работал в режиме сервера старенький openvpn-2.0.7 используя протокол udp. Работал он хорошо, но была у него проблемка. Маршрутизатор подключен к нескольким провайдерам и соответственно у него имеется несколько сетевых интерфейсов. Так вот, пока у openvpn-сервера отсутствовали подключения openvpn-клиентов, то первый клиент мог подключится через любой сетевой интерфейс. Но чуть появлялось первое клиентское подключение, то все последующие соединения могли быть установлены только через тот же самый интерфейс, т.е. через того же самого провайдера.

Формулируя другими словами, openvpn сервер версии 2.0 не может принимать клиентские udp подключения через разные сетевые интерфейсы.

Предполагаемые варианты решения:

  1. Вместо udp использовать протокол tcp. Но во-первых, существует точка зрения что пропускать протокол tcp поверх протокола tcp это плохо. Во-вторых, хотелось бы избежать изменений в конфигурационных файлах клиентов, потому что их много и некоторые находятся в других городах.
  2. Использовать bridging. По непроверенным данным, если несколько сетевых интерфейсов объединить в один мост, данной проблемы не наблюдается. Зато появляются другие, навроде свободного прохождения широковещательных пакетов между клиентами.
  3. Обновить openvpn на маршрутизаторе до версии 2.1. В описании новых возможностей прямо говорится о решении данной проблемы: "multihome feature to enable UDP-based multihoming of the server on multiple interfaces". Единственный недостаток, на текущий момент OpenVPN 2.1 имеет статус бета-версии 2.1rc15.

Еще раз подчеркну, что выше перечислены только предполагаемые варианты решения. Фактически был опробован и оставлен в работе только вариант №3.

Подробно не буду останавливаться на процессе компиляции openvpn, т.к. пакетная система для каждого дистрибутива linux своя. Универсальный же способ из configure, make и make install, которым грешат многие статьи, гарантированно превращает вашу файловую систему в помойку. Для используемой у меня Slackware я уже описывал процесс пересборки tgz пакетов, как раз на примере openvpn. Всё что необходимо сделать — это выкачать свежий архив исходников и поменять версию openvpn в slackbuild-скрипте.

Обновление openvpn-сервера в целом прошло гладко. Единственное дополнение пришлось внести в конфигурационный файл openvpn-сервера, для совместимости режима вызова внешних скриптов:

# compatibility with OpenVPN 2.0
script-security 3 system

Клиенты заработали с полностью неизмененными, старыми конфигурационными файлами. Только в логах установки соединения для старых OpenVPN 2.0 клиентов стало появлятся сообщение:

Options error: Unrecognized option or missing parameter(s) in [PUSH-OPTIONS]:2: topology (2.0.9)

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

Несмотря на статус бета-версии никаких проблем в работе нового openvpn не наблюдается. Наоборот, новая для OpenVPN 2.1, возможность udp multihome заработала просто прекрасно. Теперь клиенты могут использовать для соединения того провайдера, который им удобнее, дешевле и т.д.

P.S. При сборке пакета для Slackware 9.1 штатный gcc-3.2.3 ниасилил сборку нового openvpn со следующим сообщением об ошибке:

ssl.c:3402:1: directives may not be used inside a macro argument
ssl.c:3401:92: unterminated argument list invoking macro "msg"
ssl.c: In function `key_method_2_read':
ssl.c:3403: invalid type argument of `->'
ssl.c:3408: syntax error before ')' token
make[2]: *** [ssl.o] Error 1

Тут ситуация не совсем понятна. Толи это убогая старая версия препроцессора С, толи разработчики OpenVPN используют приёмы программирования на грани разрешенного. Во всяком случае версия gcc-4.2.4 от новой Slackware 12.2 собрал этот пакет без проблем. Т.к. компилятор языка C написан на языке C, то сначала пришлось скомпилировать пакет с компилятором, обновить пакет gcc, а потом уж компилировать openvpn :)

8 комментариев:

Анонимный комментирует...

Странно, использую версию OpenVPN 2.0_rc21. Много клиентов подключается через разные интерфейсы. Таких проблем никогда не наблюдал. БСС

xeim комментирует...

Вы ничего не путаете? Проверьте ещё раз. У вас используется протокол udp? И клиенты подключаются через разные интерфейсы ОДНОВРЕМЕННО?
И уточните версию, 2.0_rc21 очень старая версия, судя по changlog-у она вышла в первой половине 2005 года.

Анонимный комментирует...

а возможно ли сделать наоборот? - чтобы клиент с несколькими интернет-интефейсами балансировал траффик опенвпн подключения между ними поровну?

а если делать это железякойс двумя WAN побайтно или попакетно, то будет ли оно корректно работать?

xeim комментирует...

Средствами openvpn такую балансировку трафика сделать нельзя.
Если бы я решал такую задачу для linux, я бы сначала посмотрел в сторону linux bonding.
А про желелезку вообще ничего сказать не могу, прежде всего зависит от того что за железка.

Анонимный комментирует...

Использую Fedora 7 попробовал openvpn
2.1_rc15, 2.1_rc16 - udp подключения с двух разных интерфейсов -не работают. Пакеты приходят на любой интерфейс, а уходят с дефолтного. Пакеты пробовал собирать с дефолтными опциями, и с --with-multihome.
В чем может быть причина, на что нужно обратить внимание?

xeim комментирует...

В первую очередь возникает вопрос, всё ли в порядке с маршрутизацией. Т.е. например можно ли нормально попингать сервер со стороны обоих клиентов?

Анонимный комментирует...

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

Анонимный комментирует...

Долго бился над решением) Оказалось все гораздо проще. Надо просто в серверном конфиге добавить сам параметр multihome.