Пока для android-платформы не выпустили официального OpenVPN-клиента, в своё время энтузиасты успели наваять кучу альтернативных разной степени кривизны. Их отличительная особенность заключалась в том, что все они требовали для работы наличия рута, и, как правило, ещё и установленного BusyBox-а.
Потом случился уже не помню какой по счёту релиз Android, в него добавили API для построения VPN-ов. После чего был выпущен "оригинальный" OpenVPN Connect, который работал (и работает) через этот API и больше не требует привилегий суперпользователя.
Но вот же ж, блин, какая подстава. Я не знаю как сейчас обстоят дела с 5-м и 6-м ондроедами. А до версии 4.4 включительно пресловутый API позволял направлять в свежепостроенный тоннель либо всё, либо ничего. То есть взять и оставить Default Gateway в покое, а в дополнение к нему прописать на телефончике несколько статических маршрутов вовнутрь тоннеля, извините, не получится. Причём, меня "до кучи" удивляет способ реализации всей этой хренотени. Поясняю.
На обычном, "взрослом" линуксе демон OpenVPN по сюжету запускается из-под root-а, устанавливает соединение с вражеской стороной, прописывает в таблице маршрутизации "main" все необходимые маршруты, после чего опционально "сбрасывает" привилегии и дальше продолжает себе работать под тем uid-ом, который у него был прописан в конфиге. Под андроидом же он изначально стартует как непривилегированный, при этом попросить себе побольше прав у всяких там SuperSu то ли не умеет, то ли не хочет. Как следствие, у него нет и прямого доступа к системным таблицам маршрутизации. Вместо этого он в iptables-mangle создаёт ещё одну цепочку, куда прописывает присвоение метки с номером 60 для исходящих пакетов на те сети, которые были ему "спущены" с сервера директивой "push". Также он создает новую таблицу маршрутизации с номером "60" и к ней правило в ip rule, которое требует направлять в таблицу "60" все пакеты, помеченные меткой "60", которую они могут получить или не получить в процессе прохождения через iptables. Уххх!
Но и это ещё не всё. Независимо от содержимого конфигов сервера и клиента, в таблице "main" создаются два маршрута: "0.0.0.0/1 via tun0" и "128.0.0.0/1 via tun0". И вот дальше хоть трава не расти. Весь исходящий трафик неизбежно уйдёт в тоннель, и я в упор не понимаю на хрена вообще затеяны все эти кульбиты с метками, iptables-mangle и созданием альтернативных таблиц.
При этом единственной возможностью отвадить софтину от манипуляций с маршрутизацией является прописывание ей в конфиге директивы "route-nopull". Экспериментальным путём выяснено, что никакие другие способы и заклинания не срабатывают. Но в таком случае OpenVPN не добавляет вообще никаких маршрутов. То есть толку от данного манёвра, мягко говоря, очень мало.
Теоретически можно было бы создать нужные статические маршруты из какой-нибудь сторонней софтины. Но вот незадача, ей каким-то образом понадобится отслеживать моменты, когда тоннель поднимается и когда падает. Что тоже весьма неочевидно. Логично было бы запускать shell-скрипт из самого OpenVPN, ведь он-то прекрасно "знает" когда интерфейс готов к работе. И во "взрослом" линуксе такой способ вполне себе канает. Но у "андрюши" всё не как у людей. На практике я уже попробовал и так, и сяк, и разэдак. Не запускает он мой скрипт. Ну не хочет, и всё тут.
Что-то у меня идеи уже совсем закончились. Вопросов больше, чем ответов. Во-первых, как обстоят дела в более свежих, современных андроидах. Может быть там что-то принципиально поменяли? Во-вторых, существуют ли сейчас нормальные "альтернативные" реализации OpenVPN, которые умеют запускаться из-под root-а и напрямую писать в таблицу "main", безо всяких извращений. В-третьих, можно ли подставить под "официальный" OpenVPN Connect какие-нибудь костыли, чтобы в системе прописались те маршруты, которые я хочу, а не те, которые хочет Android.
Если у вас есть какие-нибудь мысли по этому поводу, или вы знаете у кого можно спросить, милости прошу в комментарии.