dumbproxy — что нового?

от автора

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-адрес машины доменное имя и всё готово. Если доменного имени нет, то вот списочек с идеями где его взять:

  1. https://freemyip.com/

  2. https://www.dnshome.de/ — выбирать только поддомены *.dnshome.de, на остальных могут быть проблемы с лимитами на выпуски сертификатов.

  3. https://www.duckdns.org/

  4. https://dynv6.com/

  5. https://www.noip.com/

  6. https://now-dns.com/

  7. https://www.nsupdate.info/

Можно сказать, что этот список для бесплатных доменных имён исчерпывающий. Любые другие (например nip.io) не присутствуют в public domain suffix list-е и будут иметь проблемы с выпусками сертификатов из-за лимитов.

Вспомнить, как настраивать клиенты, можно в прошлом посте (архив).

Что ещё?


ссылка на оригинал статьи https://habr.com/ru/articles/870452/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *