Кратко — можно, но не так, как вы попытались. Коротко по сути проблем и рабочим вариантам.
Почему у вас не работает
- ocserv отправляет клиенту маршруты / исключения (директивы route / no-route), но приложение‑клиент должно их применить. Не все клиенты (и не все ОС) корректно поддерживают или применяют большое количество pushed‑маршрутов.
- Мобильные Android‑клиенты часто имеют ограничения VpnService (ограничение на число маршрутов/правил), либо автор приложения OpenConnect мог не реализовать поддержку no-route/массовых изменений. Поэтому Android может игнорировать ваши директивы.
- Push ~16 000 префиксов — это плохая идея: много сетевых записей, большой трафик управления, клиенты/ядро ОС могут «подвисать», часть маршрутов отбрасываться, а обновление/применение может происходить с задержкой.
Варианты решений и рекомендации
1) Понять, где проблема — сервер или клиент
- Подключитесь с Linux/Windows клиентом (openconnect CLI на Linux, ocserv-compatible клиент на десктопе) и посмотрите, применяются ли no-route‑правила сразу. Если на десктопе применяются — виноват Android/мобильный клиент.
- Логи ocserv (debug) покажут, что сервер отправляет клиенту. Логи клиента покажут, что он применяет.
2) Если контролируете клиенты — делайте исключения на клиенте
- Самый надёжный путь — настроить split‑tunneling на самом клиенте (скрипты добавления маршрутов, policy routing, iptables+ip rule), а не пытаться передавать 16k префиксов серверу. На Linux/macOS/Windows это реализуется скриптом при подключении.
- На Android это возможно только при root (добавление маршрутов в таблицу) или с использованием VPN‑приложений/локальных прокси, которые умеют per‑app/proxy правила (например, прокси с PAC, либо приложения с поддержкой per‑app VPN). Без root и без поддержки split‑tunnel со стороны клиента это сделать нельзя.
3) Если нужно, чтобы трафик шёл «мимо VPN» — клиент должен посылать его мимо туннеля
- Ваша цель «чтобы RU‑трафик шел мимо VPN» требует, чтобы клиент НЕ отправлял эти пакеты в туннель. Сервер не может заставить клиент «вернуть» пакеты в локальную сетевую стэк, если клиент уже запаковал их в туннель. Поэтому решение — либо push‑no‑route, которое клиент применит, либо настройка на самом клиенте.
4) Практический компромисс: доменное/прокси‑разделение (рекомендую)
- Если важны только крупные сервисы (Яндекс, Сбер, Госуслуги, Mail.ru и т.п.), гораздо удобнее использовать доменно‑ориентированный обход: ставите PAC (Proxy Auto Config) или браузер/приложение, которое использует системный/локальный прокси и направляет трафик к конкретным доменам в обход VPN. Это работает для веб/HTTP(S) трафика и часто для приложений, которые поддерживают прокси/PAC.
- На Android можно использовать браузеры с поддержкой PAC/профилей или локальный прокси (например, браузер + tinyproxy на устройстве), либо использовать VPN‑приложения с поддержкой PAC/whitelist.
5) Уменьшение размера списка IP (агрегация и ASN)
- Не пытайтесь передавать 16k строк «как есть». Можно:
a) Взять готовые country CIDR‑списки и агрегировать (ipdeny, ipverse, delegations).
Пример: https://www.ipdeny.com/ipblocks/data/countries/ru.zone
b) Свернуть префиксы с помощью netaddr (Python) или cidrmerge:
Примеры команд:
curl -s https://www.ipdeny.com/ipblocks/data/countries/ru.zone > ru.zone
python3 - <<'PY'
import netaddr
cidrs=[netaddr.IPNetwork(l.strip()) for l in open('ru.zone') if l.strip()]
for c in netaddr.cidr_merge(cidrs):
print(c)
PY
Это уменьшит число префиксов (иногда в 2–5 раз).
c) Ещё компактнее — брать префиксы по ASN компаний (AS для Яндекса, Сбера, Mail.ru и т.д.) — тогда вы будете исключать все префиксы конкретного оператора/провайдера, а не каждую маленькую сеть. Получить префиксы ASN можно через whois/radb:
whois -h whois.radb.net -- '-i origin ASXXXX' | awk '/^route/ {print $2}'
(сначала узнайте ASN по домену/IP, например через whois/ipinfo).
- Даже после агрегации число префиксов для всей страны остаётся большим — но обычно список становится приемлемым (тысячи → сотни).
6) Как сгенерировать строки для ocserv
- В ocserv вы можете добавить в конфиг строки no-route = X.Y.Z.T/NN
- Автоматически сгенерировать можно так (после cidr_merge):
for p in $(python3 cidr_merge_script.py); do echo "no-route = $p"; done >> /etc/ocserv/ocserv.conf
Но повторюсь: это работает только если клиент поддерживает и применяет no-route и если число префиксов не слишком велико.
7) Альтернативный серверный подход (не «мимо VPN», но полезно)
- Если ваша цель — не «куда отправляет клиент», а «чтобы сессии с RU ресурсами шли через другой исходящий шлюз на сервере», то можно на VPN‑сервере делать policy routing: по destination IP ставить MARK и отправлять через специфический routing table/gateway. Это означает, что трафик клиент→VPN всё равно идёт в туннель, но на сервере вы можете выбирать, через какой интернет‑интерфейс выходить. Это НЕ делает трафик «мимо VPN» с точки зрения провайдера клиента, но может помочь, если сервер имеет несколько выходов/гейтвеев и нужно разделить исходящий путь.
8) Что делать конкретно вам
- Шаг 1: протестируйте на Linux/desktop клиенте, чтобы понять, сервер ли правильно отсылает no-route.
- Шаг 2: если сервер правильно шлёт, но Android игнорирует — либо смените клиент/версию, либо делайте split на самом Android (root или per‑app/proxy), либо используйте доменный PAC‑подход.
- Шаг 3: сократите список префиксов: используйте ipdeny.ru.zone + cidr_merge или собирайте префиксы по ASN для конкретных сервисов (Яндекс, Сбер, Mail.ru и т.д.).
- Шаг 4: не пушьте десятки тысяч префиксов — это ненадёжно. Стремитесь к сотням агрегированных префиксов или к AS‑спискам для крупных сервисов.
Полезные ссылки/команды
- Список префиксов по странам: https://www.ipdeny.com/ipblocks/data/countries/ru.zone
- Сжатие префиксов: использовать Python netaddr.cidr_merge или утилиты cidrmerge/cidr-tools.
- Префиксы по ASN: whois/radb:
whois -h whois.radb.net -- '-i origin ASXXXX' | awk '/^route/ {print $2}'
- Логирование отправки маршрутов в ocserv — включите debug и посмотрите, что сервер отправляет клиенту.
Если хотите — могу:
- Посмотреть вашу конфигурацию ocserv (фрагмент с route/no-route) и подсказать оптимизацию.
- Сгенерировать агрегированный список префиксов для России из ipdeny и дать его в виде no-route строк (и пример скрипта для добавления в ocserv.conf).
- Помочь собрать список ASN для конкретных сервисов (напишите, какие именно сервисы/доменные имена вас интересуют), и получить их префиксы.