Откуда пришла проблема

Сейчас довольно часто нужно включать VPN. На Android, IOS и Windows у меня получалось находить программы, которые по одной кнопке его хорошо подключают. Но даже в них, во-первых, есть реклама, во-вторых, есть лимиты, а в-третьих (по крайней мере, с бесплатной версией) бывает такое, что приложение говорит, что всё сработало, а трафик либо вообще не идёт, либо идёт в обход VPN-а.

Решения

Среди очевидных решений — покупать платную версию или поднимать собственный VPN. Для первого напрямую нужны деньги: 10-20 долларов в месяц. Для второго нужна собственная машина, за которую надо платить. Может, конечно, это и не так много, но всё-таки это в бесконечное число раз дороже, чем бесплатно, и я решил посмотреть, что же есть из бесплатного.

И тут мой взгляд упал на https://www.freeopenvpn.org, куда выкладывают конфиг-файлы, с помощью которых можно подключаться к их VPN-у. 

Проблемы

Одной из проблем является безопасность. Никто не гарантирует, что те серваки, которые они предоставляют, никак не мониторят трафик, который через них идёт. Более того, они имеют такую возможность, судя по предупреждению на их сайте:

Предупреждение на freeopenvpn.org

Предупреждение на freeopenvpn.org

Но мне кажется, что если такое происходит, то только пост-фактум, если к ним придут и спросят, мол, кто положил сайт example.org или наспамил 100500 обращений в госдуму. Более того, практически уверен, что другие VPN-сервисы тоже могут отдавать данные правительству, если такой запрос поступит. Но это при условии чего-то уж слишком криминального. Если просто скролить заблокированную инсту или фейсбук — на это никто смотреть не будет.

Второй проблемой, про решение которой, собственно, я и хочу рассказать, было то, что пароль для подключения постоянно меняется. Примерно раз в двенадцать часов пароль для подключения к VPN меняется на случайные девять цифр, и для того, чтобы его узнать, надо открыть сайт freeopenvpn, найти нужный конфиг, увидеть картинку с паролем (по сути — капчу), понять, что там написано, запомнить, нажать на кнопку «подключиться», ввести пароль… В среднем это у меня занимало около двух минут, с учётом медленной работы сайта и моей нерасторопностью.

И снова решения

Наверное, можно скачивать картинку с паролем по ссылке. Было бы, конечно, легко, если бы пароль лежал просто текстом. Но показывается как капча:

Пример того, как пароль показывается на сайте

Пример того, как пароль показывается на сайте

И тут приходит мысль, что, наверное, не зря я учу весь этот машинлёнинг и программирование в целом в университете. Давайте обучим сетку, которая будет распознавать пароль за нас! Тогда остальное — дело техники: скачиваем картинку скриптом, распознаём пароль, командой подключаемся к VPN, профит! И всё это можно запускать сочетанием клавиш.

Про реализацию

Общая концепция

Пароль состоит из девяти цифр (ура, без символов, задача упрощается!), причём на картинке они находятся примерно с одинаковыми отступами. Давайте нарежем картинки на девять частей по вертикали и будем считать, что в одном квадратике лежит одна цифра. После этого для каждого квадратика предскажем, что же там лежит за цифра, склеим предсказания вместе и получим пароль.

Сбор данных

Для того, чтобы нормально обучиться, нужно довольно много данных. Размечать, конечно же, я ничего не хотел. Но тут к нам снова приходит на помощь непродуманность сервиса freeopenvpn. Так как пароль для подключения в каждый момент времени один для всех пользователей, то в течение 12 часов картинки для конфиг-файла содержат один и тот же пароль. Создатели сайта могли бы показывать одну и ту же картинку (не понимаю, почему так не сделали), но на сайте показывается каждый раз новая! 

Примеры четырёх картинок для одного пароля
Примеры двух картинок для одного пароля
Примеры двух картинок для одного пароля

Это значит, что сохранив достаточно много вариантов отображения двух-трёх паролей (так, чтобы на этих паролях были все цифры от 0 до 9), можно собрать много вариантов написания каждой цифры, разметив только эти две-три картинки!

Так и поступим. Я написал скрипт, который сохраняет около трёх тысяч картинок одного и того же пароля, нарезал их по цифрам и получил около пяти тысяч вариантов для каждой цифры.

Выбираем архитектуру

Тут сильно заморачиваться не стал. Можно было использовать обычный ResNet, но раз уж мы тут все такие глубинные обучатели, взял свою архитектуру из домашнего задания по Deep-learning-у.

Схема модели. Просто и лаконично

Схема модели. Просто и лаконично

Это — AlexResNet (тут есть шутка, меня Алексей зовут, да), на самом деле — лёгкий ResNet. А тяжёлого нам и не надо: задачка вроде не такая сложная.

Данные есть, сетка есть, можно обучать! Сжигал GPU-часы я в Kaggle, общее число обучения — минут 10. На отложенной выборке точность получилась около 0.99.

