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;
X-Forwarded-For— настоящий IP клиента (для логов, rate-limit, бана).X-Forwarded-Proto— по какой схеме пришёл клиент (https), чтобы приложение не делало бесконечный редирект на HTTPS.Host— какой домен запрашивали.
Приложение должно этим заголовкам доверять только от своего прокси, иначе их можно подделать снаружи.
Что важно запомнить
Reverse proxy стоит перед приложением: терминирует TLS, роутит по доменам/путям и отдаёт статику. Сертификат подключается в одном месте.
Прокси проксирует по HTTP внутрь, поэтому передаёт реальный контекст
клиента через X-Forwarded-For (IP) и X-Forwarded-Proto (схему).
Приложение доверяет этим заголовкам только от своего прокси.
nginx настраивается через server/proxy_pass. Caddy короче и сам берёт
сертификаты.
В следующем уроке разберём балансировку нагрузки, когда за прокси стоит не один сервис, а несколько одинаковых.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс