Отримуємо IP-адреси HTTPS-клієнтів з HAProxy (frontend) на Nginx (backend) в режимах HTTP і TCP-балансування

Досить часто потрібно балансувати навантаження між декількома веб-серверами. При цьому, як правило, необхідно, щоб веб-додатки отримували реальні IP-адреси клієнтів, а не IP балансувальника.

У разі балансування та термінації HTTP(S)-трафіку на HAProxy (Layer 7 [1]) ця задача легко вирішується додаванням заголовка «X-Real-IP» і його обробкою на Nginx за допомогою модуля ngx_http_realip_module [2]. При балансуванні TCP трафіку від HTTPS-клієнтів і передачі його на веб-сервера напряму без модифікації або термінації (Layer 4 [3]) додати даний заголовок неможливо, тому потрібно скористатися можливостями, наданими Proxy Protocol [4, 5, 6].

Розглянемо обидва варіанти (балансування L7 і L4) на прикладі витягів з конфігураційних файлів haproxy 1.5.9 і nginx 1.6.2

Балансування на прикладному рівні (Layer 7): термінація HTTPS-трафіку на HAProxy і передача по HTTPS на Nginx
В даному прикладі HTTPS трафік від клієнта терминируется на HAProxy, модифікується і передається на Nginx так само по HTTPS.

haproxy.cfg

global
maxconn 4096
chroot /usr/share/haproxy
uid 99
gid 99
daemon
tune.ssl.default-dh-param 2048

defaults
log global
option redispatch
option tcp-smart-accept
option tcp-smart-connect
retries 3
maxconn 2000
timeout connect 5000
timeout check 3000
timeout client 50000
timeout server 50000

frontend http_frontend *:80
http mode
redirect scheme https code 301 if !{ ssl_fc }

frontend https_frontend_ssl_terminate
http mode
bind *:443 ssl crt /etc/haproxy/ssl/public.example.com.pem
option forwardfor header X-Real-IP
default_backend web_server_http

backend web_server_http
http mode
balance roundrobin
# Відправляємо трафік на backend по HTTPS
server s1_https 192.168.1.10:443 ssl verify none
server s2_https 192.168.1.20:443 ssl verify none


nginx.conf

server {
server_name localhost;

listen 443 ssl default_server;

ssl_certificate /etc/nginx/ssl/internal.example.com.pem;
ssl_certificate_key /etc/nginx/ssl/internal.example.com.key;

# Адреса HAProxy
set_real_ip_from 192.168.1.254;
real_ip_header X-Real-IP;

root /usr/share/nginx/html;
index index.html index.htm;

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

location ~ /\.ht {
deny all;
}
}


Балансування на транспортному рівні (Layer 4): передача TCP трафіку з HAProxy на Nginx
В даному прикладі HTTPS трафік клієнтів не модифікується (HAProxy втручається в транспортний рівень) і його термінація відбувається безпосередньо на Nginx.

haproxy.cfg

global
maxconn 4096
chroot /usr/share/haproxy
uid 99
gid 99
daemon

defaults
log global
option redispatch
option tcp-smart-accept
option tcp-smart-connect
retries 3
maxconn 2000
timeout connect 5000
timeout check 3000
timeout client 50000
timeout server 50000

frontend http_frontend *:80
http mode
redirect scheme https code 301 if !{ ssl_fc }

frontend https_frontend_ssl_pass
mode tcp
bind *:443
default_backend web_server_tcp

backend web_server_tcp
mode tcp
balance roundrobin
# УВАГА! Робота з send-proxy можлива лише,
# коли приймаюча сторона розуміє, що це таке.
# Для Nginx необхідно включити в директиву listen
# опцію proxy_protocol.
server s1_tcp 192.168.1.10:443 send-proxy
server s2_tcp 192.168.1.20:443 send-proxy


nginx.conf

server {
server_name localhost;

# УВАГА! Робота з директивою proxy_protocol можлива тільки у зв'язці з haproxy.
# Для прямого доступу дану директиву необхідно відключити.
listen 443 ssl default_server proxy_protocol;

ssl_certificate /etc/nginx/ssl/public.example.com.pem;
ssl_certificate_key /etc/nginx/ssl/public.example.com.key;

# Адреса HAProxy
set_real_ip_from 192.168.1.254;
real_ip_header proxy_protocol;

root /usr/share/nginx/html;
index index.html index.htm;

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

location ~ /\.ht {
deny all;
}
}


Висновок
Використовуючи описані вище налаштування ми змогли передати веб-сервера Nginx, розташованому за HAProxy, реальні IP-адреси клієнтів при роботі по HTTPS. Подібним підходом так само можна скористатися при роботі зі сторонніми балансировщиками навантаження, наприклад CloudFlare [7, 8] і AWS ELB [9, 10].

Література
  1. Протоколи прикладного рівня мережевої моделі OSI — ru.wikipedia.org
  2. Модуль ngx_http_realip_module — nginx.org
  3. Транспортний рівень мережевої моделі OSI — ru.wikipedia.org
  4. The PROXY protocol — haproxy.org
  5. HAProxy Configuration Manual: send-proxy — cbonte.github.io
  6. Модуль ngx_http_core_module: директива listen — nginx.org
  7. Getting Real IP Addresses Using CloudFlare, Nginx, and Varnish — danielmiessler.com
  8. Getting Real IP Addresses Using Nginx and CloudFlare — babaei.net
  9. Using Proxy Protocol With Nginx — chrislea.com
  10. AWS Elastic Load Balancing — aws.amazon.com


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.