История из практики
Рабочая задача: развернуть VPN на MikroTik с поддержкой L2TP и PPTP, авторизация — через Radius.
В роли серверов — стандартные для нас RouterOS CCR1016-12G. Параллельно возникло требование: подобрать клиент под Windows, чтобы можно было просто передать пользователям исполняемый файл, и они могли подключиться — без инструкций, .bat-файлов и шаманства.
Ключевое условие — не палить IPSEC_KEY.
Звучит несложно. Но, как это часто бывает, при попытке найти готовое решение стало ясно: либо его нет, либо оно недостаточно гибкое.
Ну и поехали. Ситуация была, скажем так, срочной. Почему — может, расскажу позже в Telegram-канале.
Результат: написал собственный VPN-клиент.
Ну как «написал» — взял PowerShell-скрипты, обернул в GUI на Python и получил рабочее приложение.
Почему не C#?
Потому что я умею в сети, а не в Cи-шарпы.
Python — мой максимум, и этого хватило, чтобы всё заработало.
Если вы думаете: «Очередной велосипед», — возможно, этот метериал не для вас.
Но если остались — покажу, как (не без помощи AI) я сделал удобный VPN-клиент, поделюсь исходниками и покажу, как собрать .exe под себя — с иконкой, версией и без лишнего гемора.
Приложение работает на Windows 10+ и выполняет следующее:
создаёт L2TP или PPTP-подключение средствами Windows;
добавляет маршруты (192.168.0.0/16, 10.0.0.0/8);
включает Split Tunneling — интернет остаётся через локального провайдера.
Ключевое: весь трафик не уходит в туннель а только трафик до серых сетей.
Плюс — Telegram-уведомления о подключениях: IP, гео, ОС, AS.
Не столько ради мониторинга, сколько для дебага и отладки.
Полный код и инструкции доступны:
Загрузка конфигурации
if getattr(sys, 'frozen', False): config_path = os.path.join(sys._MEIPASS, 'config.json') else: config_path = 'config.json' with open(config_path, 'r') as f: config = json.load(f)
Для сборки приложения через pyinstaller, путь к файлам будет отличаться. Это условие — чтобы искать config.json в нужном месте в обоих случаях.
По простому можно запустить код через PyCharm и протестировать что все работает перед сборкой приложения (PyCharm запускать тоже от администратора).

Переменные и константы
TELEGRAM_TOKEN = config['TELEGRAM_TOKEN'] ... SERVERS = { "111.111.111.111": {"name": "SERVER1", "gateway": "10.22.22.1"}, ... }
Все данные — в конфиге. Здесь мы храним Telegram-данные, IP-серверов и их шлюзы.
Проверка прав администратора
def is_admin(): return ctypes.windll.shell32.IsUserAnAdmin() != 0
VPN-команды требуют прав администратора. Если их нет — приложение сразу завершится.
Интерфейс на ttkbootstrap
root = ttk.Window(themename="darkly") app = VPNManagerApp(root) self.login_entry = ttk.Entry(root, bootstyle="info")
Используем ttkbootstrap — он делает обычный tkinter более симпатичным. Тема «darkly» даёт тёмный вид.
Добавляем поля ввода логина/пароля, выбор сервера, кнопки подключения и отключения.
Работа с VPN
subprocess.call("rasdial /disconnect", shell=True) command = f"rasdial \"{interface_name}\" {login} {password}"
Используем rasdial и Add-VpnConnection через PowerShell для создания, подключения и удаления VPN-соединений.
После подключения добавляются маршруты через route add.
Telegram-уведомления
await bot.send_message(chat_id=TELEGRAM_CHAT_ID, text=message, parse_mode="Markdown")
После подключения отправляется информация в Telegram: IP, страна, ОС, логин.
Логирование и безопасность
if hide_sensitive: message = message.replace(IPSEC_KEY, "[HIDDEN]")
Чтобы лог не слил пароль или PSK — замещаем конфиденциальные данные.
Что в итоге
Это приложение:
-
создаёт VPN соединение (L2TP/PPTP)
-
подключает его через rasdial
-
добавляет маршруты
-
логирует каждый шаг
-
отправляет информацию о подключении в Telegram
-
показывает красивый GUI на Python
🚀 Сборка VPN-клиента в .exe: от иконки до метаданных
После того как мы написали рабочий VPN GUI-клиент, пора собрать его в .exe, чтобы можно было запускать на любом Windows-компьютере без Python и консоли.
Разберем по шагам, как именно я это делал.
version.txt — метаинформация
StringStruct('FileDescription', 'VPN-клиент для Windows с GUI и Telegram-уведомлениями') ... StringStruct('CompanyName', 'netscripor')
Файл version.txt задаёт, что будет отображаться в свойствах .exe:
-
имя продукта;
-
автор;
-
версия;
-
описание;
-
иконка и прочее. Полный пример — в репозитории.
Команда сборки с PyInstaller
pyinstaller --onefile --noconsole --uac-admin --icon=vpn.ico --version-file=version.txt --add-data "pp.png;." --add-data "vpn.ico;." --add-data "config.json:." "main.py"
Разберем, что делает каждая часть:
|
Аргумент |
Назначение |
|---|---|
|
—onefile |
Всё в одном .exe без папки dist |
|
—noconsole |
Не открывать черное окно консоли при запуске |
|
—uac-admin |
Требовать права администратора при запуске |
|
—icon=vpn.ico |
Иконка приложения |
|
—version-file=version.txt |
Метаданные для свойства файла |
|
—add-data «pp.png;.» |
Картинка логотипа в GUI |
|
—add-data «vpn.ico;.» |
Иконка в окне программы |
|
—add-data «config.json;.» |
Конфиг-файл (внимание: подставляется тестовая версия!) |
|
Главный исполняемый файл |
После выполнения команды в каталоге dist/ появится main.exe, готовый к запуску. Он будет:
-
выглядеть как полноценное Windows-приложение (с иконкой и описанием),
-
требовать админ-доступ при запуске,
-
не показывать консоль,
-
работать независимо от наличия Python на ПК.

📌 Заключение
Да, это не Enterprise-решение.
Но оно решает конкретную задачу: простой, автономный, настраиваемый VPN-клиент под Windows с поддержкой Split Tunneling и Telegram-логированием. И главное — его можно дорабатывать под себя.
Если статья была полезной — звёздочку на GitHub и подписку в Telegram я восприму с благодарностью.
ссылка на оригинал статьи https://habr.com/ru/articles/928242/
Добавить комментарий