Много это или мало? Сначала кажется, что много, неправильно будет распознаваться только 1% цифр. Но так как пароль — не одна цифра, а целых девять, вероятность угадать все составляет (0.99)^9 ~= 0.91. Уже не так хорошо. Побороть это можно снова воспользовавшись тем, что в каждой момент времени нам доступно сколько угодно вариантов написания пароля. Возьмём k картинок с паролями, нарежем их на цифры, независимо предскажем цифры для каждой позиции всё той же обученной сеткой, ответ будем считать как наиболее популярный прогноз для каждой цифры. Подсчёт ожидаемого качества такого алгоритма оставляю в качестве упражнения читателю, но оно явно больше 0.91, что меня вполне устраивает.

Небольшие формальности

А как теперь подключиться к VPN? Поискав нужные команды, нашёл nmcli — утилиту командной строки, с помощью которой можно управлять NetworkManager-ом в линуксе. С помощью неё создаю новую конфигурацию VPN, выставляю пароль и выполняю подключение.

Теперь можно забиндить запуск скрипта со всем пайплайном на сочетание клавиш и полностью автоматизировать подключение.

Так что в итоге?

А в итоге — подключение к VPN-у одной кнопкой, как я и хотел. С помощью сочетания клавиш можно вызвать скрипт подключения, который скачает конфигурационный файл, файл с паролем, распознает цифры и подключится к VPN. Весь процесс занимает где-то 7 секунд.

После окончания работы можно отключиться из интерфейса настроек

После окончания работы можно отключиться из интерфейса настроек

А что можно улучшить?

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

Во-вторых, 7 секунд это всё ещё много. Около трёх секунд выполняется само подключение, с этим ничего не сделаешь. А вот скачивание картинок с паролями и файлами конфигурации можно сделать параллельным, тем сам сократив эту часть времени подключения в k раз, где k — число скриншотов, которые сетка распознаёт. Это позволит как ускорить текущее подключение, так и увеличить число капчей, которые анализируются при подключении, тем самым повысив качество.

Вместо послесловия

Пользуюсь этой штукой уже шесть месяцев и ужасно рад! Можно сказать, что 100% положительных отзывов у проекта имеется.

Спасибо, что дочитали! Буду рад ответить на вопросы, если они возникли.

Код выложил на гитхаб, там есть как скрипты для подключения, так и Jupyter Notebook для обучения модели. Данные и веса модели не выложил, но если есть потребность — могу скинуть.

Комментарии (9)


  1. MAXH0
    29.11.2023 14:00

    Ну Вы просто успели впрыгнуть в уходящий поезд... Сохраню статью и попытаюсь её прочесть на Хабре через 2 дна.


    1. Astus
      29.11.2023 14:00
      +4

      через 2 дна

      Замечательная опечатка. Что ни новый день, то новое дно.

      Вспомнилось.


      1. IvanPetrof
        29.11.2023 14:00

        Почему-то мне кажется, что это не опечатка..


  1. oleg_rico
    29.11.2023 14:00
    +3

    Не знаю, где автор находит VPN за 20 баксов в месяц. В том же fornex 2 евро в месяц стоит и никаких плясок с бубном и также подключается одной кнопкой или щелчком мыши.


    1. Orange_Kir
      29.11.2023 14:00
      +2

      2 бакса это целая шаурма. Автор, судя по тексту, студент, так что она точно лишней не будет


    1. Zrgk
      29.11.2023 14:00
      +1

      Согласен, я лично KVM виртуалку арендовал за те же 20 баксов, но только на год. И поднял там openvpn, shadowsocks и прочее добро.


  1. palyaros02
    29.11.2023 14:00
    +3

    А можно получить студенческий github pro, потом получить за него 100$ на digital ocean, поднять свой сервер за 5 баксов в месяц с ограничением в терабайт трафика в месяц, настроить на нем shadowsocks запуском одного скрипта и жить не тужить. Подключение занимает доли секунды, можно настроить частичную фильтрацию (например, госуслуги, банки и т.п. идут через ваш основной канал, а чатгпт, Твиттер и т.п. идут через shadowsocks автоматически). Звучит сложно, но по количеству телодвижений и итоговому результату это проще и лучше способа в статье.

    Большая часть ВПН за 20 баксов именно так и работают, арендуя поды на aws/do/google cloud за три копейки, и шеря каждый на 10+ человек, с каждого получая по 20 баксов.


  1. Andru84
    29.11.2023 14:00

    Как это будет работать после блокировки сайта freeopenvpn.org ?


  1. Artem_Khromov
    29.11.2023 14:00

    Зачем включать и выключать VPN, есть множество решений с выборочной маршрутизацией
    Для OpenWRT:
    https://habr.com/ru/articles/773696/
    https://habr.com/ru/articles/757694/

    Для своего домашнего сервака, на Авито можно взять старый неттоп ~ 2.000:
    https://habr.com/ru/articles/746894/

    Для Keenetic есть КВАС:
    https://github.com/qzeleza/kvas

    Да придется иметь свой VPS за рубежом, но стоит ~ 2 евро