Предыстория
В связи с введением в нашей стране блокировок некоторых ресурсов (не будем показывать пальцем), понадобилось мне реализовать к ним доступ через VPN. К слову говоря, пользуюсь я этими ресурсами не так часто, но пользуюсь. И казалось бы, что проще. Есть сегодня целая куча различных сервисов предоставляющих VPN доступ.
Однако платить за сервис несколько десятков долларов и пользоваться им несколько раз в месяц я посчитал нецелесообразно. Тогда мой выбор пал на бесплатные VPN. Одним из таких является сервис vpnbook. Для моих требований его предостаточно, но вот незадача — пароль для доступа к VPN по PPTP периодически меняется. И при каждой его смене заходить на сайт копировать его и настраивать соединение на роутере — честно говоря лень. А говорят, что «лень – двигатель прогресса». В моем случае это так. Надо что-то делать…
Я подумал, а почему бы мне не парсить со страницы пароль и автоматически обновлять параметры соединения на моем Mikrotik. Почему только пароль? Ну так на vpnbook адреса серверов достаточно постоянны и я использую один а логин всегда один и тот же — vpnbook. Итак, приступим.
Часть про PHP — простенький парсер
Для начала я решил написать простенький парсер странички на PHP. Честно сказать программировать по своей работе я особо не программирую, поэтому весь код, который я буду здесь приводить, наверняка можно сделать лучше и надеюсь в комментариях мне укажут на ошибки, косяки и недочеты.
При парсинге я использовал библиотеку «PHP Simple HTML DOM Parser». Её можно скачать по ссылке. И для начала нам конечно же нужно её подключить:
include "simple_html_dom.php";
Далее для того чтобы получить содержимое страницы vpnbook.com/freevpn будем использовать cURL. Пример как его использовать я взял с сайта php.net и обернул в функцию:
function url_get_html($url){
// инициализируем cURL
$ch = curl_init();
// устанавливаем url с которого будем получать данные
curl_setopt($ch, CURLOPT_URL, $url);
// устанавливаем опцию чтобы содержимое вернулось нам в string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// выполняем запрос
$output = curl_exec($ch);
// закрываем cURL
curl_close($ch);
// возвращаем содержимое
return $output;
}
Далее, используя возможности библиотеки «PHP Simple HTML DOM Parser», нам нужно вытащить пароль из содержимого страницы. Просмотрев исходный код страницы, можно увидеть, что пароль находится в последнем элементе списка в теге strong.
...
</div>
<p>PPTP (point to point tunneling) is widely used since it is supported across all Microsoft Windows,
Linux, Apple, Mobile and PS3 platforms. It is however easier to block and might not work if your ISP or
government blocks the protocol. In that case you need to use OpenVPN, which is impossible to detect or block.</p>
<ul class="disc">
<li><strong>euro217.vpnbook.com</strong></li>
<li><strong>euro214.vpnbook.com</strong></li>
<li><strong>us1.vpnbook.com</strong> <span class="red">...</span></li>
<li><strong>us2.vpnbook.com</strong> <span class="red">...</span></li>
<li><strong>ca1.vpnbook.com</strong> <span class="red">...</span></li>
<li><strong>de233.vpnbook.com</strong> <span class="red">...</span></li>
<li>Username: <strong>vpnbook</strong></li>
<li>Password: <strong>qedE3ha</strong></li>
</ul>
<div><strong><span class="green"> More servers coming. Please Donate.</span></strong></div>
...
Почему бы не получить все теги strong из первого списка на страницу и из последнего не получить пароль? Делаем:
// URL с которого будем парсить пароль
$url = "http://www.vpnbook.com/freevpn";
// получаем DOM
$html = str_get_html(url_get_html($url));
// находим необходимые элементы к первом списке с классом "disc"
$items = $html->find(".disc", 0)->find("strong");
// пароль находится в последнем
$pswd = end($items);
// выводим пароль
echo $pswd->innertext;
Итак парсер готов. Осталось его выложить на сервер.
include "simple_html_dom.php";
function url_get_html($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
$url = "http://www.vpnbook.com/freevpn";
$html = str_get_html(url_get_html($url));
$items = $html->find(".disc", 0)->find("strong");
$pswd = end($items);
echo $pswd->innertext;
Часть про Mikrotik — скрипт для создания VPN подключения
Парсер готов и представим, что он доступен по адресу vpn.pswd.tk. Теперь нам нужно на Mikrotik (у меня hap lite) написать скрипт, который будет обращаться к нашему парсеру, получать от него пароль и пересоздавать VPN подключение. Покопавшись в документации Mikrotik, я нашел необходимый мне функционал, а именно с помощью /tool fetch можно сделать запрос по URL и содержимое поместить в текстовый файл, после чего считать его содержимое в переменную. Вот полный код скрипта:
/tool fetch url="http://vpn.pswd.tk/" mode=http dst-path="vpn_pswd.txt";
:delay 2s
:local password [/file get vpn_pswd.txt contents]
/file remove vpn_pswd.txt;
/interface pptp-client remove [/interface pptp-client find name=pptp-out1]
/interface pptp-client add name=pptp-out1 user=vpnbook password=$password connect-to=us1.vpnbook.com disabled=no
Немного разберем, что есть что. Первой строчкой мы делаем запрос к нашему парсеру и ответ в виде пароля записываем в файл vpn_pswd.txt. Далее, как несложно догадаться, у нас происходит задержка в 2 секунды. Для чего? Дело в том, что роутеру для выполнения запроса и создания файла требуется некоторое время и если не сделать задержку, то следующая команда может попросту не считать в переменную значение из файла (т.к. его на тот момент еще нет). Далее, после записи значения в переменную, мы удаляем созданный файл — он нам уже не нужен. Потом удаляем созданное VPN подключение и создаем новое.
Остается только добавить в планировщик запуск этого скрипта через какой-нибудь (на ваш выбор) промежуток времени. Делается это в разделе System/Scheduler. Если допустим наш скрипт называется «through_vpn_list», то тогда вот этой командой мы создадим задание для запуска скрипта каждые 6 часов:
/system scheduler add name=schedule1 interval=6h on-event="/system script run through_vpn_list"
Итоги
Мы получили возможность автоматически создавать VPN подключение, используя пароль от бесплатного сервиса. Как использовать это подключение — это уже ваше решение. Например, можно настроить роутинг на основе политик, чтобы VPN подключение использовалось только для определенного списка сайтов и ресурсов. Так например у меня и реализовано. Прикладываю ссылку на документацию, по которой это можно сделать.
Конечно, это решение, скорее всего не самое лучшее. И здесь можно много чего улучшать. Например, что если поменяется верстка? Уже не будет работать парсер. Поэтому нужно подумать об более универсальном подходе к получению пароля. Но цель была достигнута и такая связка прекрасно работает.
P.S. Пожалуйста пишите комментарии, что не так, что можно улучшить. Как написано: «Без доверительного разговора планы расстроятся, а при множестве советников будет успех».
Автор: 12pz21