
Устав искать нормальный портативный инструмент для переключения между моим рабочим прокси-сервером и прямым подключением дома (который, к тому же, работал бы на Windows и Linux), я решил-таки запилить собственную тулзу для этих целей. Вооружившись Python и Qt, начал клепать код в VSCode… Что из этого вышло — читаем под катом.
Мотивация
Основной мотивацией для создания данного инструмента стало жуткое неудобство системных настроек прокси при работе из офиса и дома. Каждый раз приходилось лезть в настройки прокси, передвигать флажок… А, кроме того, еще удалять или скрывать системные переменные HTTP_PROXY (и им подобные), чтобы консольные приложения вроде git также слушались руля… Это на Винде. А на Линуксе так вообще веселая история: не все графические системы имеют встроенные утилиты для управления настройками прокси, и моя Kali Linux как раз такая. Приходится вручную комментировать / раскомментировать экспорты переменных среды (той же HTTP_PROXY) и перелогиниваться… Морока, одним словом.
Беглый (а затем и не очень беглый) поиск в гугле / яндексе результатов не дал: предлагаются в основном плагины для браузеров, переключающие прокси только для браузера (системные настройки не изменяются). Нормальной легковесной, портативной, бесплатной, кроссплатформенной тулзы с графическим интерфейсом мне найти так и не удалось. И тогда, кряхтя и сопя от борьбы с ленью, открыл я VSCode и создал новый проект на Python…
Требования к инструменту
Почиркав в блокноте наброски GUI, я определился со следующими минимальными требованиями к приложению:
-
включение / выключение прокси-сервера одной кнопкой (с соответствующими автоматическими изменениями переменных среды)
-
настройки прокси должны быть постоянными, т.е. записываться в соответствующие системные файлы и оставаться после перезагрузки
-
возможность раздельных настроек для HTTP, HTTPS, FTP и (что бывает нужно для Unix) — RSYNC
-
импорт / экспорт настроек в / из файла
-
возможность подробного лога для отладки
Сразу скажу, что особой эстетичнойти GUI в минимальных требованиях не числилось. Главное — простота и интуитивность. Это так, чтобы вы меня не слишком терроризировали за дизайнерские способности 🙂
Где хранятся системные настройки прокси
Windows
На машинах под Windows настройки прокси хранятся (как и большинство других системных настроек) в реестре. А именно, в ветке HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings (таким образом, эти настройки задаются пользователем и не являются общесистемными).

За настройки прокси отвечают две переменные в реестре:
-
ProxyServer: адрес и порт прокси сервера, разделенные двоеточием (у моего прокси, например, адрес = 192.168.1.10, порт = 3128) -
ProxyOverride: разделенные запятыми адреса и маски адресов, которые должны работать по прямому соединению, минуя прокси (обычно сюда добавляется<local>, что означает localhost, т.е. не использовать прокси для локальных соединений)
Кроме того, многие приложения (в основном, консольные) берут настройки прокси не из реестра, а из специальных переменных среды:
-
HTTP_PROXY— прокси для HTTP-соединений в форматеhttp://[[USER]:[PASSWORD]@]HOST:PORT(например, «http://user:pass@192.168.1.1:3000» или если без прокси-аутентификации: «http://192.168.1.1:3000») -
HTTPS_PROXY— то же для HTTPS-соединений -
FTP_PROXY— то же для FTP-соединений -
RSYNC_PROXY— то же для RSYNC-соединений -
NO_PROXY— адреса в обход прокси (аналог вышеуказанногоProxyOverride)

Linux и MacOS
В Unix’ах, как водится, все настройки хранятся в обычных файлах: пользовательские — в директории текущего пользователя (~/...), системные — в директории /etc.
Настройки прокси задаются такими же переменными среды для соответствующих соединений (HTTP_PROXY и т.д.) + NO_PROXY для прямых адресов + иногда может встречаться переменная ALL_PROXY, задающая настройки для всех типов соединений.
Вот неполный перечень файлов, в которых обычно задаются переменные среды и иные настройки:
-
Пользователь:
~/.profile, ~/.bashrc, ~/.bash_profile, ~/.zshrc, ~/.cshrc, ~/.tcshrc, ~/.login -
Система:
/etc/environment, /etc/profile, /etc/bashrc, /etc/bash.bashrc, /etc/zsh/zshrc, /etc/csh.cshrc, /etc/csh.login
А еще, конечно, переменные могут определяться в скриптах, расположенных в специальных директориях: /etc/init.d, /etc/environment.d и т.п. Простор фантазии, в двух словах!
Структура приложения
➯ Приложение размещено на Github.
Структура приложения (писалось на Python 3.10) получилась такая:
-
?
doc/— документация (сделана при помощи Doxygen) -
?
resources/— иконки и картинки -
©
LICENSE— лицензионный файл (MIT License, т.е. полностью open-source, свободно для изменений и использования в т.ч. в коммерческих целях) -
✍
README.md— краткое описание -
?
proxen.py— главный файл для запуска приложения (создает объектQApplicationи запускает главный цикл с основным окном) -
?
gui.py— все GUI формы (виджеты Qt) -
?
qtimports.py— импорт пакетов Qt с поддержкой различных фреймворков: PyQt5, PyQt6, PySide2 и PySide6 (импортируется тот, который установлен) -
?
sysproxy.py— классы для работы с переменными среды и настройками прокси — «сердце» инструмента -
?
utils.py— глобальные переменные и полезные функции -
⚙
config.ini— файл с настройками приложения (пока там только включение лога и вывод его в консоль) -
?
config.py— соответствующий объект настроек (используется configparser) -
?
requirements.txt— зависимости, которые можно установить при помощи pip.
Принцип работы приложения
Работу приложения проще объяснить на визуальной схеме.

? Просмотр с возможностью зума ▶ ????.??
Окно приложения реализовано Qt-виджетом MainWindow. Связь между GUI и настройками прокси осуществляется при помощи 4 уровней абстракции:
-
Уровень ❹. Обычный питоновский словарь (dict)
localproxyсо следующими элементами:{ 'enabled': b_enabled, # статус прокси (вкл/выкл) 'http_proxy': { # настройки прокси для HTTP 'host': str_host, # адрес сервера 'port': n_port, # порт сервера 'auth': b_auth, # требуется ли аутентификация 'uname': str_username, # имя пользователя на прокси-сервере 'password': str_userpass # пароль пользователя }, 'https_proxy': { # настройки прокси для HTTPS # см. http_proxy }, 'ftp_proxy': { # настройки прокси для FTP # см. http_proxy }, 'rsync_proxy': { # настройки прокси для RSYNC # см. http_proxy }, 'noproxy': str_no_proxy # адреса (маски) без прокси через "," }Параметры элементов управления пользовательского интерфейса синхронизируются с этим локальным словарем. Пока пользователь не нажал кнопку
ApplyилиRestore, никакого взаимодействия с нижними уровнями не происходит. -
Уровень ❸. Объект
Proxy(sysproxy), реализующий те же параметры в виде свойств (properties). Свойства прокси (http_proxy,https_proxyи т.д.) — объекты типаProxyconf(инкапсулирующие параметры хоста, порта и аутентификации); свойство noproxy — объект типаNoproxy, который позволяет преобразовывать прямые адреса в список и в строку и обратно. Синхронизация со словаремlocalproxyосуществляется двумя методами:asdict()сериализует объектProxyв словарь,from_dict()— применяет данные из словаря. При изменении каждого свойства вызываются соответствующие setter-методы, которые и передают управление на нижестроящий уровень — объектSysenv. -
Уровень ❷. Класс
Sysenvопределяет основные методы для работы непосредственно с переменными среды и файлами, хранящими системные настройки. Для получения значения переменной среды (например,HTTP_PROXY) используется методget_sys_env(). Для изменения переменной и записи ее в соответствующий файл — методset_sys_env(). Для удаления переменной (из памяти и соответствующих файлов) —unset_sys_env(). Каждый из этих методов уже вызывает соответствующие низкоуровневые методы. -
Уровень ❶. На самом нижнем уровне используются специальные методы для работы с реестром Windows (чтение, запись, создание и удаление переменных в соответствующих ветках) и файлами Linux / Mac (чтение, изменение и удаление экспортов переменных среды). Как я уже говорил, на Винде за прокси отвечает пользовательская ветка в реестре (независимо от наличия прав администратора у текущего пользователя). На Unix’ах приложение по умолчанию работает с локальным файлом пользователя (зависящем от выбранного шелла, например, у меня это
~/.zshrc) и дополнительно, если есть права суперпользователя, также синхронизирует все переменные с системным файлом (по умолчанию —/etc/environment).
Стоит отметить еще два момента:
-
приложение реализовано с использованием многопоточности: операции работы с настройками прокси выполняются в отдельных потоках, чтобы не «замораживать» GUI
-
переключатель
Enableна первой вкладке сразу применяет настройки (без нажанияApply) — это было так задумано в рамках идеи «one-click switch»
Ручное управление переменными среды
Пока я отлаживал утилиту, я незаметно для себя реализовал еще один виджет для просмотра и управления всех переменных среды. При помощи этого инструмента я создавал, удалял и изменял произвольные переменные, следя, как программа работает с системными файлами. Позже я решил добавить эту возможность в само приложение и разместил кнопку Env variables на странице Settings.

Интерфейс до предела минималистичен. Я даже не буду ничего описывать, просто дам скрин 🙂

Эта «утилита в утилите» может применяться вместно штатных инструментов ОС.
Справочная документация
Она есть 🙂 По кнопке Help | Open docs открывается HTML-справка в браузере.

Весь код подробно прокомментирован, что позволяет пользоваться Doxygen для генерации документации для разработчиков:

На этом всё! Буду рад, если кому-то инструмент окажется полезным. Также можно направлять предложения в комментариях? или через страницу репозитория.
ссылка на оригинал статьи https://habr.com/ru/post/646407/
Добавить комментарий