Ваш профиль OpenVPN на Android не добавляет маршрут, потому что у телефона нет адреса на виртуальном интерфейсе, и маршруту не на что указывать. Маршруты отвечают только на вопрос, куда должны уходить пакеты. Адрес туннеля отвечает на вопрос, кем является телефон внутри туннеля, и клиент должен предоставить его прежде, чем интерфейс сможет появиться. Пройдите четыре проверки ниже по порядку и остановитесь на первом сбое, потому что правка маршрутов до появления адреса скрывает настоящую проблему.

Читайте сбой в том порядке, в каком его выполняет клиент

VpnService.Builder в Android разделяет два понятия: addAddress() помещает адрес на интерфейс, который строит приложение, addRoute() добавляет префикс назначения, а establish() отказывается создавать интерфейс, пока не добавлен хотя бы один адрес. Клиент OpenVPN отображает профиль и параметры, которые присылает сервер, ровно на эти вызовы, поэтому соединение, которое ни разу не разобрало адрес, вообще не может построить интерфейс.

Поэтому строка журнала, которую вы читаете, может упоминать маршрут, тогда как причина на шаг раньше. Клиент доходит до этапа маршрута только после того, как интерфейс существует; без адреса вызов маршрута немедленно завершается ошибкой или не выполняется вовсе. Когда журнал сообщает, что маршрут добавить нельзя, начинайте с адреса, а не с синтаксиса маршрута.

Проверка 1: помещает ли сервер адрес в ответ?

В маршрутизируемой службе OpenVPN адрес берётся из пула сервера или из назначения для каждого клиента, а форму задаёт топология. На сервере OpenVPN 2.4 или новее служба с топологией подсети выглядит так:

topology subnet
server 10.8.0.0 255.255.255.0
client-config-dir ccd

При такой форме сервер присылает что-то вроде ifconfig 10.8.0.6 255.255.255.0. Более старая установка с topology net30 присылает вместо этого адрес партнёра, например ifconfig 10.8.0.6 10.8.0.5, поэтому профиль, перенесённый между двумя моделями, может выглядеть правильным, но нести неверную маску сети.

Поищите в журнале подключения клиента набор присланных параметров. Если в нём нет ни одной строки ifconfig, сервер никогда не присылал адрес или клиент отклонил параметр. На сервере, который использует client-config-dir, файл, названный по common name сертификата, должен существовать и содержать назначение:

# ccd/phone-anna
ifconfig-push 10.8.0.6 255.255.255.0

Проверка 2: сохраняет ли клиент полученный адрес?

Слишком широкий фильтр — вторая распространённая причина. pull-filter существует в OpenVPN 2.4 и новее, и когда несколько фильтров совпадают с одним параметром, побеждает последний совпавший, поэтому catch-all в конце убирает адрес без ошибки:

# removes every pushed option, including the address
pull-filter ignore "ifconfig"
pull-filter ignore "route"

Сузьте фильтр до того параметра, который действительно нужно убрать, и оставьте адрес в покое:

# keeps the pushed address, drops one unwanted LAN route
pull-filter ignore "route 10.60.0.0"

Совет отключить все pull обычно исходит от того, кто хочет избавиться от одного единственного маршрута. route-nopull — более узкий переключатель: он сохраняет ifconfig и остальные присланные параметры, но отклоняет присланные маршруты и параметры в духе DHCP. Используйте его, когда это действительно то, что нужно, а вопрос адреса решайте отдельно.

Проверка 3: вам ли вписывать этот адрес?

Ручная адресация оправдана только тогда, когда оператор сам выдаёт вам значение. Если вы вписываете адрес сами, он должен быть из подсети клиента VPN, уникальным среди активных сеансов и соответствовать топологии, которую использует сервер. Копирование адреса настольного моста или хоста в удалённой локальной сети неверно по обеим причинам: телефон заявит адрес, который уже существует в другом месте, а у шлюза не будет обратного пути к нему.

Префикс удалённой локальной сети в маршруте — это назначение, а не личность телефона. Маршрут для 10.60.0.0/24 говорит, что до этой сети нужно дойти через туннель; он ничего не говорит о том, какой адрес 10.60.0.x должен быть у телефона, и телефон не должен иметь ни одного из них. Статические назначения принадлежат стороне сервера, где они не могут конфликтовать с динамическим пулом.

Два сеанса под одной личностью вскрывают тот же конфликт. Если один и тот же сертификат подключается дважды и сервер присылает один фиксированный адрес обоим, второй сеанс дублирует первый, и решением будут отдельные личности или отдельные назначения, а не правка на стороне клиента.

Проверка 4: не занято ли место туннеля чем-то ещё?

Android разрешает только одну активную службу VPN одновременно. Другое VPN-приложение или запись постоянно включённого VPN, оставленная включённой для профиля, который больше не работает, может занять это место до того, как ваш клиент OpenVPN вызовет establish(). Тогда интерфейс не появляется вовсе, хотя профиль корректен, поэтому отключите другое VPN, выключите настройку постоянного включения и подключитесь заново, прежде чем трогать профиль.

Служба, которая настаивает на мосту Ethernet, — это второй тупик. Приложение Android без root может создать IP-туннель, а не мостовой сегмент Ethernet, поэтому ни один вписанный адрес не заставит сервер dev tap работать; оператор должен предложить маршрутизируемую службу. Когда сообщаете о проблеме, укажите имя и версию клиента, набор присланных параметров, топологию и точный шаг, на котором адрес должен был появиться.

Если все четыре проверки пройдены и адрес присутствует, уникален и правильно маскирован, вопрос о маршруте становится обычным: какие префиксы сервер разрешает и как клиент должен их ограничивать. Запишите адрес туннеля, его маску сети и топологию, прежде чем менять что-то ещё, потому что именно эти три значения оператору нужно сравнить с тем, что видно на сервере.

Похожие статьи