Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
reproxy — Легковесный граничный HTTP(S) сервер и обратный прокси с автоматическим SSL, обнаружением Docker/Consul, аутентификацией по маршрутам, ограничением скорости и отказоустойчивостью на основе проверки здоровья. | Kitploit
Инструменты/GitHubGitHub/umputun/reproxy
Аутентификация и авторизацияУтилиты общего назначенияВеб-безопасностьСетевая безопасностьБезопасность API
GitHubumputun/reproxy

reproxy

Легковесный граничный HTTP(S) сервер и обратный прокси с автоматическим SSL, обнаружением Docker/Consul, аутентификацией по маршрутам, ограничением скорости и отказоустойчивостью на основе проверки здоровья.

Репозиторий
1.3k96115 ч 6 мин назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Сайт
Reproxy | Простой обратный прокси

Reproxy — это простой пограничный HTTP(s) сервер/обратный прокси, поддерживающий различные провайдеры (docker, static, file, consul catalog). Один или несколько провайдеров предоставляют информацию о запрашиваемом сервере, запрашиваемом URL, целевом URL и URL проверки работоспособности. Распространяется как единый бинарный файл или как docker-контейнер.

  • Автоматическое завершение SSL с Let's Encrypt
  • Поддержка пользовательских SSL-сертификатов
  • Простые, но гибкие правила прокси
  • Провайдер статических правил прокси из командной строки
  • Динамический провайдер правил прокси на основе файлов
  • Docker-провайдер с автоматическим обнаружением
  • Провайдер Consul Catalog с обнаружением по тегам сервисов
  • Поддержка нескольких (виртуальных) хостов
  • Опциональное сжатие трафика
  • Опциональный контроль доступа на основе IP
  • Базовая аутентификация для каждого маршрута
  • Заданные пользователем ограничения размера и таймауты
  • Единый бинарный файл
  • Docker-контейнер
  • Встроенный сервер статических ассетов с опциональным режимом "SPA friendly"
  • Поддержка правил перенаправления
  • Опциональный ограничитель как общей активности, так и активности пользователя
  • Проверка работоспособности в реальном времени и отказоустойчивость/балансировка нагрузки
  • Управляющий сервер с информацией о маршрутах и метриками prometheus
  • Поддержка плагинов через RPC для реализации собственной функциональности
  • Опциональное логирование в формате Apache Log Format и упрощённые отчёты в stdout.

build Coverage Status Go Report Card Docker Hub

Сервер (хост) может быть задан как FQDN, например s.example.com, * (любой) или регулярное выражение. Точное совпадение имеет приоритет, поэтому если есть два правила с серверами example.com и example\.(com|org), запрос к example.com/some/url будет соответствовать первому. Запрашиваемый URL может быть регулярным выражением, например ^/api/(.*), а целевой URL может содержать группы из регулярного выражения, например http://d.example.com:8080/$1. Для приведённого примера запрос http://s.example.com/api/something?foo=bar будет проксирован на http://d.example.com:8080/something?foo=bar.

Для удобства запросы с завершающим / и без групп регулярного выражения расширяются до /(.*), а целевые адреса в таких случаях расширяются до /$1. То есть /api/ -> http://127.0.0.1/service будет преобразовано в ^/api/(.*) -> http://127.0.0.1/service/$1.

Поддерживается подстановка хоста в целевой URL. Например, /files/${host} будет заменено на имя соответствующего хоста. Также можно использовать $host (без фигурных скобок).

