how to create a reverse proxy

Огляд

Дізнайтеся, як налаштувати зворотний проксі за допомогою HAProxy на VPS, щоб приховати справжню IP-адресу сервера, підвищити продуктивність і захистити свої програми від третіх осіб. Як створити зворотний проксі за допомогою HAProxy, щоб приховати справжню IP-адресу сервера походження?


Що таке зворотний проксі?

Зворотний проксі розташовується між клієнтами і вашими серверами. Він отримує вхідні запити, вирішує, куди їх надсилати, і повертає відповіді – при цьому зберігаючи ваші сервери походження прихованими від публічного інтернету. Він також може розподіляти навантаженняміж кількома внутрішніми серверами, додавати заголовки безпеки, обмежувати швидкість зловмисних клієнтів і централізовано завершувати TLS (HTTPS). Подумайте про нього як про розумного вишибалу: він спрямовує людей до потрібних кімнат, але залишає закулісся приватним.

Коротше кажучи, зворотний проксі – це тиха робоча конячка, яка забезпечує безперебійну роботу, а ваше походження залишається приватним.


Зворотний проксі з HAProxy: Як це працює

HAProxy – це потужний L4/L7 проксі і балансувальник навантаження. Клієнтські запити спочатку потрапляють на HAProxy, де

  • TLS (HTTPS) може бути перервано.
  • Додаються заголовки X-Forwarded-For, X-Forwarded-Proto і X-Forwarded-Host.
  • Трафік спрямовується на бекенд за іменем хоста, шляхом або користувацькими правилами.
  • Доступні перевірки стану, автоматичне обхід відмов, обмеження швидкості, стиснення, легке кешування, WebSockets і пропуск gRPC.
  • Детальні журнали та сторінка статистики в реальному часі забезпечують спостережливість.

Підсумок: HAProxy спрощує вашу архітектуру, підвищує безпеку і продуктивність, а також спрощує масштабування


Переваги та недоліки HAProxy

Плюси (чому HAProxy блищить)

  • Висока продуктивність і низькі накладні витрати (керований подіями, багатопотоковий).
  • Інтелектуальні функціїL4 + L7 (пропуск TCP/SNI або повна маршрутизація/перезапис HTTP).
  • Надійне балансування навантаження та перевірка працездатності (round-robin, leastconn, хешування; активні перевірки, обхід відмови).
  • Функції безпеки (завершення TLS, HSTS, ACL, обмеження швидкості за допомогою stick-таблиць, дозвіл/заборона IP).
  • Спостережуваність (багаті логи, сокет/сторінка статистики в реальному часі; доступні експортери Prometheus).
  • Надійність (плавне перезавантаження з майже нульовим часом простою; перевірено в боях).
  • Малий розмір (працює практично будь-де: Linux/BSD/контейнери).

Мінуси (компроміси)

  • Крива навчання (потужна, але багатослівна конфігурація).
  • Автоматизація сертифікації не вбудована (потрібна пара з Certbot/lego або Data Plane API).
  • За замовчуванням ручне виявлення сервісів (динамічні бекенди потребують шаблонів/API).
  • Обмеженевбудоване кешування/статичне обслуговування (використовуйте CDN/Varnish/Nginx, якщо потрібно).
  • Немає власного WAF (використовуйте окремий WAF або HAProxy Enterprise).
  • Складні перезаписи можуть бути багатослівними.
  • Обмежена підтримка Windows (найкраще на Linux/BSD).

Що вам знадобиться

  • VPS/публічний сервер для HAProxy (зворотний проксі).
  • Ваш вихідний сервер (наприклад, 10.0.0.10:8080).
  • Домен (наприклад, example.com) з DNS A/AAAA, що вказує на публічну IP-адресу HAProxy-сервера.

Порада щодо конфіденційності: Щоб дійсно приховати IP-адресу походження, переконайтеся, що вона не є загальнодоступною, налаштуйте брандмауер на прийом трафіку тільки з сервера HAProxy і уникайте DNS-записів, які розкривають походження.


Крок 1 – Встановлення HAProxy

Ubuntu/Debian

sudo apt update
sudo apt install -y haproxy

RHEL/Alma/Rocky

sudo dnf install -y haproxy

Крок 2 – Отримання TLS-сертифікату (давайте зашифруємо)

Ми дозволимо Certbot отримати сертифікат і використаємо його для HAProxy

Встановіть certbot і отримайте сертифікат (одноразово)

# Ubuntu/Debian
sudo apt install -y certbot
sudo certbot certonly --standalone -d example.com --agree-tos -m you@example.com --non-interactive

Створіть PEM-бандл HAProxy (повний ланцюжок + приватний ключ)

sudo mkdir -p /etc/haproxy/certs
sudo bash -c 'cat /etc/letsencrypt/live/example.com/fullchain.pem 
              /etc/letsencrypt/live/example.com/privkey.pem 
              > /etc/haproxy/certs/example.com.pem'
sudo chmod 600 /etc/haproxy/certs/example.com.pem

Автоматичне об’єднання та перезавантаження HAProxy при поновленні

sudo bash -c 'cat >/etc/letsencrypt/renewal-hooks/deploy/haproxy.sh' <<'EOF'
#!/usr/bin/env bash
cat /etc/letsencrypt/live/example.com/fullchain.pem 
    /etc/letsencrypt/live/example.com/privkey.pem 
    > /etc/haproxy/certs/example.com.pem
systemctl reload haproxy
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/haproxy.sh

Крок 3 – Мінімальна, готова до роботи конфігурація HAProxy (HTTPS + редирект)

Замініть example.com і ваш внутрішній IP/порт, де зазначено.

# /etc/haproxy/haproxy.cfg
global
  log /dev/log local0
  maxconn 50000
  daemon

defaults
  log global
  mode http
  option httplog
  timeout connect 5s
  timeout client  60s
  timeout server  60s
  http-reuse safe

# Frontend: listen on 80/443, redirect to HTTPS, route ACME and app traffic
frontend fe_https
  bind :80
  bind :443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1

  # Force HTTPS
  http-request redirect scheme https unless { ssl_fc }

  # Basic security header
  http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" if { ssl_fc }

  # Preserve client info for your app
  option forwardfor header X-Forwarded-For
  http-request set-header X-Forwarded-Proto https if { ssl_fc }
  http-request set-header X-Forwarded-Host %[req.hdr(host)]

  # Simple rate cap: 100 requests / 10s per IP
  stick-table type ip size 100k expire 10m store http_req_rate(10s)
  http-request track-sc0 src
  acl too_fast sc0_http_req_rate gt 100
  http-request deny status 429 if too_fast

  # Route ACME HTTP-01 challenges to local certbot (used during renewals)
  acl acme path_beg /.well-known/acme-challenge/
  use_backend be_acme if acme

  # Route your domain to the origin backend
  acl host_example hdr(host) -i example.com
  use_backend be_app if host_example
  default_backend be_app

# Backend: your origin server
backend be_app
  balance leastconn
  option httpchk GET /health
  http-check expect status 200
  server app1 10.0.0.10:8080 check

# Backend to serve ACME challenges (certbot standalone hook)
backend be_acme
  server local 127.0.0.1:8081

Чому це працює

  • HAProxy завершує TLS на :443 і перенаправляє :80 → HTTPS.
  • Звичайний трафік повертається до місця відправлення за адресою 10.0.0.10:8080.
  • Тільки /.well-known/acme-challenge/* направляється на крихітний локальний веб-сервер, який Certbot буде запускати під час поновлення.

Крок 4 – Запуск, перезавантаження та перевірка

# Validate config
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

# Enable and start
sudo systemctl enable --now haproxy

# Reload after edits/renewals
sudo systemctl reload haproxy

Крок 5 – Поновлення без участі користувача

Дозвольте Certbot ненадовго прив’язатися до :8081, поки HAProxy тримає :80/:443 відкритим:

# Typically handled by systemd timer; safe to run manually for testing
sudo certbot renew --deploy-hook "/etc/letsencrypt/renewal-hooks/deploy/haproxy.sh" 
  --http-01-port 8081 --pre-hook "systemctl start haproxy" --post-hook "systemctl start haproxy"

Під час оновлення Certbot відповідає на виклик на порту 8081; HAProxy вже прокладає цей шлях до ###ATP_NOTR_26_CODE_TAG_NOTR_ATP##.


Варіації (виберіть те, що вам потрібно)

A) Кілька джерел за іменем хоста

# Add in frontend:
acl host_api hdr(host) -i api.example.com
use_backend be_api if host_api

# Define an API backend:
backend be_api
  balance roundrobin
  option httpchk GET /healthz
  server api1 10.0.0.21:9000 check
  server api2 10.0.0.22:9000 check

B) TLS passthrough (походження обробляє TLS/mTLS)

Використовуйте режим TCP з маршрутизацією SNI. Тут немає перезапису заголовків або функцій L7.

frontend fe_tcp
  mode tcp
  bind :443
  tcp-request inspect-delay 5s
  tcp-request content accept if { req_ssl_hello_type 1 }
  use_backend be_tls_app if { req_ssl_sni -i example.com }

backend be_tls_app
  mode tcp
  server app_tls 10.0.0.10:443 check

C) Мінімальний зворотний проксі тільки для HTTP (без TLS)

Тільки для внутрішніх/тестування – використовуйте HTTPS для виробництва.

global
  log /dev/log local0

defaults
  mode http
  log global
  option httplog
  timeout connect 5s
  timeout client  60s
  timeout server  60s

frontend public_http
  bind :80
  option forwardfor
  default_backend app

backend app
  server app1 10.0.0.10:8080 check

Швидкі перевірки та усунення несправностей

# DNS should point to HAProxy
dig +short example.com

# HTTP should redirect to HTTPS (301)
curl -I http://example.com

# HTTPS should serve content
curl -I https://example.com

# See headers the app receives (in your app logs):
# X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host

Поради щодо брандмауера

  • Заблокуйте джерело, щоб воно приймало трафік лише від HAProxy-сервера (наприклад, за допомогою ufw, firewalld або хмарних груп безпеки).
  • За бажанням заблокуйте прямий публічний доступ до вихідної IP-адреси на рівні вашого провайдера.

Заключні зауваження

  • Встановіть таймаути, що відповідають вашому робочому навантаженню (для WebSockets/gRPC можуть знадобитися більші таймаути ).
  • Розкрийте кінцеву точку /health у вашому додатку для httpchk.
  • Сплануйте розгортання з нульовим часом простою: вимкніть сервер (disabled) під час розгортання, а потім увімкніть його знову.

Важливе зауваженняЯкщо ви не впевнені, як правильно налаштувати сервер, ми наполегливо рекомендуємо звернутися до професіонала для завершення конфігурації. Важливо переконатися, що всі налаштування виконані точно, включаючи перевірку портів брандмауера, щоб переконатися у відсутності блокування портів. Важливо мати хоча б базове розуміння брандмауерів і команд Linux, щоб ефективно керувати процесом конфігурації. Зверніть увагу, що ми не несемо відповідальності за будь-які збитки або проблеми, які можуть виникнути в процесі конфігурації. Вся інформація, надана тут, призначена лише для отримання технічних знань і навчання. Дякуємо за розуміння