Reverse Proxy concept page covering nginx/HAProxy/Caddy/Envoy/Traefik. Functions: TLS termination, caching, compression, routing, header injection, rate limiting, auth offload, WAF. Reverse vs forward proxy. CDN edge as reverse proxy. Sidecar proxy (Envoy) for service mesh. ADR comparing Reverse Proxy vs API Gateway vs Service Mesh. 5 scenarios.
Reverse proxy — самый дешёвый архитектурный рычаг во всей backend-инфраструктуре. За цену одного nginx-контейнера ты получаешь TLS termination, edge-кеш, gzip/brotli, request rewriting, базовый WAF, rate limiting, скрытие топологии бэкенда, единые access-логи и canary routing. Это вещи, которые дороже реализовать в каждом сервисе отдельно, и глупее отдавать каждому сервису делать их самостоятельно.
Где знание окупается в первый же спринт:
proxy_cache, Varnish, CDN) гасит большую часть GET-ов. Origin держит в 5-10 раз меньше нагрузки.nginx -s reload. Откат — за 5 секунд.Главный takeaway: всё, что можно вынести «до приложения» — TLS, gzip, кеш, rate limit, auth offload, header injection, routing — выноси сюда. Бэкенд должен заниматься бизнес-логикой, а не повторно решать сетевые задачи в каждом сервисе.
Reverse proxy = единый front door перед группой бэкендов. Клиент видит только его, бэкенды клиента не видят. Прокси отвечает «от имени» апстрима. Forward proxy наоборот — работает «от имени клиента» в сторону интернета.
Три категории, которые путают, потому что они работают на одном базисе (L7 прокси, чаще всего nginx/Envoy/HAProxy):
| Reverse proxy | Load balancer | API Gateway | |
|---|---|---|---|
| Минимум | TLS, кеш, gzip, простой routing | + алгоритмы балансировки, health checks, sticky | + auth, per-consumer quotas, schema validation, billing |
| Control plane | static config file | config + health probes | knows consumers и API products |
| Когда брать | edge перед монолитом / группой сервисов | distribution по пулу | API как продукт (partners, monetization) |
| Примеры | nginx, Caddy | HAProxy, AWS NLB/ALB | Kong, Apigee, AWS API Gateway |
В реальности один продукт (nginx-plus, HAProxy 2.x, Envoy + xDS) играет все три роли. На собеседовании говори в терминах ролей, не вендоров: «reverse proxy для TLS, load balancer для распределения, gateway для аутентификации».
Отдельная история — service mesh (Istio, Linkerd, Consul Connect): тот же L7-прокси (обычно Envoy), но в виде sidecar на каждом pod. Перехватывает inbound + outbound, делает mTLS прозрачно, retry/circuit-breaker/timeout декларативно через CRD. Это «reverse proxy на каждом сервисе» как pattern. Подходит для большого количества internal микросервисов с zero-trust сетью. Не ставь service mesh ради «потому что modern» — sidecar добавляет 100-300MB RAM на pod и +1-2ms на каждый hop. Для 10 сервисов это overkill.
Канвас собран как реалистичный edge с тремя физическими зонами:
nginx reverse proxy + proxy_cache. На ноде прокси висит ADR-001 «Reverse Proxy vs API Gateway vs Service Mesh». Это единственная точка, в которую упирается интернет.app-v1 (95% трафика), app-v2 (5% canary), static (origin для статики).svc-a + envoy-a сайдкар, svc-b + envoy-b. Между sidecar'ами едет mTLS, между сервисом и его sidecar'ом — plain HTTP по loopback.Edges подписаны протоколом и ролью: HTTPS от клиентов, HTTP внутри VPC (cert остался на edge), mTLS между sidecar'ами, loopback HTTP от сервиса к своему sidecar. Это главное визуальное доказательство принципа «TLS терминируется на границе, внутри периметра — plain» и «service mesh даёт mTLS бесплатно без участия бизнес-кода».
Классический nginx-кейс. Клиент тянет /static/logo.png — прокси находит в proxy_cache HIT и отдаёт за 1ms, бэкенд вообще не задействован. Следом /api/users/42 — динамика, кеш MISS, идём в app-v1 через proxy_pass. Прокси инжектит X-Forwarded-For и X-Request-ID (для distributed tracing), бэкенд отвечает JSON-ом, прокси сжимает gzip-ом перед отправкой. Один и тот же прокси разруливает три ортогональные задачи: статика, кеш, прокси с трансформацией.
TLS handshake терминируется на edge — у прокси единственный сертификат на домен. Внутри VPC трафик идёт plain HTTP, бэкенды освобождены от криптографии. Прокси на лету видит plaintext payload и через WAF rules матчит OWASP-паттерны: q=1' OR 1=1-- ловится правилом SQLi и возвращает 403, бэкенд никогда этот запрос не видел. Дальше attacker устраивает flood — 1000 req/s от одного IP — прокси через token bucket режет на 100 req/s лимите и шлёт 429. Это главный value reverse proxy в безопасности: фильтр перед приложением, который видит payload (в отличие от L4-firewall'а, для которого TLS-трафик — opaque bytes).
Service mesh в действии. svc-a пишет в коде GET http://service-b/api как обычный plain HTTP к localhost. Реально запрос ловит envoy-a (его sidecar через loopback). Envoy презентует client-cert от mesh CA, открывает mTLS-канал к envoy-b. На приёме envoy-b расшифровывает и форвардит plain HTTP к svc-b. Сервис никогда не знал, что был mTLS. Дальше сценарий показывает retry: svc-b отдаёт 503 (transient overload), envoy-b по retry policy делает вторую попытку — успех, svc-a получает 200 как будто никакого фейла не было. Timeout, retry, circuit breaker, outlier detection — декларативно в mesh config, push через xDS, ни строчки в бизнес-коде. Это то, чего никогда не получишь от reverse-proxy на edge — здесь sidecar даёт policy на каждом hop'е.
5% трафика на v2 канарейку по hash от user-id. Прокси читает cookie, считает hash, попадание в 5% bucket — route на app-v2. Для клиента это прозрачно. Параллельно прокси переписывает path: /api/v1/orders → /internal/orders, инжектит трейсинг-хедеры. Дальше — драма: метрика error rate v2 прыгает с 0.1% до 8%, alert. Откат — правкой одной строки в nginx config и nginx -s reload: 5% → 0%. Никакого deploy, никакого rollback, zero downtime. Это то, ради чего держат edge proxy — traffic shifting без участия kubectl и CI.
CDN — это distributed reverse proxy на сотнях edge locations. EU-юзер по anycast DNS попадает на ближайший PoP, тянет /assets/app.js — кеш-HIT, 5ms RTT, origin даже не знает о запросе. Дальше non-cacheable /api/personalized — кеш MISS, прокси форвардит через private backbone к origin VPC. Параллельно attacker устраивает 1M RPS L7 DDoS — атака distributed across 200+ edge locations, ни один PoP не насыщен, бот-challenge и mitigation rules глушат за миллисекунды. Origin никогда атаку не видел. CDN = reverse proxy + global anycast + cache + WAF + DDoS scrubbing в одном продукте.
На ноде nginx (reverse proxy) висит ADR-001 «Reverse Proxy vs API Gateway vs Service Mesh».
Контекст. Все три категории работают на одной основе (L7 прокси), решают пересекающиеся задачи (routing, TLS, observability, retry/timeout, rate limit), но scope и control plane разные. Команды путают роли и либо ставят три отдельных продукта (overhead, три места править конфиг), либо пытаются впихнуть всё в один (например, делают service mesh из nginx — теряют автоматический mTLS и distributed xDS-control).
Решение. Маппинг по роли:
Правило: edge → reverse proxy. External API as product → API gateway. Большой internal mesh → service mesh. Можно комбинировать: Envoy на edge + Istio mesh внутри VPC.
Что получаем. Минимум дублирования логики, ясная зона ответственности у каждого слоя. Команды сети, security, и application разводят зоны, не наступая друг другу на ноги.
Что платим. Когнитивный overhead — нужно держать в голове три категории. Иногда искушение «давайте всё засунем в API Gateway» — через год получаем 200-строчные Lua-скрипты в Kong, которые никто не понимает.
Альтернативы.
| Подход | Плюсы | Минусы |
|---|---|---|
| Только edge nginx | Просто, дёшево | Нет per-user квот, нет mTLS между сервисами |
| Только API Gateway | Богатые фичи | Overkill для internal, тяжёлый control plane |
| Только Service Mesh | mTLS, observability бесплатно | +100-300MB RAM на pod, overkill для < 20 сервисов |
| Правильная роль на правильном слое | Покрывает все кейсы | День на изучение границ |
req.connection.remoteAddress напрямую → видит IP прокси, не клиента. Rate-limit и аналитика по IP сломаны. Читай из X-Forwarded-For с проверкой trust chain.X-Forwarded-For от клиента → клиент сам шлёт X-Forwarded-For: 1.2.3.4 и спуфит IP. Прокси обязан перезаписывать, не append'ить от клиента.keepalive 64 (nginx) или option http-server-close (HAProxy).server_name _; без явного списка хостов → прокси отдаёт любые Host'ы на бэкенд. Open relay для CDN-bypass и SSRF атак. Дефолтный server должен возвращать 444/421.X-Forwarded-Proto не проставлен → бэкенд видит http, делает редирект на http://..., ломает HTTPS.client_body_timeout / client_header_timeout падает под медленным клиентом с 100k idle коннектов.Reverse proxy — практически always-on в production. Но есть кейсы, где он реально лишний:
npm run dev не нуждается в TLS termination и edge cache.Для всего остального публичного — ставь reverse proxy с первого дня. Дешевле добавить сразу, чем потом ретроактивно вставлять между клиентом и приложением.
Концепты:
X-Forwarded-*, Forwarded RFC 7239).Кейсы:
Книги:
Production docs:
ngx_http_proxy_module — ключевые настройки.RFC:
Forwarded HTTP extension, стандартизация X-Forwarded-*.Инструменты:
nginx -T — дамп всего эффективного config.nginx -s reload — graceful reload без обрыва коннектов.haproxy -c -f /etc/haproxy/haproxy.cfg — валидация конфига до перезапуска.tcpdump -i any port 443 -w trace.pcap — что реально видит прокси на L4.curl -v --resolve api.example.com:443:10.0.0.5 — обойти DNS, бить напрямую в IP прокси для debug.