← Сеть: продвинутое
12 мин · средне · Урок 3 из 4

Reverse proxy (nginx, Caddy)

Зачем перед приложением ставят прокси: TLS-терминация, роутинг по доменам, заголовки и зачем нужен X-Forwarded-For.

Что стоит перед приложением

Приложение слушает какой-нибудь 127.0.0.1:8080 и умеет отдавать HTTP. Напрямую выставлять его в интернет плохо: оно не умеет TLS, не разруливает несколько доменов, не отдаёт статику эффективно. Перед ним ставят reverse proxy: nginx или Caddy. Снаружи на 443 порту стоит прокси, а он уже передаёт запросы внутреннему приложению.

«Reverse» в названии потому, что прокси работает на стороне сервера и представляет приложение клиентам. Обычный (forward) прокси, наоборот, представляет клиента серверам.

TLS-терминация

Самая частая работа прокси — терминировать TLS. Клиент устанавливает HTTPS-соединение с прокси, прокси расшифровывает запрос и передаёт его приложению уже по обычному HTTP внутри доверенной сети.

Клиент --HTTPS--> [nginx :443] --HTTP--> [app :8080]

Приложению не нужно знать про сертификаты и шифрование. Этим занимается прокси. Сертификат от Let's Encrypt подключается в одном месте, а не в каждом сервисе.

Роутинг по доменам и путям

Один прокси обслуживает несколько сайтов на одном IP. Он смотрит на заголовок Host (и на SNI в TLS) и решает, куда направить:

server {
    server_name api.example.com;
    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

server {
    server_name shop.example.com;
    location / {
        proxy_pass http://127.0.0.1:9090;
    }
}

api.example.com уйдёт на порт 8080, shop.example.com — на 9090. Роутить можно и по пути: /api/ на одно приложение, / на другое.

Caddy делает то же самое короче и сам получает сертификаты:

api.example.com {
    reverse_proxy 127.0.0.1:8080
}

Заголовки: кто на самом деле клиент

После проксирования приложение видит соединение от прокси, а не от реального клиента. Если ничего не настроить, в логах приложения у всех будет IP прокси (127.0.0.1), а схема будет http, хотя клиент пришёл по https. Прокси добавляет служебные заголовки, чтобы передать правду:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

Приложение должно этим заголовкам доверять только от своего прокси, иначе их можно подделать снаружи.

Что важно запомнить

Reverse proxy стоит перед приложением: терминирует TLS, роутит по доменам/путям и отдаёт статику. Сертификат подключается в одном месте.

Прокси проксирует по HTTP внутрь, поэтому передаёт реальный контекст клиента через X-Forwarded-For (IP) и X-Forwarded-Proto (схему). Приложение доверяет этим заголовкам только от своего прокси.

nginx настраивается через server/proxy_pass. Caddy короче и сам берёт сертификаты.

В следующем уроке разберём балансировку нагрузки, когда за прокси стоит не один сервис, а несколько одинаковых.

Прошли материал до конца? Отметьте урок пройденным.