Round-robin default gateway и OpenVPN

Автор: Admin | 17.02.2016

Round-robin default gateway ломает маршрутизацию от источника для OpenVPN

На Linux (Debian 8) шлюзе настроена маршрутизация от источника (multipath) при помощи iproute2. Корректно маршрутизируются как forward пакеты, так и input\output. Но после включения round-robin default gateway стали возникать проблемы при подключении OpenVPN клиентов

Round-robin gateway был включен следующей командой:

ip route add default scope global nexthop via $GW1 dev $IF1 weight 1 nexthop via $GW2 dev $IF2 weight 1 nexthop via $GW3 dev $IF3 weight 1

В реальности с маршрутизацией все немного сложнее, но эти частности не сильно влияют на конечный вывод, поэтому их можно опустить. Как видно, попеременно используется три шлюза с одинаковым весом. OpenVPN сервер настроен так, что слушает все интерфейсы и работает по UDP протоколу, полный конфиг приведен в данной статье. По идее, OpenVPN должен работать при таких настройках, но нет, клиенты перестали подключаться к данному серверу. Хотя тот же SSH продолжал работать при подключении по любому из интерфейсов. Можно предположить, что причина в UDP протоколе, но тест на DNS сервере показал, что ответы на UDP запросы возвращаются с нужных интерфейсов. Таким образом, при включении Round-robin gateway, маршрутизация от источника сломалась только для OpenVPN и причину надо искать в нем.

При коннекте, перед началом рукопожатия, запрашивается логин с паролем и авторизация проходит успешно, дальнейшее подключение не происходит, лог неудачного подключения клиента не говорит ровным счетом ни чего полезного:

TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
TLS Error: TLS handshake failed
SIGUSR1[soft,tls-error] received, process restarting
MANAGEMENT: >STATE:1451454269,RECONNECTING,tls-error
Restart pause, 2 second(s)

Интересно то, что у некоторых клиентов (по факту, было только на одном) в логах прилетало кое-что интересное. При подключении на первый интерфейс $GW1 лог выдавал следующее:

Incoming packet rejected from [AF_INET]$GW1:1194[2], expected peer address: [AF_INET]$GW2:1194 (allow this incoming source address/port by removing --remote or adding --float)
Incoming packet rejected from [AF_INET]$GW1:1194[2], expected peer address: [AF_INET]$GW3:1194 (allow this incoming source address/port by removing --remote or adding --float)

И так по кругу. При чем, если на клиенте заменить IP адрес сервера на $GW2, то ответные пакеты будут приходить с $GW1 и $GW3, но не с $GW2. Т.е. к какому бы IP не подключался клиент, ответ никогда не приходит с того же интерфейса. Достаточно странное поведение. Повторю, в этот же момент маршрутизация от источника по другим подключениям работает исправно.

В поисках причин такого поведения выяснилось, что при настроенном OpenVPN на TCP протокол соединение все же происходит, таким образом причина в реализации OpenVPN при работе по UDP протоколу. Как причина стала ясна быстро нагуглилось решение — параметр multihome на стороне сервера OpenVPN. Man openvpn параметра multihome:

--multihome
              Configure  a multi-homed UDP server.  This option needs to be used when a server has more than one IP address (e.g. multiple interfaces, or secondary IP addresses), and is not using --local to force binding to one
              specific address only.  This option will add some extra lookups to the packet path to ensure that the UDP reply packets are always sent from the address that the client is talking to. This is not supported on  all
              platforms, and it adds more processing, so it's not enabled by default.

              Note: this option is only relevant for UDP servers.

              Note  2:  if  you  do  an  IPv6+IPv4  dual-stack  bind on a Linux machine with multiple IPv4 address, connections to IPv4 addresses will not work right on kernels before 3.15, due to missing kernel support for the
              IPv4-mapped case (some distributions have ported this to earlier kernel versions, though).

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *