Як я можу використовувати HAproxy з SSL та отримати заголовки X-Forwarded-For І сказати PHP, що використовується SSL?


20

У мене є така настройка:

(internet) ---> [  pfSense Box  ]    /-> [ Apache / PHP server ]
                [running HAproxy] --+--> [ Apache / PHP server ]
                                    +--> [ Apache / PHP server ]
                                     \-> [ Apache / PHP server ]

Для HTTP-запитів це чудово працює , запити поширюються на мої сервери Apache просто чудово. Для SSL запитів у мене був HAproxy, який розподіляв запити, використовуючи балансування навантаження TCP, і він працював, однак, оскільки HAproxy не діяв як проксі, він не додав X-Forwarded-Forзаголовка HTTP, а сервери Apache / PHP не знали клієнта реальна IP-адреса.

Отже, я додав stunnelперед HAproxy, читаючи, що оглушення може додати X-Forwarded-Forзаголовок HTTP. Однак пакет, який я міг би встановити в pfSense, не додає цього заголовка ... також це, очевидно, вбиває мою здатність використовувати запити KeepAlive , які я б дуже хотів зберегти. Але найбільшою проблемою, яка вбила цю ідею, було те, що оглушення перетворило HTTPS-запити в звичайні HTTP-запити, тому PHP не знав, що SSL увімкнено, і намагався перенаправити на SSL-сайт.

Як я можу використовувати HAproxy для завантаження балансу на декілька серверів SSL, дозволяючи цим серверам обидва знати IP-адресу клієнта та знати, що використовується SSL? І якщо можливо, як це зробити на моєму сервері pfSense?

Або я повинен кинути все це і просто використовувати nginx?


3
Re: оглушення і X-Forwarded-For, дивіться тут .
Шейн Мадден

@Shane: Дякую Саме там я і прочитав, що програю KeepAlive :-)
Джош

2
+1 за відмінну діаграму ASCII. :-)
KyleFarris

@AlanHamlett, ваше посилання - 404.
luckydonald

@luckydonald спасибі, ось оновлене посилання. Протокол проксі можна використовувати, додавши ключове слово send-proxy у ваш конфігурацію haproxy. Я написав повідомлення в блозі з прикладами тут: wakatime.com/blog/23-how-to-scale-ssl-with-haproxy-and-nginx
Алан Гамлетт

Відповіді:


17

Вам не потрібно все це кидати, ви можете просто використовувати nginx перед haproxy для підтримки SSL, зберігаючи всі налаштування балансування навантаження. Вам навіть не потрібно використовувати nginx для HTTP, якщо ви цього не хочете. Nginx може передавати як X-Forwarded-For, так і користувальницький заголовок із зазначенням, що використовується SSL (і інформація клієнтського сертифікату, якщо ви хочете). Фрагмент Nginx config, який надсилає необхідну інформацію:

proxy_set_header SCHEME $scheme;      # http/https
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header CLIENT_CERT $ssl_client_raw_cert;

37

Як раз для запису, оскільки цей потік часто посилається на HAProxy + SSL, HAProxy підтримує нативні SSL з обох сторін з 1.5-dev12. Отже, маючи X-Forwarded-For, HTTP залишається живим, а також заголовок, який повідомляє серверу про те, що з'єднання було здійснено через SSL, є таким же простим, як і наступне:

listen front
    bind :80
    bind :443 ssl crt /etc/haproxy/haproxy.pem
    mode http
    option http-server-close
    option forwardfor
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    server srv1 1.1.1.1:80 check ...
    ...

Я впевнений, що до того часу, коли ви придумали щось інше, але зараз принаймні нові відвідувачі отримають просте рішення :-)


Дякую, це гарна загальна інформація ... моє запитання стосувалося роботи HAproxy на pfSense, тому наразі мені потрібно використовувати nginx перед HAproxy, оскільки pfSense не підтримує цю версію HAProxy (поки що)
Josh

Вибачте Джош, я не знаю достатньо про pfSense, щоб знати, чи можете ви оновити компоненти на ньому чи ні, і оскільки ви говорили про встановлення пакету, я вважав, що це так. Востаннє я спробував це було близько 5 років тому, тому я не пам'ятаю всіх подробиць.
Віллі Тарро

1
Я зараз мало розумію конфігурацію haproxy, але до останньої версії мені довелося додати acl: acl is-ssl dst_port 443і переписати рядок: reqadd X-Forwarded-Proto:\ https if is-sslNginx, здається, досить добре обробляє цей заголовок
greg0ire

Це спрацювало як шарм. Не потрібно nginx.
Джей Тейлор

1
@ greg0ire це тому, що в останньому гапроксі немає is_ssl, а натомість
ssl_fc

12

Для всіх, хто знайде це питання, я дотримувався порад Ochoto і використовував nginx. Ось конкретні кроки, якими я користувався, щоб зробити цю роботу на моєму маршрутизаторі pfSense :

  1. Використовуючи веб-інтерфейс pfsense, я встановив пакет pfsense PfJailctl та пакет "jail_template" в розділі Система> Пакети, щоб я міг створити в'язницю FreeBSD, під якою збирати та встановлювати nginx у системі pfsense.

  2. Я налаштував в'язницю для свого сервера nginx в розділі Служби> Сідниці , давши новій в'язниці те саме ім'я хоста та IP-адресу віртуального псевдоніма IP, на якому працював HAproxy. Я прив’язав тюрму до інтерфейсу WAN. Я використовував шаблон в'язниці за замовчуванням і вмикав Unionfs, а не nullfs.

  3. Як тільки в'язниця була запущена, я ввійшов до коробки pfsense і побіг jlsзнайти номер в'язниці. Потім я побіг jexec 1 shотримати снаряд всередині в'язниці. Звідти я встановив порти BSD та встановив nginx за допомогою:

    portsnap extract
    portsnap fetch update
    cd /usr/ports/www/nginx
    make install clean
    
  4. Потім я налаштував nginx для прослуховування на порту 443 і передав усі запити HAproxy на порт 80, включаючи реальний IP та статус SSL у заголовках HTTP. Моє usr/local/etc/nginx/nginx.confвиглядає так:

    worker_processes  1;
    
    events {
        worker_connections  2048;
    }
    
    http {
        upstream haproxy {
            server 209.59.186.35:80;
        }
    
        server {
            listen       443;
            server_name  my.host.name default_server;
            ssl                  on;
            ssl_certificate      my.crt;
            ssl_certificate_key  my.key;
            ssl_session_timeout  5m;
    
            ssl_protocols  SSLv3 TLSv1;
            ssl_ciphers  HIGH:!aNULL:!MD5;
            ssl_prefer_server_ciphers   on;
    
            location / {
                proxy_pass http://haproxy;
    
                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 https;
            }
        }
    
    }
    
  5. Потім я змінив свою програму PHP для виявлення X-Forwarded-Protoзаголовка HTTP:

    function usingSSL()
    {
        return (
           (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' )
            || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
                   && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https' ));
    }
    

Отже, остаточне налаштування:

(internet) ---> [ -> nginx -> haproxy -]--> (pool of apache servers)
                [    (pfSense server)  ]

2
Вам слід відключити SSLv2, якщо вам це справді не потрібно. gnu.org/software/gnutls/manual/html_node/… Я не знаю, чому Nginx досі підтримує його в конфігурації за замовчуванням.
Ochoto

Також розумійте, що з 1024 підключеннями працівників ви будете підтримувати не більше 512 одночасно клієнтів.
Ochoto

@Ochoto: Дякую за обидва ці поради! Я новачок у HAproxy, але ще менше знайомий з nignx ...
Джош

7

Моя конфігурація для версії haproxy 1.5-dev-17:

global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        #log loghost    local0 info
        maxconn 4096
        #chroot /usr/share/haproxy
        user haproxy
        group haproxy
        daemon
        #debug
        #quiet

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        option  http-server-close
        retries 3
        option redispatch
        fullconn 1000        
        maxconn 1000
        timeout queue 600s
        timeout connect 5s
        timeout client 600s
        timeout server 600s

frontend http-in
        bind *:80
        bind *:443 ssl crt /usr/local/etc/ssl/certs
        reqadd X-Forwarded-Proto:\ https if { ssl_fc }
        default_backend varnish-ha
        option forwardfor
backend varnish-ha
  server hafront1 10.1.69.1:6081  minconn 100 maxqueue 10000

Він використовує ssl_fcACL. Зверніть увагу, що option http-server-closeдеталь дуже важлива.


Спасибі! Я запускаю HAProxy v1.4, тому не думаю, що можу це зробити, але це може допомогти іншим.
Джош

Так, і 1,5 має бути скоро.
greg0ire

5

HAProxy не може потрапити на сервер із підтримкою SSL без використання необробленого режиму TCP, програвши X-Forwarded-For , але, можливо, ви зможете повторно зашифрувати трафік за допомогою прослуховування для проходження транзиту. Некрасиво, правда.

Мені подобається підхід Ochoto краще, із застереженням: nginx - це ідеально здатний балансир навантаження; якщо ви використовуєте його, я б сказав, використовуйте його для всього. Проксі-сервер вхідних HTTPS для завантаження збалансованих HTTPS-записів - і, таким чином, немає необхідності у спеціальних заголовках для інформації про SSL (якщо вам не потрібен клієнтський сертифікат).


Я не впевнений, чому я чіпляюся за HAproxy. Я думаю, це тому, що у pfSense є пакет, і SOIS використовує його. Жодна з них не є чудовою причиною. :-)
Джош

Я відступаю від nginx, маючи здатний балансир завантаження, якщо ви не використовуєте нестандартний модуль upstream_fair, він робить простий круглої робін (або хеш клієнта ip), не враховуючи, якщо бекенд призначення вже зайнятий запитами і, таким чином, зростає черга в цьому бекенді, коли є інші безкоштовні програми, які чекають на роботу. HAProxy також чудово відстежує мітки та відображає статистику щодо них.
Ochoto

Якщо тільки один з наступних стане справжньою A) Nginx отримує пристойний стан відстеження та балансування навантаження справедливої б) HAProxy отримує пристойну підтримку SSL можна тільки сподіватися
Явір Shahpasov

Я щойно розгорнув налаштування, використовуючи nginx -> haproxy -> nginx -> бекенд для SSL, це пов’язано з відсутністю підтримки HTTPS у haproxy, як обговорювалося тут, а також тому, що nginx не підтримує сценарії перевірки здоров'я http.
Джеффрі

2

Минулого року я реалізував рішення про інтеграцію HAProxy з pfSense таким чином, щоб він використовував усі функції HAProxy і підтримував хорошу ізоляцію з pfSense. Так що це життєздатний варіант для виробничих середовищ . SSL припиняється на HAProxy . Я встановив HAProxy всередині в'язниці в pfSense за допомогою ezjail та Ports Collection . Таким чином дуже просто підтримувати обидва компоненти незалежно. І ви можете встановити будь-яку версію, яку хочете. Я почав з 1,5-dev13. І відтоді це для мене прекрасно працює. Я тут все задокументував.

Встановлення HAProxy на pfSense

BTW Віллі, велике спасибі за такий чудовий продукт.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.