Frage Wie kann ich HAproxy mit SSL verwenden und X-Forwarded-For-Header erhalten und PHP mitteilen, dass SSL verwendet wird?


Ich habe folgendes Setup:

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

Für HTTP-Anfragen funktioniert das großartig, Anfragen werden gut an meine Apache-Server verteilt. Für SSL-Anfragen hatte ich HAproxy, das die Anfragen über den TCP-Load-Balancing verteilte, und es funktionierte, da HAproxy nicht als Proxy agierte X-Forwarded-For HTTP-Header, und der Apache / PHP-Server kannte die reale IP-Adresse des Clients nicht.

Also, fügte ich hinzu stunnel vor HAproxy könnte das Lesen dieses Stunnels das hinzufügen X-Forwarded-For HTTP-Header Allerdings fügt das Paket, das ich in pfSense installieren konnte, diesen Header nicht hinzu ... Dies tötet anscheinend meine Fähigkeit, KeepAlive-Anfragen zu verwenden, die ich gerne behalten würde. Aber das größte Problem, das diese Idee zunichte machte, war, dass stunnel die HTTPS-Anfragen in einfache HTTP-Anfragen umwandelte, sodass PHP nicht wusste, dass SSL aktiviert war und versuchte, auf die SSL-Site umzuleiten.

Wie kann ich HAproxy verwenden, um das Guthaben auf mehrere SSL-Server zu verteilen, sodass diese Server die IP-Adresse des Clients kennen? und wissen, dass SSL verwendet wird? Und wenn möglich, wie kann ich das auf meinem pfSense Server tun?

Oder sollte ich all das fallen lassen und nginx benutzen?


19
2017-08-17 21:08


Ursprung


Re: Stunnel und X-Forwarded-For, sehen Hier. - Shane Madden♦
@ Shane: Danke. Genau dort habe ich gelesen, dass ich KeepAlive verliere :-) - Josh
+1 für exzellente ASCII-Diagramme. :-) - KyleFarris
@AlanHamlett, dein Verknüpfung ist 404. - luckydonald
@ luckydonald danke, hier ist ein aktualisierter Link. Sie können das Proxy-Protokoll verwenden, indem Sie das send-proxy-Schlüsselwort zu Ihrer haproxy-Konfiguration hinzufügen. Ich habe hier einen Blogbeitrag mit Beispielen geschrieben: wakatime.com/blog/23-how-to-scale-ssl-mit-haproxy-and-nginx - Alan Hamlett


Antworten:


Sie müssen nicht alles löschen, Sie könnten nur Nginx vor Haproxy für SSL-Unterstützung verwenden, behalten Sie alle Ihre Lastenausgleichskonfiguration. Sie müssen nicht einmal nginx für HTTP verwenden, wenn Sie nicht möchten. Nginx kann sowohl X-Forwarded-For als auch einen benutzerdefinierten Header übergeben, der angibt, dass SSL verwendet wird (und Client-Cert-Informationen, wenn Sie möchten). Nginx Config Snippet, das die erforderlichen Informationen sendet:

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;

16
2017-08-17 21:38





Nur zur Erinnerung, da dieser Thread oft in Bezug auf HAProxy + SSL erwähnt wird, unterstützt HAProxy natives SSL auf beiden Seiten seit 1.5-dev12. Mit X-Forwarded-For, HTTP keep-alive und einem Header, der dem Server mitteilt, dass die Verbindung über SSL hergestellt wurde, ist das folgende einfach:

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 ...
    ...

Ich bin mir sicher, dass du bis dahin etwas anderes gefunden hast, aber zumindest neue Besucher werden jetzt die einfache Lösung bekommen :-)


34
2017-09-16 08:35



Danke, das sind gute allgemeine Informationen ... meine Frage war über HAproxy läuft auf pfSense Deshalb muss ich jetzt nginx vor HAproxy verwenden, da pfSense diese Version von HAProxy (noch) nicht unterstützt. - Josh
Entschuldigung, Josh, ich weiß nicht genug über pfSense, um zu wissen, ob du Komponenten aktualisieren kannst oder nicht, und da du über die Installation eines Pakets gesprochen hast, habe ich geglaubt, dass dies der Fall ist. Das letzte Mal, als ich es versuchte, war es vor ungefähr 5 Jahren, also erinnere ich mich nicht an alle Details. - Willy Tarreau
Ich verstehe jetzt nicht viel über die haproxy-Konfiguration, aber mit der neuesten Version musste ich ein acl hinzufügen: acl is-ssl dst_port 443 und schreibe eine Zeile um: reqadd X-Forwarded-Proto:\ https if is-ssl Nginx scheint diesen Header ziemlich gut zu handhaben - greg0ire
Das hat wie ein Zauber funktioniert. Kein Nginx erforderlich. - Jay Taylor
@ greg0ire das ist, weil mit der neuesten haproxy gibt es keine is_ssl aber ssl_fc statt - josch


Für jeden anderen, der diese Frage findet, habe ich Ochotos Ratschlag befolgt und nginx benutzt. Hier sind die spezifischen Schritte, die ich verwendet habe, um diese Arbeit zu machen auf meinem pfSense-Router:

  1. Unter Verwendung der pfsense Webschnittstelle installierte ich den pfsense PfJailctl Paket und das "jail_template" -Paket unter System> Pakete Ich könnte also ein FreeBSD-Jail erstellen, unter dem ich nginx auf dem pfsense-System kompilieren und installieren kann.

  2. Ich habe ein Gefängnis für meinen Nginx-Server unter konfiguriert Dienstleistungen> KerkerGeben Sie dem neuen Gefängnis den gleichen Hostnamen und die IP-Adresse des virtuellen IP-Alias, auf dem HAproxy ausgeführt wurde. Ich habe das Gefängnis an die WAN-Schnittstelle gebunden. Ich habe die Standard-Jail-Vorlage verwendet und unionfs anstelle von nullfs aktiviert.

  3. Sobald das Gefängnis begonnen hatte, ging ich in die Pfsensenkiste und rannte los jls um die Nummer des Gefängnisses zu finden. Ich bin dann gerannt jexec 1 shum eine Shell in das Gefängnis zu bekommen. Von dort habe ich BSD-Ports eingerichtet und nginx installiert mit:

    portsnap extract
    portsnap fetch update
    cd /usr/ports/www/nginx
    make install clean
    
  4. Ich habe dann nginx konfiguriert, um auf Port 443 zu hören und alle Anfragen an HAproxy auf Port 80 zu übergeben, einschließlich der realen IP und des SSL-Status in den HTTP-Headern. Meine usr/local/etc/nginx/nginx.conf sieht aus wie:

    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. Ich habe dann meine PHP-Applikation modifiziert, um das zu erkennen X-Forwarded-Proto HTTP-Kopfzeile:

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

Das endgültige Setup ist also:

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

11
2017-08-18 15:17



Sie sollten SSLv2 deaktivieren, wenn Sie es nicht wirklich brauchen. gnu.org/software/gnutls/manual/html_node/... Ich weiß nicht, warum Nginx es immer noch in seiner Standardkonfiguration unterstützt. - Ochoto
Beachten Sie auch, dass Sie mit 1024 Arbeiterverbindungen maximal 512 gleichzeitige Clients unterstützen. - Ochoto
@Ochoto: Danke für beide Tipps! Ich bin neu bei HAproxy, aber noch weniger vertraut mit nignx ... - Josh


Meine Konfiguration für eine 1.5-dev-17 Version von haproxy:

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

Es nutzt die ssl_fc ACL. Bitte beachten Sie, dass die option http-server-close Teil ist sehr wichtig.


5
2018-01-15 10:58



Vielen Dank! Ich betreibe HAProxy v1.4, also glaube ich nicht, dass ich das kann, aber es könnte anderen helfen. - Josh
Ja, und die 1.5 sollte bald raus sein. - greg0ire


HAProxy kann nicht auf ein SSL-Backend zugreifen, ohne den Raw-TCP-Modus zu verwenden X-Forwarded-For, aber Sie könnten den Datenverkehr möglicherweise mit einem Listening Stunnel für den Back-End-Transit neu verschlüsseln. Hässlich.

Ich mag Ochotos Ansatz besser, mit einem Vorbehalt: nginx ist ein perfekt fähiger Load Balancer; Wenn du es benutzt, würde ich es für alles verwenden. Proxy für eingehende HTTPS, um ausgeglichene HTTPS-Back-Ends zu laden. Auf diese Weise sind keine benutzerdefinierten Header für SSL-Informationen erforderlich (außer Sie benötigen das Client-Zertifikat).


4
2017-08-17 21:48



Ich bin nicht sicher, warum ich an HAproxy festhalte. Ich denke es ist, weil PfSense ein Paket dafür hat und SOIS es benutzt. Keines ist ein guter Grund. :-) - Josh
Ich bin davon abgenickt, dass Nginx ein fähiger Load Balancer ist, es sei denn, Sie verwenden das Nicht-Standard-Modul upstream_fair, es macht ein einfaches Round-Robin (oder Client-IP-Hash), ohne zu berücksichtigen, ob das Ziel-Backend bereits mit Anfragen beschäftigt ist und somit die Warteschlange in diesem Backend wächst Es gibt andere Backends, die frei sind und auf einen Job warten. HAProxy überwacht auch Backends und zeigt Statistiken über sie. - Ochoto
Wenn nur einer der folgenden Punkte zutreffen würde: a) Nginx erhält eine anständige Zustandsverfolgung und einen fairen Lastenausgleich. B) HAProxy erhält anständige SSL-Unterstützung. Man kann nur hoffen - Yavor Shahpasov
Ich habe gerade ein Setup unter Verwendung von nginx -> haproxy -> nginx -> Backend für SSL implementiert, dies liegt an der fehlenden HTTPS-Unterstützung in haproxy wie hier beschrieben, aber auch daran, dass nginx keine HTTP-Health-Check-Skripte unterstützt. - Geoffrey


Ich habe letztes Jahr eine Lösung implementiert Integriere HAProxy mit pfSense in einer Weise, dass es alle Funktionen von HAProxy nutzt und eine gute Isolation mit pfSense aufrechterhält. Damit ist es eine praktikable Option für Produktionsumgebungen. SSL wird auf HAProxy beendet. Ich habe HAProxy in einem Gefängnis installiert in pfSense mit ezjail und Ports-Sammlung. Auf diese Weise ist es sehr einfach, beide Komponenten unabhängig voneinander zu warten. Und Sie können installieren, welche Version Sie wollen. Ich habe mit 1.5-dev13 angefangen. Und seitdem funktioniert es perfekt für mich. Ich habe das Ganze hier dokumentiert.

Installation von HAProxy auf pfSense

BTW Willy, vielen Dank für solch ein ausgezeichnetes Produkt.


1
2018-04-29 13:15