Приветствую!
Сегодня напишем и опробуем простой, но продуманный bash скрипт, выполняющий клиентское подключение к OpenConnect VPN серверу, про запуск и настройку которого рассказывалось в одной из прошлых статей. Как говориться, “Нам нужно больше bash’а!”. Будет интересно (или больно) ;)
Присоединяйтесь к нашему каналу в телеграм: t.me/r4ven_me, уведомления о новых постах приходят туда в день публикации. А если у вас есть вопросы или просто желание пообщаться по тематике – заглядывайте в чат: t.me/r4ven_me_chat.
Предисловие
Еще раз напомню, что ранее мы с вами развернули свой VPN сервер на базе OpenConnect SSL based сервера (ocserv): Поднимаем OpenConnect SSL VPN сервер (ocserv) в docker для внутренних проектов.
А сегодня продемонстрирую работу скрипта клиентского подключения, который я написал с учетом одной полезной статьи на Habr, пресловутого ChatGPT и какой-то там матери.
Данный способ подключения предпочтителен на серверах без GUI, но на десктопе также прекрасно работает.
И так, начнем с описания логики работы.
Описание логики работы скрипта
Тут всё просто. Скрипт проверяет наличие исполняемого файла openconnect, затем в фоновом режиме выполняет подключение к VPN серверу ocserv и переходит в режим перманентного ожидания/проверки доступности внутреннего шлюза VPN. В случае 3-х неудачных попыток проверки доступности шлюза по пингу, скрипт завершает свою работу.
Но т.к. в нашем случае запуск/автозапуск скрипта будет выполнятся с помощью systemd, то после “аварийного” завершения скрипта, systemd перезапустить его через 5 секунд. Таким образом, подразумевается (но не гарантируется ) бесперебойная работа скрипта подключения.
Сам скрипт + systemd unit
Скрипт доступен по ссылке: https://github.com/r4ven-me/docker/blob/main/openconnect/openconnect-src/occlient.sh
B systemd unit: https://github.com/r4ven-me/docker/blob/main/openconnect/openconnect-src/occlient.service
Далее будет разбор скрипта, но если вам это не интересно, то сразу переходите к пункту “Установка и тестовый запуск“.
Разбор скрипта
Блок №1
В первом блоке устанавливаются специальные флаги обработки ошибок при работе скрипта. Является рекомендацией. Также тут универсальным образом задана переменная, которая содержит в себе путь до директории, из которой запускается скрипт. Её наличие тоже опционально, если вдруг вам понадобиться расширить функционал.
Блок №2
В этом блоке определяются пользовательские переменные. Это единственный блок, который обязательно необходимо модифицировать перед использованием. Как видно, тут определяются следующие значения:
- CERT_FILE – путь до файла пользовательского сертификата p12;
- CERT_PASS – пароль от этого файла;
- VPN_ADDRESS – адрес OpenConnect VPN сервера (ocserv);
- VPN_PORT – порт подключения к серверу;
- VPN_GATEWAY – адрес внутреннего VPN шлюза (необходим для проверки связи с сервером);
- SSL_FLAG – переменная, определяющая использование валидного SSL. 1 – да, 0 – нет.
Прошу обратить внимание, что хранить чувствительную информацию, такую, как пароли, внутри скриптов считается не безопасным. В данной статье я лишь демонстрирую работу.Как правильно использовать пароли внутри сценариев – это тема для отдельного поста. В будущем обязательно сделаю такой.
Блок №3
Этот блок определяет служебные переменные. Изменять их не требуется.
У нас тут:
- Переменная OC_BIN, значение которой определяется результатом команды which openconnect. Если в системе не установлена утилита openconnect, то при определении переменной команда завершится ошибкой, что в свою очередь завершит работу всего скрипта;
- Переменная VPN_COMMAND – используется функцией terminate_vpn (см. ниже) для идентификации процесса клиентского подключения, с целью его завершения;
- Переменная CHECK_INTERVAL, определяющая период ожидания между попытками проверки связи с внутренним шлюзом VPN;
- Переменная TIMEOUT – определяет время ожидания ответа при проверке связи с помощью утилиты ping в функции check_gateway (см. ниже);
- RETRY_COUNT – количество проверок.
Блок №4
Это функция вывода информационных сообщений, с префиксом в виде текущей метки времени и перенаправлением вывода в поток ошибок >&2.
Блок №5
Тут у нас функция, выполняющая завершение процесса клиентского подключения. Реализована с помощью команды pkill, которой аргументом передается имя команды подключения (VPN_COMMAND).
По теме управления процессами в Linux на сайте также есть отдельная статья: Командная строка Linux, процессы: команды jobs, fg, bg, ps, pgrep, kill, pkill, htop.
Блок №6
Это функция проверки доступности внутреннего шлюза VPN сервера с помощью утилиты ping. При успешной проверке функция возвращает 0, в ином случае 1. Логично)
Блок №7
В данном блоке выводится стартовое сообщение, затем выполняется проверка установленного флага SSL. В зависимости от его наличия, происходит соответствующее ветвление. В любом случае выполняется команда подключения к OpenConnect серверу, после чего, с помощью оператора контроля выполнения & она отправляется в фоновый режим, передавая работу следующему коду скрипта.
Обратите внимание, что тут присутствует закомментированная переменная VPN_PID, которая (если раскоментить) будет содержать в себе идентификатор (pid) последнего процесса, который был отправлен в фоновый режим, т.е. нашей команды подключения. Данный pid можно использовать вместо VPN_COMMAND. Тут уже на ваше усмотрение.
Блок №8
Последний блок представляет собой бесконечный цикл, который выполняет проверку доступности внутреннего шлюза VPN и в случае успешной проверки, переходит в режим ожидания длительностью в CHECK_INTERVAL, после чего вновь выполняет проверку.
В случае отсутствия связи, счетчик неудачных попыток (FAILED_COUNT) будет увеличиваться на единицу. Если значение этого счетчика превысит значение RETRY_COUNT, скрипт вызовет функцию остановки процесса подключения (terminate_vpn) и завершит работу.
Установка и тестовый запуск
При подключении клиентом будет выступать Ubuntu 22, а сервером Debian 12.
Скачивание скрипта
Хочу сразу обратить внимание, что при использовании подключения с помощью утилиты openconnect необходимы права суперпользователя.
Для установки скрипта вы можете скопировать его вручную из этой статьи или скачать из моего GitHub, например, такой командой:
sudo curl -fLo /root/occlient.sh https://raw.githubusercontent.com/r4ven-me/docker/main/openconnect/openconnect-src/occlient.sh
Она скопирует файл в домашнюю директорию пользователя root.
После скачивания, необходимо выдать скрипту права на исполнение:
sudo chmod 700 /root/occlient.sh
Про права на файлы я подробно рассказывал в статье: Командная строка Linux, права на файлы: команды id, chmod, chown.
Теперь открываем скрипт на редактирование любым редактором. Я предпочитаю Vim/Neovim:
sudo vim /root/occlient.sh
На моём сайте также есть цикл статей про этот консольный редактор. Посмотреть список можно по соответствующему тегу: Vim/Neoim.
Заменяем все значения в блоке Custom vars на свои, сохраняем файл и выходим.
ВАЖНО!
Не забудьте верно указать SSL флаг в переменной SSL_FLAG. Чтобы не возникло ошибок при запуске. Напомню, 1 – используется валидный SSL, 0 (или что угодно) – не используется.
В моём примере используется валидный SSL сертификат на сервере, поэтому переменная SSL_FLAG установлена в 1.
Запуск скрипта
Пробуем запуститься:
sudo /root/occlient.sh
Если вы все шаги проделали верно, то увидите примерно такую картину:
Подключение успешно.
Открываем соседнюю вкладку и проверяем доступ в интернет:
ping -c3 8.8.8.8
ip route get 8.8.8.8
Трафик идёт через виртуальный интерфейс, всё корректно.
Проверить внешний IP в терминале можно такой командой:
curl ifconfig.me
Возвращаемся на вкладку со скриптом и нажимаем Ctrl+c для выхода.
Активация автозапуска с помощью systemd
Теперь настроим автозапуск/перезапуск нашего скрипта. Для этого скачиваем systemd unit:
sudo curl -fLo /etc/systemd/system/occlient.service https://raw.githubusercontent.com/r4ven-me/docker/main/openconnect/openconnect-src/occlient.service
Затем открываем его на редактирование:
sudo vim /etc/systemd/system/occlient.service
И меняем в нём путь до файла скрипта:
Сохраняем, выходим.
Перечитываем конфигурацию systemd и активируем автозапуск нашего сервиса при старте системы, а также запускаем его:
sudo systemctl daemon-reload
sudo systemctl enable --now occlient
sudo systemctl status occlient
Готово.
Для просмотра вывода юнита occlient.service в реальном времени выполните:
sudo journalctl -fu occlient
Послесловие
Вот мы с вами и настроили автоматическое подключение/переподключение к OpenConnect серверу с проверкой доступности.
Вновь отмечу, что данный способ подключения предпочтителен на серверах без GUI. Потому что при использовании клиентов на десктопе, лучше заюзать плагин NetworkManager (если, конечно, за сеть у вас отвечает он). Процедура подключения такого клиента описана в соответствующем разделе статьи по настройке ocserv: 5.1 Настройка OpenConnect клиента для Linux.
Спасибо, что читаете. С подключением ;)
Полезные источники
Мои ссылки:
- Мой основной сайт - r4ven.me
- Мой телеграм - t.me/r4ven_me