Поддерживаются как HTTP, так и HTTPS. Для HTTPS можно использовать статический сертификат, а также автоматические сертификаты ACME (Let's Encrypt). Опциональный сервер ассетов может использоваться для раздачи статических файлов. Для запуска reproxy требуется как минимум один определённый провайдер. Остальные параметры строго опциональны и имеют разумные значения по умолчанию.

Примеры:

  • со статическим провайдером: reproxy --static.enabled --static.rule="*,example.com/api/(.*),https://api.example.com/$1"
  • с автоматическим обнаружением docker: reproxy --docker.enabled --docker.auto
  • как docker-контейнер: docker up -p 80:8080 umputun/reproxy --docker.enabled --docker.auto
  • с автоматическим SSL: docker up -p 80:8080 -p 443:8443 umputun/reproxy --docker.enabled --docker.auto --ssl.type=auto --ssl.fqdn=example.com

Установка

Reproxy распространяется как небольшой самодостаточный бинарный файл, а также как docker-образ. И бинарный файл, и образ поддерживают несколько архитектур и несколько операционных систем, включая linux_x86_64, linux_arm64, linux_arm, macos_x86_64, macos_arm64, windows_x86_64 и windows_arm. Мы также предоставляем deb- и rpm-пакеты для arm64 и x86.

  • для бинарной версии загрузите соответствующий файл из раздела релизов
  • для пользователей Homebrew: brew install umputun/apps/reproxy
  • docker-контейнер доступен на Docker Hub, а также на Github Container Registry. Например, docker pull umputun/reproxy или docker pull ghcr.io/umputun/reproxy.

Последняя стабильная версия имеет docker-тег :vX.Y.Z (с псевдонимом :latest), а текущий master — тег :master.

Провайдеры

Правила прокси предоставляются различными провайдерами. В настоящее время включены: file, docker, static и consul-catalog. Каждый провайдер может определять несколько правил маршрутизации как для проксируемых запросов, так и для статических ресурсов (assets). Пользователь может одновременно задавать несколько провайдеров.

Примеры различных провайдеров смотрите в examples

Статический провайдер

Это самый простой провайдер, определяющий все правила сопоставления непосредственно в командной строке (или окружении). Поддерживается несколько правил. Каждое правило состоит из 3–7 элементов, разделённых запятыми: server,sourceurl,destination[,ping-url[,forward-health-checks[,timeout[,throttle]]]]. Например:

  • *,^/api/(.*),https://api.example.com/$1 — проксировать все запросы к любому хосту/серверу с префиксом /api на https://api.example.com
  • example.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping — проксировать все запросы к example.com с URL /foo/bar на https://api.example.com/zzz; для проверки работоспособности используется https://api.example.com/ping.
  • example.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping,true — то же самое, но также перенаправляет запросы /ping и /health на бэкенд.
  • example.com,^/upload/(.*),https://api.example.com/$1,,,5m — таймаут запроса для маршрута 5 минут (4-е и 5-е поля оставлены пустыми, чтобы пропустить ping-url и forward-health-checks).

Четвёртый элемент задаёт опциональный ping-URL, используемый для отчётов о работоспособности. Пятый элемент опционально включает перенаправление запросов проверки работоспособности на бэкенд (true, yes, 1). Подробнее см. раздел Проверка работоспособности. Шестой элемент — опциональный таймаут запроса для маршрута (длительность Go, например 5m, 30s); 0 или пустое значение наследует глобальную настройку --timeout.write. Седьмой элемент — опциональное ограничение запросов/сек на пользователя для маршрута; 0 или пустое значение наследует --throttle.user. Допускается оставлять поля пустыми (например, ,, для неиспользуемых средних полей).

Файловый провайдер

Этот провайдер использует yaml-файл с правилами маршрутизации.

reproxy --file.enabled --file.name=config.yml

Пример config.yml:```yaml default: # the same as * (catch-all) server

  • { route: "^/api/svc1/(.*)", dest: "http://127.0.0.1:8080/blah1/$1" }
  • { route: "/api/svc3/xyz", dest: "http://127.0.0.3:8080/blah3/xyz", ping: "http://127.0.0.3:8080/ping", remote: "192.168.1.0/24, 127.0.0.1", # optional, restrict access to the route forward-health-checks: true # optional, forward /ping and /health to backend }
  • { route: "^/admin/(.*)", dest: "http://127.0.0.4:8080/$1", auth: "admin:$2y$05$..." # optional, per-route basic auth (htpasswd bcrypt format) }
  • { route: "^/upload/(.*)", dest: "http://127.0.0.5:8080/$1", timeout: 5m # optional, per-route request timeout (Go duration). 0 or omitted inherits --timeout.write }
  • { route: "^/login", dest: "http://127.0.0.6:8080/login", throttle: 2 # optional, per-route req/sec per user. 0 or omitted inherits --throttle.user } srv.example.com:
  • { route: "^/api/svc2/(.*)", dest: "http://127.0.0.2:8080/blah2/$1/abc" }
  • { route: "/web/", dest: "/var/www", "assets": true } "*.files.example.com":
  • { route: "^/files/(.*)", dest: "http://123.123.200.200:8080/$host/$1" }
root@kitploit:~
Это динамический провайдер, и изменение файла будет применено автоматически.

**Несколько статических сайтов на разных доменах** можно обслуживать, используя имена серверов в качестве ключей с `assets: true`:```yaml
site-en.example.com:
  - { route: "/", dest: "/var/www/en", "assets": true }
site-ru.example.com:
  - { route: "/", dest: "/var/www/ru", "assets": true }

Важно: поле route для правил статических ресурсов должно быть префиксом пути (например, /, /web/), а не регулярным выражением. Шаблоны регулярных выражений, такие как ^/(.*), не будут работать с assets: true, потому что сопоставление статических ресурсов использует сравнение префиксов путей, а не регулярные выражения.

Провайдер Docker

Провайдер Docker поддерживает полностью автоматическое обнаружение (с --docker.auto) без необходимости дополнительной настройки. По умолчанию он перенаправляет все запросы вида http://<url>/<имя контейнера>/(.*) на внутренний IP указанного контейнера и открытый порт. Обнаруживаются только активные (работающие) контейнеры.

Это поведение по умолчанию можно изменить с помощью меток:

  • reproxy.server — сервер (имя хоста) для сопоставления. Также может быть списком серверов, разделённых запятыми.
  • reproxy.route — исходный маршрут (расположение)
  • reproxy.dest — путь назначения. Примечание: это не полный URL, а только путь, который будет добавлен к ip:порту контейнера.
  • reproxy.port — порт назначения для обнаруженного контейнера
  • reproxy.ping — путь ping для контейнера назначения.
  • reproxy.remote — ограничить доступ к маршруту списком подсетей или IP-адресов, разделённых запятыми
  • reproxy.auth — требовать базовую аутентификацию для маршрута с парами user:bcrypt_hash, разделёнными запятыми (сгенерированными с помощью htpasswd -nbB)
  • reproxy.assets — задать сопоставление ресурсов в формате web-root:location, например reproxy.assets=/web:/var/www

Обратите внимание: без --docker.auto контейнер назначения должен иметь хотя бы одну из меток reproxy.*, чтобы рассматриваться как потенциальное место назначения.

С --docker.auto все контейнеры с открытыми портами будут рассматриваться как маршруты назначения. Есть 3 способа ограничить это:

  • Явно исключить некоторые контейнеры с помощью --docker.exclude, например --docker.exclude=c1 --docker.exclude=c2 ...
  • Разрешить только определённую сеть Docker с помощью --docker.network
  • Установить метку reproxy.enabled=false или reproxy.enabled=no или reproxy.enabled=0

Если не задан reproxy.route, маршрут по умолчанию — ^/<container_name>/(.*). Если все проксируемые источники должны иметь одинаковый шаблон префикса, например /api/(.*), пользователь может определить общий префикс (в данном случае /api) для всех маршрутов на основе контейнеров. Это можно сделать с помощью параметра --docker.prefix.

Провайдер Docker также позволяет определять несколько наборов меток reproxy.N.something для сопоставления нескольких различных маршрутов на одном контейнере. Это полезно, так как в некоторых случаях один контейнер может предоставлять несколько конечных точек, например, публичный API и какой-нибудь административный API. Все перечисленные выше метки можно использовать с «N-индексом», т.е. reproxy.1.server, reproxy.1.port и так далее. N должно быть в диапазоне от 0 до 9.

Это динамический провайдер, и любые изменения статуса контейнера будут применяться автоматически.

Провайдер Consul Catalog

Использование: reproxy --consul-catalog.enabled

Провайдер Consul Catalog периодически вызывает API Consul (по умолчанию каждую секунду) для получения сервисов, имеющих любой тег с префиксом reproxy.. Пользователь может изменить интервал проверки с помощью флага командной строки --consul-catalog.interval, а также адрес Consul с помощью параметра командной строки --consul-catalog.address. Адрес по умолчанию — http://127.0.0.1:8500.

Например:``` reproxy --consul-catalog.enabled --consul-catalog.address=http://192.168.1.100:8500 --consul-catalog.interval=10s

root@kitploit:~
По умолчанию провайдер устанавливает значения для каждого сервиса:
- enabled `false`
- server `*`
- route `^/(.*)`
- dest `http://<SERVICE_ADDRESS_FROM_CONSUL>/$1`
- ping `http://<SERVICE_ADDRESS_FROM_CONSUL>/ping`

Это значение по умолчанию можно изменить с помощью тегов:

- `reproxy.server` — сервер (имя хоста) для сопоставления. Также может быть списком серверов, разделённых запятыми.
- `reproxy.route` — исходный маршрут (расположение)
- `reproxy.dest` — путь назначения. Примечание: это не полный URL, а только путь, который будет добавлен к ip:port сервиса.
- `reproxy.port` — порт назначения для обнаруженного сервиса
- `reproxy.remote` — ограничение доступа к маршруту списком подсетей или IP-адресов, разделённых запятыми
- `reproxy.auth` — требование базовой аутентификации для маршрута с парами `user:bcrypt_hash`, разделёнными запятыми (сгенерировано с помощью `htpasswd -nbB`)
- `reproxy.ping` — путь ping для целевого сервиса.
- `reproxy.forward-health-checks` — перенаправление запросов `/ping` и `/health` на бэкенд (`true`, `yes`, `1`).
- `reproxy.timeout` — таймаут запроса для маршрута в формате Go duration (например, `5m`, `30s`). `0` или неустановленное значение наследует глобальный `--timeout.write`. Некорректные значения игнорируются с предупреждением.
- `reproxy.throttle` — ограничение запросов в секунду на пользователя для маршрута. `0` или неустановленное значение наследует `--throttle.user`. Некорректные или отрицательные значения игнорируются с предупреждением.
- `reproxy.enabled` — включение (`yes`, `true`, `1`) или отключение (любое другое значение) сервиса из целей reproxy.

### Особенности работы с Compose

Если правила задаются в составе окружения docker compose, назначение с группой регулярного выражения будет конфликтовать с синтаксисом compose. То есть попытка использовать `https://api.example.com/$1` в среде compose приведёт к синтаксической ошибке. Стандартное решение — «экранировать» знак `$`, заменив его на `$$`, т.е. `https://api.example.com/$$1`. Эта подстановка поддерживается docker compose и не имеет отношения к самому reproxy. Другой способ — использовать `@` вместо `$`, что поддерживается на уровне reproxy, т.е. `https://api.example.com/@1`_

## Поддержка SSL

Режим SSL (по умолчанию none) может быть установлен в `auto` (сертификаты ACME/LE), `static` (существующий сертификат) или `none`. Если включён режим `auto`, SSL-сертификат будет выдаваться автоматически для всех обнаруженных имён серверов. Пользователь может переопределить это, установив значения `--ssl.fqdn`. В режимах SSL `auto` и `static` Reproxy автоматически добавляет заголовки `X-Forwarded-Proto` и `X-Forwarded-Port`. Эти заголовки полезны для сервисов за прокси, чтобы узнать исходный протокол (http или https) и номер порта, используемые клиентом.

При использовании ACME с провайдерами обнаружения (docker, file, consul) SSL-сертификаты автоматически получаются для вновь обнаруженных серверов без необходимости перезапуска reproxy.

### Проблемы ACME

Reproxy поддерживает два типа задач ACME для проверки SSL-сертификатов:

1. **HTTP-01 Challenge** (по умолчанию): Проверяет владение доменом, предоставляя токен по определённому HTTP-URL. Требует общедоступности порта 80.

2. **DNS-01 Challenge**: Проверяет владение доменом путём создания DNS TXT-записей. Этот метод:
   - Не требует доступности порта 80
   - Работает с подстановочными сертификатами
   - Требует настройки поддерживаемого DNS-провайдера

#### Выбор задачи

Reproxy автоматически определяет, какой метод проверки использовать, исходя из вашей конфигурации:

- **HTTP-01** (по умолчанию): Используется, если DNS-провайдер не настроен
- **DNS-01**: Используется, если DNS-провайдер настроен

Вам не нужно явно выбирать тип задачи — достаточно настроить DNS-провайдера, если вы хотите использовать DNS-01.

#### Текущие поддерживаемые DNS-провайдеры

В настоящее время Reproxy включает поддержку следующих DNS-провайдеров:

- **Cloudflare**: `--ssl.dns.type=cloudflare --ssl.dns.cloudflare.api-token=TOKEN`
- **Route53 (AWS)**: `--ssl.dns.type=route53 --ssl.dns.route53.region=REGION --ssl.dns.route53.hosted-zone-id=ID`
- **Gandi**: `--ssl.dns.type=gandi --ssl.dns.gandi.bearer-token=TOKEN`
- **DigitalOcean**: `--ssl.dns.type=digitalocean --ssl.dns.digitalocean.api-token=TOKEN`
- **Hetzner**: `--ssl.dns.type=hetzner --ssl.dns.hetzner.api-token=TOKEN`
- **Linode**: `--ssl.dns.type=linode --ssl.dns.linode.api-token=TOKEN`
- **GoDaddy**: `--ssl.dns.type=godaddy --ssl.dns.godaddy.api-token=TOKEN`
- **Namecheap**: `--ssl.dns.type=namecheap --ssl.dns.namecheap.api-key=KEY --ssl.dns.namecheap.user=USER`
- **Scaleway**: `--ssl.dns.type=scaleway --ssl.dns.scaleway.secret-key=KEY --ssl.dns.scaleway.organization-id=ID`
- **Porkbun**: `--ssl.dns.type=porkbun --ssl.dns.porkbun.api-key=KEY --ssl.dns.porkbun.api-secret-key=SECRET`
- **DNSimple**: `--ssl.dns.type=dnsimple --ssl.dns.dnsimple.api-access-token=TOKEN --ssl.dns.dnsimple.account-id=ID`
- **DuckDNS**: `--ssl.dns.type=duckdns --ssl.dns.duckdns.api-token=TOKEN`

Пример с Cloudflare в качестве DNS-провайдера:```
export CLOUDFLARE_API_TOKEN=your_api_token
reproxy --ssl.type=auto [email protected] --ssl.fqdn=example.com

Испытание DNS-01 особенно полезно, когда:

  • Ваш сервер не имеет открытого порта 80
  • Вам нужны wildcard-сертификаты (например, *.example.com)
  • Вы находитесь за строгими файрволами

Заголовки

Reproxy позволяет очищать (удалять) входящие заголовки с помощью параметра --drop-header (можно повторять). Этот параметр может быть полезен, чтобы гарантировать, что некоторые заголовки, установленные внутренними службами, не могут быть установлены/подделаны конечным пользователем. Например, если некоторые службы, отвечающие за аутентификацию, устанавливают X-Auth-User и X-Auth-Token, вероятно, имеет смысл удалить эти заголовки из входящих запросов, передав параметр --drop-header=X-Auth-User --drop-header=X-Auth-Token или через переменную окружения DROP_HEADERS=X-Auth-User,X-Auth-Token

Также поддерживается противоположная функция — установка исходящих заголовков. Это может быть полезно во многих случаях, например, для применения пользовательских правил CORS, заголовков безопасности и т.д. Это можно сделать с помощью параметра --header (можно повторять) или переменной окружения HEADER. Например, вот как это можно сделать с помощью docker compose:```yaml environment: - HEADER= X-Frame-Options:SAMEORIGIN, X-XSS-Protection:1; mode=block;, Content-Security-Policy:default-src 'self'; style-src 'self' 'unsafe-inline';

root@kitploit:~
## Логирование

По умолчанию журнал запросов не создается. Это можно включить, установив `--logger.enabled`. Журнал (с автоматической ротацией) имеет [Apache Combined Log Format](http://httpd.apache.org/docs/2.2/logs.html#combined)

Пользователь также может включить вывод журнала в stdout с помощью `--logger.stdout`. Это не повлияет на ведение журнала в файл, описанное выше, но выведет некоторую минимальную информацию об обработанных запросах, например:```
2021/04/16 01:17:25.601 [INFO]  GET - /echo/image.png - xxx.xxx.xxx.xxx - 200 (155400) - 371.661251ms
2021/04/16 01:18:18.959 [INFO]  GET - /api/v1/params - xxx.xxx.xxx.xxx - 200 (74) - 1.217669m

Сервер статических файлов

Пользователи могут включить сервер статических файлов (по умолчанию выключен) для обслуживания статичных файлов. Если --assets.location задан, то каждый непроксируемый запрос к assets.root обрабатывается как запрос к статическому файлу. Сервер статических файлов может использоваться без каких-либо прокси-провайдеров; в этом режиме reproxy выступает в роли простого веб-сервера для статического контента. Сервер статических файлов также поддерживает "spa-режим" с помощью --assets.spa, при котором все запросы, не найденные на сервере, перенаправляются на index.html.

Помимо общего сервера статических файлов поддерживаются несколько пользовательских серверов. Каждый провайдер имеет свой способ определения такого статического правила, некоторые провайдеры могут вообще его не поддерживать. Например, несколько серверов статических файлов имеют смысл в статическом (строковый провайдер), файловом провайдере и даже полезны с Docker-провайдером, но совершенно нелогичны с провайдером consul catalog.

  1. статический провайдер — если исходный элемент имеет префикс assets: или spa:, он будет обрабатываться как файловый сервер. Например, *,assets:/web,/var/www, будет обслуживать все запросы /web/* с помощью файлового сервера из каталога /var/www.
  2. файловый провайдер — установка необязательных полей assets: true или spa: true. Примечание: поле route должно быть префиксом пути (например, /, /web/), а не регулярным выражением.
  3. Docker-провайдер — reproxy.assets=web-root:location, т.е. reproxy.assets=/web:/var/www. Переключение в spa-режим осуществляется установкой reproxy.spa в или .

Кэширование

Сервер статических файлов поддерживает управление кэшированием с помощью параметра --assets.cache=<длительность>. Длительность 0s (по умолчанию) отключает управление кэшированием. Длительность — это последовательность десятичных чисел, каждое с необязательной дробной частью и суффиксом единицы, например "300ms", "1.5h" или "2h45m". Допустимые единицы времени: "ns", "us" (или "µs"), "ms", "s", "m", "h" и "d".

Есть два способа задать длительность кэширования:

  1. Одно значение для всех статических файлов. Это просто: --assets.cache=48h.
  2. Задать длительность для разных MIME-типов. Должно включать две части — значение по умолчанию и пары mime:длительность. В командной строке это выглядит как несколько опций --assets.cache, например, --assets.cache=48h --assets.cache=text/html:24h --assets.cache=image/png:2h. В переменных окружения значения должны разделяться запятыми, т.е. ASSETS_CACHE=48h,text/html:24h,image/png:2h.

Пользовательскую страницу 404 (не найдено) можно задать с помощью параметра --assets.not-found=<путь>. Путь должен быть относительным относительно корня статических файлов.

Использование reproxy в качестве базового образа

Обслуживание исключительно статического контента — один из популярных вариантов использования. Обычно это применяется для отдельного контейнера с фронтендом, предоставляющего только пользовательский интерфейс. С сервером статических файлов такой контейнер становится почти тривиальным в создании. Ниже приведён пример из контейнера, обслуживающего reproxy.io.```docker FROM node:22-alpine as build

WORKDIR /build COPY site/ /build COPY README.md /build/src/index.md

RUN yarn --frozen-lockfile RUN yarn build RUN ls -la /build/public

FROM ghcr.io/umputun/reproxy COPY --from=build /build/public /srv/site EXPOSE 8080 USER app ENTRYPOINT ["/srv/reproxy", "--assets.location=/srv/site"]

root@kitploit:~
All it needs is to copy stastic assets to some location and passing this location as `"--assets.location` to reproxy entrypoint.

## SPA-friendly mode

Some SPA applications counts on proxy to handle 404 on static asset in a special way, by redirecting it to "/index.html". This is similar to nginx's `try_files $uri $uri/ …` directive and, apparently, this functionality somewhat important for the modern web apps.

This mode is off by default and can be turned on by setting `--assets.spa` or `ASSETS_SPA=true` env.

## Redirects 

By default reproxy treats destination as a proxy location, i.e. it invokes http call internally and returns response back to the client. However by prefixing destination url with `@code` this behaviour can be changed to a permanent (status code 301) or temporary (status code 302) redirects. I.e. destination set to `@301 https://example.com/something` will cause permanent http redirect to `Location: https://example.com/something`

supported codes:

- `@301`, `@perm` - permanent redirect
- `@302`, `@temp`, `@tmp` - temporary redirect

## More options

- `--gzip`   enables gzip compression for responses.
- `--max=N`  allows to set the maximum size of request (default 64k). Setting it to `0` disables the size check.
- `--timeout.*` various timeouts for both server and proxy transport. See `timeout` section in [All Application Options](#all-application-options). A zero or negative value means there will be no timeout.
- `--insecure` disables SSL verification on the destination host. This is useful for the self-signed certificates.

## Default ports

In order to eliminate the need to pass custom params/environment, the default `--listen` is dynamic and trying to be reasonable and helpful for the typical cases:

- If anything set by users to `--listen` all the logic below ignored and host:port passed in and used directly.
- If nothing set by users to `--listen` and reproxy runs outside the docker container, the default is `127.0.0.1:80` for http mode (`ssl.type=none`) and `127.0.0.1:443` for ssl mode (`ssl.type=auto` or `ssl.type=static`).
-  If nothing set by users to `--listen` and reproxy runs inside the docker, the default is `0.0.0.0:8080` for http mode, and `0.0.0.0:8443` for ssl mode.

Another default set in the similar dynamic way is `--ssl.http-port`. For run inside of the docker container it set to `8080` and without to `80`. 

## Ping, health checks and fail-over

reproxy provides two endpoints for this purpose:

- `/ping` responds with `pong` and indicates what reproxy up and running
- `/health` returns `200 OK` status if all destination servers responded to their ping request with `200` or `417 Expectation Failed` if any of servers responded with non-200 code. It also returns json body with details about passed/failed services.

In addition to the endpoints above, reproxy supports optional live health checks. In this case (if enabled), each destination checked for ping response periodically and excluded failed destination routes. It is possible to return multiple identical destinations from the same or various providers, and the only passed picked. If numerous matches were discovered and passed - the final one picked according to `lb-type` strategy (by default random selection).

To turn live health check on, user should set `--health-check.enabled` (or env `HEALTH_CHECK_ENABLED=true`). To customize checking interval `--health-check.interval=` can be used.

## Management API

Optional, can be turned on with `--mgmt.enabled`. Exposes 2 endpoints on `mgmt.listen` (address:port):

- `GET /routes` - list of all discovered routes
- `GET /metrics` - returns prometheus metrics (`http_requests_total`, `response_status` and `http_response_time_seconds`)

By default, `http_response_time_seconds` uses raw request paths as labels, which can cause high cardinality with dynamic URLs (e.g., `/api/users/123`, `/api/users/456`). Use `--mgmt.low-cardinality` to switch to route patterns (e.g., `^/api/users/(.*)`) instead, significantly reducing metrics cardinality.

_see also [examples/metrics](https://github.com/umputun/reproxy/tree/master/examples/metrics)_

## Errors reporting

Reproxy returns 502 (Bad Gateway) error in case if request doesn't match to any provided routes and assets. In case if some unexpected, internal error happened it returns 500. By default reproxy renders the simplest text version of the error - "Server error". Setting `--error.enabled` turns on the default html error message and with `--error.template` user may set any custom html template file for the error rendering. The template has two vars: `{{.ErrCode}}` and `{{.ErrMessage}}`. For example this template `oh my! {{.ErrCode}} - {{.ErrMessage}}` will be rendered to `oh my! 502 - Bad Gateway`

## Throttling 

Reproxy allows to define system level max req/sec value for the overall system activity as well as per user. 0 values (default) treated as unlimited.

User activity limited for both matched and unmatched routes. All unmatched routes considered as a "single destination group" and get a common limiter which is `rate*3`. It means if 10 (req/sec) defined with `--throttle.user=10` the end user will be able to perform up to 30 request pers second for either static assets or unmatched routes. For matched routes this limiter maintained per destination (route), i.e. request proxied to s1.example.com/api will allow 10 r/s and the request proxied to s2.example.com will allow another 10 r/s.

### Per-route timeout and throttle

Individual routes can override the global `--timeout.write` and `--throttle.user` settings via provider-specific `timeout` and `throttle` fields. This is useful for long-running endpoints (e.g. uploads, report generation) that need a deadline higher than the global write timeout, and for tightening rate limits on sensitive routes (e.g. login) without raising the global ceiling for everything else.

Precedence is "zero inherits global, positive overrides": a route with `timeout: 0` (or no `timeout` field) keeps the global `--timeout.write`; a route with `timeout: 5m` overrides it for matched requests only. The same rule applies to `throttle`.

The per-route timeout overrides the connection's read and write deadlines for matched requests, so it can extend past the global `--timeout.write` (default 30s). Routes without a per-route timeout still respect the global setting.

**Limitation — transport-level response-header timeout:** the per-route `timeout` does NOT override `--timeout.resp-header` (default 5s). That timeout is set on the shared `http.Transport` and applies before the upstream begins sending response headers. If an upstream takes longer than `--timeout.resp-header` to start its response (e.g. a slow report endpoint), the request fails at that boundary regardless of the per-route `timeout`. To support such routes, raise `--timeout.resp-header` globally to the maximum needed by any slow-response route. Per-route override of transport-level timeouts is intentionally out of scope.

Provider syntax:
- **File provider** (YAML): `timeout: 5m`, `throttle: 2`
- **Static provider** (CSV): 6th and 7th positional fields, e.g. `*,^/upload/(.*),http://up:8080/$1,,,5m,2`
- **Docker provider**: `reproxy.timeout=5m`, `reproxy.throttle=2` (or `reproxy.<n>.timeout` / `reproxy.<n>.throttle` for multi-route containers)
- **Consul Catalog provider**: `reproxy.timeout=5m`, `reproxy.throttle=2`

## Upstream connection limits

Reproxy allows configuring upstream connection pool settings to control how many connections are maintained to backend servers:

- `--upstream.max-idle-conns` - Maximum number of idle connections across all upstream hosts. Default: 100.
- `--upstream.max-conns` - Maximum number of connections per upstream host (0 = unlimited). Default: 0.

Setting `--upstream.max-conns` limits concurrent connections to each backend, which is useful when upstream servers have limited capacity or to prevent connection exhaustion.

## Basic auth

Reproxy supports basic auth in two modes: global (all routes) and per-route.

### Global basic auth

Global basic auth protects all routes. This is useful for protecting endpoints during development and testing. To enable, set the htpasswd file with `--basic-htpasswd=<file location>` or env `BASIC_HTPASSWD=<file location>`.

Reproxy expects htpasswd file to be in the following format:```
username1:bcrypt(password1)
username2:bcrypt(password2)
...

это можно сгенерировать с помощью команды htpasswd -nbB, т.е. htpasswd -nbB test passwd

Базовая аутентификация для отдельных маршрутов

Аутентификация для каждого маршрута позволяет использовать разные учетные данные для разных маршрутов. Если для маршрута настроена аутентификация на уровне маршрута, глобальная аутентификация для этого маршрута отключается. Аутентификация на уровне маршрута настраивается через специфичные для провайдера настройки:

  • File provider: поле auth в YAML, например, auth: "user1:$2y$..., user2:$2y$..."
  • Docker provider: метка reproxy.auth
  • Consul Catalog provider: тег reproxy.auth
  • Static provider: не поддерживается (используйте file provider для аутентификации на уровне маршрута)

Формат представляет собой список пар user:bcrypt_hash, разделенных запятыми (тот же формат htpasswd). Можно указать несколько пользователей для одного маршрута.

Пример с docker-compose:```yaml services: admin-api: labels: - "reproxy.route=^/admin/(.*)" - "reproxy.dest=/$1" - "reproxy.auth=admin:$$2y$$05$$hashedpassword"

root@kitploit:~
Note: In docker-compose, `$` must be escaped as `$$`.

## IP-based access control

Reproxy позволяет ограничивать доступ к маршрутам с помощью списка подсетей или IP-адресов, разделённых запятыми. Это полезно для разработки и тестирования, прежде чем разрешить неограниченный доступ к ним. Также это можно использовать для ограничения доступа к внутренним сервисам. По умолчанию все маршруты открыты для всех клиентов.

Чтобы ограничить доступ к маршрутам, пользователь должен установить соответствующие ключи для маршрутов, то есть `reproxy.remote` для docker и consul, и `remote` для файлового провайдера. Значение должно представлять собой список подсетей или IP-адресов, разделённых запятыми. Например: `127.0.0.1, 192.168.1.0/24`. Для получения дополнительной информации см. разделы [docker provider](#docker-provider) и [consul catalog provider](#consul-catalog-provider).

По умолчанию reproxy проверяет удалённый адрес из запроса клиента. Однако в некоторых случаях это не будет работать должным образом, например, за другим прокси или в сети docker bridge. Это можно изменить с помощью параметра `--remote-lookup-headers`, который позволяет проверять значение заголовка `X-Real-IP` или `X-Forwarded-For` (в этом порядке) и использовать его для проверки. Если заголовок не задан, проверка будет выполняться по удалённому адресу клиента. Эти заголовки предоставляются клиентом и легко подделываются, поэтому этот параметр должен быть включён только тогда, когда reproxy работает за доверенным внешним прокси, который всегда устанавливает и перезаписывает эти заголовки.

Проверка заголовков должна использоваться с осторожностью, так как их можно подделать. Когда `--remote-lookup-headers` включён, белый список IP-адресов полностью полагается на это доверие: клиент, отправляющий `X-Real-IP` или `X-Forwarded-For` с разрешённым адресом, может в противном случае обойти ограничение. Включайте эту опцию только в том случае, если reproxy находится за доверенным прокси, который контролирует эти заголовки, и вы можете гарантировать, что они не подделаны.

## Поддержка плагинов

Основную функциональность reproxy можно расширить с помощью внешних плагинов. Каждый плагин — это независимый процесс/контейнер, реализующий [rpc server](https://golang.org/pkg/net/rpc/). Плагины регистрируются с помощью conductor reproxy и добавляются в цепочку промежуточного программного обеспечения. Каждый плагин получает запрос с исходным URL, заголовками и всей информацией о соответствующем маршруте и отвечает заголовками и кодом состояния. Любой код состояния >= 400 рассматривается как ответ об ошибке и немедленно завершает поток с ошибкой прокси. Существует два типа заголовков, которые могут устанавливать плагины:

- `HeadersIn` — входящие заголовки. Они будут отправлены на проксируемый URL
- `HeadersOut` — исходящие заголовки. Будут отправлены обратно клиенту

По умолчанию заголовки, установленные плагином, смешиваются с исходными заголовками. Если плагину необходимо управлять всеми заголовками, например отбрасывать некоторые из них, плагин может установить поле `OverrideHeaders*`, указывая основному процессу reproxy на необходимость перезаписать все заголовки вместо их смешивания.

- `OverrideHeadersIn` — указывает, что плагин отвечает за все входящие заголовки.
- `OverrideHeadersOut` — указывает, что плагин отвечает за все исходящие заголовки

Чтобы упростить процесс разработки, предоставляются все строительные блоки. Они включают `lib.Plugin` для обработки регистрации, прослушивания и диспетчеризации вызовов, а также `lib.Request` и `lib.Response`, определяющие входные и выходные данные. Авторы плагинов должны реализовать конкретные обработчики, удовлетворяющие сигнатуре `func(req lib.Request, res *lib.HandlerResponse) (err error)`. Каждый плагин может содержать несколько таких обработчиков.

_См. [examples/plugin](https://github.com/umputun/reproxy/tree/master/examples/plugin) для получения дополнительной информации_

## Безопасность контейнера

По умолчанию контейнер reproxy работает от имени root, чтобы упростить первоначальную настройку и доступ к сокету docker. Это необходимо, чтобы позволить провайдеру docker обнаруживать запущенные контейнеры. Однако, если такое обнаружение не требуется или провайдер docker не используется, рекомендуется изменить пользователя на менее привилегированного. Это можно сделать на уровне docker-compose и на уровне docker с помощью опции `user`, см. раздел ниже для подробностей.

Иногда, даже при маршрутизации внутри docker, имеет смысл отключить провайдер docker и настроить правила с помощью статического или файлового провайдера. Все контейнеры, работающие в рамках одного compose, разделяют одну сеть и доступны через локальный DNS. Пользователь может иметь такое правило, чтобы избежать обнаружения docker: `- STATIC_RULES=*,/api/email/(.*),http://email-sender:8080/$$1`. Это правило предполагает, что контейнер `email-sender` определён в том же compose. Обратите внимание: пользователи могут достичь того же результата, используя сеть docker, даже если целевой сервис был определён в другом файле compose. Таким образом, конфигурация reproxy может оставаться отдельной от реальных сервисов.

Внутри контейнера reproxy нет ничего, кроме двоичного файла reproxy, так как он построен на основе пустого (scratch) образа.

### Запуск от непривилегированного пользователя

В контейнере предварительно создан пользователь с UID `1001` (принадлежащий группам `1001` и `999`), которого можно использовать для запуска reproxy от непривилегированного пользователя:```yaml
services:
  reproxy:
    user: 1001
    image: umputun/reproxy:latest
# <...>
# see examples/ssl/docker-compose.yml for the full file example

Если вы хотите использовать провайдер Docker, вам необходимо убедиться, что этот пользователь имеет разрешение на доступ к сокету Docker на хост-системе. То, как вы настроите эти разрешения, зависит от конфигурации вашей хост-системы. Для получения дополнительной информации о настройке разрешений сокета Docker см. документацию Docker по защите сокета демона Docker.

Options

Каждый параметр может быть указан в двух формах: командная строка или пара ключ:значение окружения. Некоторые опции командной строки имеют краткую форму, например -l localhost:8080, и все они имеют длинную форму, т.е. --listen=localhost:8080. Ключ (имя) переменной окружения перечислен для каждой опции в виде суффикса, например [$LISTEN].

Все опции размера поддерживают суффиксы единиц измерения, т.е. 10K (или 10k) для килобайт, 16M (или 16m) для мегабайт, 10G (или 10g) для гигабайт. Отсутствие суффикса (т.е. 1024) означает байты.

Некоторые опции повторяемы, в этом случае пользователь может передавать их несколько раз через командную строку или через запятую в переменной окружения. Например, --ssl.fqdn — такая опция, и её можно передать как --ssl.fqdn=a1.example.com --ssl.fqdn=a2.example.com или как переменную окружения SSL_ACME_FQDN=a1.example.com,a2.example.com

Вот список всех опций, поддерживающих несколько элементов:

  • ssl.fqdn (SSL_ACME_FQDN)
  • assets.cache (ASSETS_CACHE)
  • docker.exclude (DOCKER_EXCLUDE)
  • static.rule ($STATIC_RULES)
  • header ($HEADER)
  • drop-header ($DROP_HEADERS)

All Application Options```

-l, --listen= listen on host:port (default: 0.0.0.0:8080/8443 under docker, 127.0.0.1:80/443 without) [$LISTEN] -m, --max= max request size (default: 64K) [$MAX_SIZE] -g, --gzip enable gz compression [$GZIP] -x, --header= outgoing proxy headers to add [$HEADER] --drop-header= incoming headers to drop [$DROP_HEADERS] --basic-htpasswd= htpasswd file for basic auth [$BASIC_HTPASSWD]
--lb-type=[random|failover|roundrobin] load balancer type (default: random) [$LB_TYPE] --signature enable reproxy signature headers [$SIGNATURE] --remote-lookup-headers enable remote lookup headers, trust only behind a trusted proxy [$REMOTE_LOOKUP_HEADERS] --keep-host keep original Host header as default when proxying [$KEEP_HOST] --insecure skip SSL verification on destination host [$INSECURE] --dbg debug mode [$DEBUG]

ssl: --ssl.type=[none|static|auto] ssl (auto) support (default: none) [$SSL_TYPE] --ssl.cert= path to cert.pem file [$SSL_CERT] --ssl.key= path to key.pem file [$SSL_KEY] --ssl.acme-location= dir where certificates will be stored by autocert manager (default: ./var/acme) [$SSL_ACME_LOCATION] --ssl.acme-email= admin email for certificate notifications [$SSL_ACME_EMAIL] --ssl.http-port= http port for redirect to https and acme challenge test (default: 8080 under docker, 80 without) [$SSL_HTTP_PORT] --ssl.fqdn= FQDN(s) for ACME certificates [$SSL_ACME_FQDN]

assets: -a, --assets.location= assets location [$ASSETS_LOCATION] --assets.root= assets web root (default: /) [$ASSETS_ROOT] --assets.spa spa treatment for assets [$ASSETS_SPA] --assets.cache= cache duration for assets [$ASSETS_CACHE] --assets.not-found= path to file to serve on 404, relative to location [$ASSETS_NOT_FOUND]

logger: --logger.stdout enable stdout logging [$LOGGER_STDOUT] --logger.enabled enable access and error rotated logs [$LOGGER_ENABLED] --logger.file= location of access log (default: access.log) [$LOGGER_FILE] --logger.max-size= maximum size before it gets rotated (default: 100M) [$LOGGER_MAX_SIZE] --logger.max-backups= maximum number of old log files to retain (default: 10) [$LOGGER_MAX_BACKUPS]

docker: --docker.enabled enable docker provider [$DOCKER_ENABLED] --docker.host= docker host (default: unix:///var/run/docker.sock) [$DOCKER_HOST] --docker.network= docker network [$DOCKER_NETWORK] --docker.exclude= excluded containers [$DOCKER_EXCLUDE] --docker.auto enable automatic routing (without labels) [$DOCKER_AUTO] --docker.prefix= prefix for docker source routes [$DOCKER_PREFIX] --docker.api-version= docker API version (default: 1.24) [$DOCKER_API_VERSION]

consul-catalog: --consul-catalog.enabled enable consul catalog provider [$CONSUL_CATALOG_ENABLED] --consul-catalog.address= consul address (default: http://127.0.0.1:8500) [$CONSUL_CATALOG_ADDRESS] --consul-catalog.interval= consul catalog check interval (default: 1s) [$CONSUL_CATALOG_INTERVAL]

file: --file.enabled enable file provider [$FILE_ENABLED] --file.name= file name (default: reproxy.yml) [$FILE_NAME] --file.interval= file check interval (default: 3s) [$FILE_INTERVAL] --file.delay= reload only after the file has been unchanged for this long (default: 500ms) [$FILE_DELAY]

static: --static.enabled enable static provider [$STATIC_ENABLED] --static.rule= routing rules [$STATIC_RULES]

timeout: --timeout.read-header= read header server timeout (default: 5s) [$TIMEOUT_READ_HEADER] --timeout.write= write server timeout (default: 30s) [$TIMEOUT_WRITE] --timeout.idle= idle server timeout (default: 30s) [$TIMEOUT_IDLE] --timeout.dial= dial transport timeout (default: 30s) [$TIMEOUT_DIAL] --timeout.keep-alive= keep-alive transport timeout (default: 30s) [$TIMEOUT_KEEP_ALIVE] --timeout.resp-header= response header transport timeout (default: 5s) [$TIMEOUT_RESP_HEADER] --timeout.idle-conn= idle connection transport timeout (default: 90s) [$TIMEOUT_IDLE_CONN] --timeout.tls= TLS hanshake transport timeout (default: 10s) [$TIMEOUT_TLS] --timeout.continue= expect continue transport timeout (default: 1s) [$TIMEOUT_CONTINUE]

mgmt: --mgmt.enabled enable management API [$MGMT_ENABLED] --mgmt.listen= listen on host:port (default: 0.0.0.0:8081) [$MGMT_LISTEN] --mgmt.low-cardinality use route patterns instead of raw paths for metrics labels [$MGMT_LOW_CARDINALITY]

error: --error.enabled enable html errors reporting [$ERROR_ENABLED] --error.template= error message template file [$ERROR_TEMPLATE]

health-check: --health-check.enabled enable automatic health-check [$HEALTH_CHECK_ENABLED] --health-check.interval= automatic health-check interval (default: 300s) [$HEALTH_CHECK_INTERVAL]

throttle: --throttle.system= throttle overall activity' (default: 0) [$THROTTLE_SYSTEM] --throttle.user= limit req/sec per user and per proxy destination (default: 0) [$THROTTLE_USER]

upstream: --upstream.max-idle-conns= max idle connections total (default: 100) [$UPSTREAM_MAX_IDLE_CONNS] --upstream.max-conns= max connections per upstream host (0=unlimited) (default: 0) [$UPSTREAM_MAX_CONNS]

plugin: --plugin.enabled enable plugin support [$PLUGIN_ENABLED] --plugin.listen= registration listen on host:port (default: 127.0.0.1:8081) [$PLUGIN_LISTEN]

Help Options: -h, --help Show this help message

root@kitploit:~
## Статус

Проект находится в активной разработке и могут быть критические изменения до выхода версии `v1`. Однако мы стараемся не нарушать обратную совместимость без веской причины. Начиная с версии 0.4.x, reproxy считается достаточно стабильным для реального использования, и многие конфигурации работают с ним в продакшене.
Скачать инструмент
  • example.com,^/login,https://api.example.com/login,,,,2 — ограничение для маршрута 2 запроса/сек на пользователя (позиционные поля перед этим оставлены пустыми).
  • reproxy.keep-host — оставить заголовок Host как есть (yes, true, 1) или заменить на хост назначения (no, false, 0)
  • reproxy.forward-health-checks — перенаправлять запросы /ping и /health на бэкенд вместо обработки reproxy (yes, true, 1). Полезно, когда бэкенд имеет собственные конечные точки проверки состояния с ответами, специфичными для приложения.
  • reproxy.timeout — таймаут запроса на маршрут в виде длительности Go (например, 5m, 30s). 0 или неустановленное значение наследует глобальное --timeout.write. Некорректные значения игнорируются с предупреждением.
  • reproxy.throttle — лимит запросов в секунду на пользователя для маршрута. 0 или неустановленное значение наследует --throttle.user. Некорректные или отрицательные значения игнорируются с предупреждением.
  • reproxy.enabled — включить (yes, true, 1) или отключить (no, false, 0) контейнер в списке назначений reproxy.
  • yes
    true