dumbproxy уже упоминался на Хабре в одной из моих прошлых статей. Это HTTP(S) прокси-сервер, который работает через TLS, напрямую совместим с браузерами и браузерными расширениями, и имеет заметное количество дополнительных функций, расширяющих его границы применимости и облегчающих его использование.
Новые возможности
За последние месяцы проект заметно подрос. Пройдёмся по новым функциям!
Аутентификация
В дополнение к базовой аутентификации по логину-паролю и аутентификации по сертификатам, появилась возможность использовать HMAC-коды, передаваемые как логин и пароль. В первом приближении это похоже на JWT с HS256-подписями, но в более компактном, бинарном формате.
Это позволяет использовать централизованную авторизацию на множестве экземпляров dumbproxy без нужды взаимодействовать с центральным сервисом авторизации на каждый запрос доступа. Клиент самостоятельно получает от центрального сервиса логин и пароль, который будет действовать какое-то время, при этом такой логин и пароль нигде не хранится и передаётся серверу dumbproxy клиентом в момент запроса и может быть верифицирован без сетевых взаимодействий с центральным сервером авторизации. Эта возможность потенциально может заинтересовать разработчиков прокси-сервисов на базе dumbproxy и позволяет использовать его как прокси-бэкенд в таких сервисах.
Из менее значительного: добавился блэклист сертификатов при использовании авторизации по сертификатам.
Скриптинг
Некоторые стадии обработки запроса в dumbproxy теперь могут быть определены скриптами на JS. На данный момент это фильтрация запросов (разрешение или запрещение доступа) и выбор вышестоящего прокси или исходящего сетевого интерфейса.
Фильтрация запросов
Проиллюстрируем, как это выглядит на практике. Для примера, вот как выглядит access-скрипт, повторяющий правила из стандартного конфига Squid, которые ограничивают подключения только на «безопасные» порты:
// Deny unsafe ports for HTTP and non-SSL ports for HTTPS. const SSL_ports = [ 443, ] const Safe_ports = [ 80, // http 21, // ftp 443, // https 70, // gopher 210, // wais 280, // http-mgmt 488, // gss-http 591, // filemaker 777, // multiling http ] const highPortBase = 1025 function access(req, dst, username) { if (req.method == "CONNECT") { if (SSL_ports.includes(dst.port)) return true } else { if (dst.port >= highPortBase || Safe_ports.includes(dst.port)) return true } return false }
Для его применения достаточно задать опцию -js-access-filter
с путём к скрипту.
Выбор вышестоящего прокси или исходящего адреса
Работает аналогично предыдущему, рассмотрим примеры.
Нужно отправить onion-домены в Tor? Запросто.
// Redirect .onion hidden domains to Tor SOCKS5 proxy function getProxy(req, dst, username) { if (dst.originalHost.replace(/\.$/, "").toLowerCase().endsWith(".onion")) { return "socks5://127.0.0.1:9050" } return "" }
Размазать трафик по нескольким машинам с переменой адреса раз в 10 минут? Легко.
const serverList = [ "https://USERNAME:PASSWORD@m1.example.com:443", "https://USERNAME:PASSWORD@m2.example.com:443", "https://USERNAME:PASSWORD@m3.example.com:443", "https://USERNAME:PASSWORD@m4.example.com:443", "https://USERNAME:PASSWORD@m5.example.com:443", "https://USERNAME:PASSWORD@m6.example.com:443", "https://USERNAME:PASSWORD@m7.example.com:443", "https://USERNAME:PASSWORD@m8.example.com:443", ] const rotationPeriod = 600 // 10 minutes function getProxy() { const ts = Math.floor(Date.now() / 1000) return serverList[Math.floor(ts / rotationPeriod) % serverList.length] }
Отправить трафик на какие-то домены в VPN-туннель? Ну… если правила PBR насчёт выбора таблицы маршрутизации на основе исходящего адреса уже готовы, то пожалуйста.
function getProxy(req, dst, username) { const normalizedHostname = dst.originalHost.replace(/\.$/, "").toLowerCase() if (normalizedHostname === "2ip.ru" || normalizedHostname.endsWith(".2ip.ru")) { return "set-src-hints://?hints=10.2.0.2" } return "" }
Кэширование выписываемых сертификатов
dumbproxy поддерживает автоматический выпуск сертификатов на своё доменное имя достаточно давно, и для этого использовался простой кэш сертификатов в локальной директории. Однако теперь возможности в этой области расширены:
-
Теперь в качестве хранилища можно использовать Redis и Redis Cluster.
-
Опционально доступна кэширующая прослойка в памяти процесса.
-
Опционально доступно шифрование кэша AEAD-шифрованием (XChaCha20Poly1305)
Вынос кэша сертификатов во внешнее хранилище прокладывает путь к stateless-развёртываниям. То есть сервер не хранит никакого состояния локально и может быть удалён/пересоздан хоть каждые 10 минут без проблем с (пере)выпуском сертификатов. К слову, бесплатные инстансы редиса на https://cloud.redis.io/ неплохо справляются, файл с опциями выглядит примерно так:
OPTIONS=-auth basicfile://?path=/var/lib/dumbproxy/dumbproxy.htpasswd \ -autocert \ -autocert-local-cache-ttl 24h \ -autocert-cache-redis redis://default:xxxxxxxx@redis-16273.c528.europe-west3-1.gce.redns.redis-cloud.com:16273/0 DUMBPROXY_CACHE_ENC_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Функции для операторов крупных инсталляций
Локальный кэш DNS
Появилась опция, которая принудительно кэширует соответствия доменных имён адресам. Главным образом она нужна операторам прокси с множеством клиентов, которые почему-то используют публичные DNS-резолверы типа 8.8.8.8 и 1.1.1.1, и получают от них негативные ответы за большую частоту запросов.
Я бы вместо этого лучше посоветовал бы развернуть локальный knot-resolver или unbound с кэшом, но не для всех это приемлемо.
Лимит полосы пропускания для каждого пользователя
Эта функция полезна для тех же самых операторов крупных инсталляций, чтобы более честно распределить канал между пользователями, да и в целом сделать сверхпотребление (например, ютуб в 4к) непрактичным.
Есть ещё несколько мелочей, о которых я не упомянул, но лучше оставим это внимательным читателям документации и поговорим о развёртывании.
Новые развёртывания
А развёртывание dumbproxy с авторизацией и общепризнаваемыми TLS-сертификатами теперь совсем простое. Не нужно даже заходить на сервер по SSH!
Для хостеров, которые поддерживают cloud-init (24.3.1 или новее, берите ubuntu 24.10 — не ошибётесь), достаточно при создании виртуалки указать следующий конфиг (не забудьте заменить USERNAME
и PASSWORD
на настоящие!):
## template: jinja #cloud-config write_files: - source: {% if v1.machine == 'aarch64' %} uri: https://github.com/SenseUnit/dumbproxy/releases/download/v1.20.0/dumbproxy.linux-arm64 {% else %} uri: https://github.com/SenseUnit/dumbproxy/releases/download/v1.20.0/dumbproxy.linux-amd64 {% endif %} path: /usr/local/bin/dumbproxy permissions: '0755' - content: | OPTIONS=-auth basicfile://?path=/etc/dumbproxy.htpasswd -autocert -bind-address :443 path: /etc/default/dumbproxy - content: | [Unit] Description=Dumb Proxy Documentation=https://github.com/SenseUnit/dumbproxy/ After=network.target network-online.target Requires=network-online.target [Service] EnvironmentFile=/etc/default/dumbproxy User=root Group=root ExecStart=/usr/local/bin/dumbproxy $OPTIONS TimeoutStopSec=5s PrivateTmp=true ProtectSystem=full LimitNOFILE=20000 [Install] WantedBy=default.target path: /etc/systemd/system/dumbproxy.service runcmd: - [dumbproxy, -passwd, /etc/dumbproxy.htpasswd, USERNAME, PASSWORD] - [systemctl, daemon-reload] - [systemctl, enable, --now, --no-block, dumbproxy.service]
На всякий случай, если возникнут проблемы с ориентированием, окошко для cloud-init-а обычно выглядит примерно так:
Остаётся навесить на IP-адрес машины доменное имя и всё готово. Если доменного имени нет, то вот списочек с идеями где его взять:
-
https://www.dnshome.de/ — выбирать только поддомены *.dnshome.de, на остальных могут быть проблемы с лимитами на выпуски сертификатов.
Можно сказать, что этот список для бесплатных доменных имён исчерпывающий. Любые другие (например nip.io) не присутствуют в public domain suffix list-е и будут иметь проблемы с выпусками сертификатов из-за лимитов.
Вспомнить, как настраивать клиенты, можно в прошлом посте (архив).
Что ещё?
ссылка на оригинал статьи https://habr.com/ru/articles/870452/
Добавить комментарий