404 Routing problem bei Haproxy und mehreren Domains mit tcp/http frontends

Started by badzoo, January 21, 2021, 12:53:44 PM

Previous topic - Next topic
Hallo, ich nutze Haproxy 2.0.19 und das Letsencrypt-Plugin

Mein Setup:
- Ein Backend cloud.mydomain.com, für das ich die SSL-Terminierung mit Letsencrypt verwenden muss.
- Ein Backend sub1.mydomain.com, das für Ports 80 und 443 TCP verwendet
- ein Backend sub2.mydomain.com, das für Ports 80 und 443 TCP verwendet an das auch alle Wildcard aufrufe für * sub2.mydomain.com weitergeleitet werden soll
- Port 80 sollte nur für acme-redirects verwendet werden und der Rest des Datenverkehrs an SSL umgeleitet werden
- Derzeit leite ich Port 80 für cloud.domain.com auf der seite selbst um, nicht im haproxy. Das muss ich auch ändern

Meine Konfiguration unten funktioniert die meiste Zeit gut für das Cloud.mydomain.com backend, schlägt jedoch manchmal mit 404 für das tcp backend sub2.mydomain.com fehl.
Im Log konnte ich keine Nachricht über den fehler 404 finden. Ich konnte nur in einem Eintrag sehen, dass sub2.domain.com beim frontend-in an sub1.domain.com weitergeleitet wurde, was den 404-Fehler zu verursachen scheint. Aber ich könnte das bisher nicht beheben ..

Ich habe bereits zwei Tage mit Testen verbracht. Wie bekomme ich das zum laufen?
Vielen Dank..

Hier meine config:

global
        uid                         80
        gid                         80
        chroot                      /var/haproxy
        daemon
        stats                       socket /var/run/haproxy.socket group proxy mode 775 level admin
        nbproc                      1
        nbthread                    1
        tune.ssl.default-dh-param   1024
        spread-checks               2
        tune.chksize                16384
        tune.bufsize                16384
        tune.lua.maxmem             0
        log /var/run/log local0 debug
        ssl-default-bind-options no-sslv3 no-tlsv10 no-tls-tickets
        ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
        ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
       

    defaults
        log     global
        maxconn 500
        timeout client 5s
        timeout connect 30s
        timeout server 450s
        retries 3
        default-server init-addr libc,last
        mode tcp
        option tcplog

    # Frontend: frontend_http ()
    frontend frontend_http
        bind *:80 name *:80
        mode tcp
        default_backend sub1_http
        # tuning options
        timeout client 5s

        # logging options
        option tcplog
        # ACL: find_acme_challenge
        acl acl_5b16dcd0b64453.15125102 path_beg -i /.well-known/acme-challenge/
        # ACL: host_is_cloud
        acl acl_5ae04b3549a228.53262550 hdr(host) -i cloud.mydomain.com

        # ACTION: redirect_acme_challenges
        use_backend acme_challenge_backend if acl_5b16dcd0b64453.15125102
        # ACTION: cloud-domain
        use_backend cloud if acl_5ae04b3549a228.53262550
        # WARNING: pass through options below this line
        option tcplog


    # Frontend: frontend_in ()
    frontend frontend_in
        bind *:443 name *:443
        mode tcp
        default_backend sub1_https
        # tuning options
        timeout client 5s
        # stickiness
        stick-table type ip size 50k expire 30m 
        tcp-request connection track-sc0 src
        # logging options
        option tcplog
        # ACL: clienthello
        acl acl_5fff84ac926de8.55606604 req.ssl_hello_type 1

        # goal here to catch all calls to sub2.mydomain.com and *.sub2.mydomain.com
        # ACL: sub2_sni
        acl acl_60073cbe607c98.79079679 req.ssl_sni -m sub -i sub2.mydomain.com
        # ACL: sub2_sni_2
        acl acl_60074ff27bb5c3.85553936 req.ssl_sni -i sub2.mydomain.com
        # ACL: sub2_sni_3
        acl acl_600758b1975163.29487316 ssl_fc_sni sub2.mydomain.com
       
        # ACL: cloud_sni
        acl acl_60018b049c5c68.40679038 req.ssl_sni -i cloud.mydomain.com
        # ACL: find_acme_challenge
        acl acl_5b16dcd0b64453.15125102 path_beg -i /.well-known/acme-challenge/

        # Inspect Header, capture and log all
        tcp-request inspect-delay 5s
        tcp-request content capture req.ssl_sni len 100
        capture request header Referer len 64
        capture request header Content-Length len 20
        capture request header User-Agent len 64
        # ACTION: log_own_format for more details
        # NOTE: actions with no ACLs/conditions will always match
        log-format "frontend-in: ssl-url: %[capture.req.hdr(0)] %{+Q}o\ client_address = %ci, client_port = %cp, server_address = %si, server_port = %sp ,  %Th\ %hr\%hrl \%hsl\ %f\ %b/%s\ %Tw/%Tc/%Tt\ %B\   %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ {%hrl}\ {%hsl}\ "
        # ACTION: accept_ssl
        tcp-request content accept if acl_5fff84ac926de8.55606604
        # ACTION: sub2_sni
        use_backend sub2 if acl_60073cbe607c98.79079679 || acl_60074ff27bb5c3.85553936 || acl_600758b1975163.29487316
        # ACTION: cloud_sni
        use_backend proxy_ssl if acl_60018b049c5c68.40679038
        # ACTION: redirect_acme_challenges
        use_backend acme_challenge_backend if acl_5b16dcd0b64453.15125102

    # Frontend: frontend_https ()
    frontend frontend_https
        http-response set-header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
        bind 127.0.0.1:4443 name 127.0.0.1:4443 accept-proxy ssl no-sslv3 no-tlsv10 no-tls-tickets ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 crt-list /tmp/haproxy/ssl/60018e42546898.15414025.certlist
        mode http
        option http-keep-alive
       
        default_backend cloud
        option forwardfor
        # tuning options
        timeout client 5s

        # logging options
        option httplog

        # ACL: find_acme_challenge
        acl acl_5b16dcd0b64453.15125102 path_beg -i /.well-known/acme-challenge/

        # ACTION: redirect_acme_challenges
        use_backend acme_challenge_backend if acl_5b16dcd0b64453.15125102

    # Backend: cloud ()
    backend cloud
        # health checking is DISABLED
        mode http
        balance source
        # stickiness
        stick-table type ip size 50k expire 30m 
        stick on src
        # tuning options
        timeout connect 30s
        timeout server 450s

        # WARNING: pass through options below this line
        option tcp-smart-connect
        http-reuse never
        server ucs 10.10.10.2:443 ssl verify none

    # Backend: acme_challenge_backend (Added by Let's Encrypt plugin)
    backend acme_challenge_backend
        # health checking is DISABLED
        mode http
        balance source
        # stickiness
        stick-table type ip size 50k expire 30m 
        stick on src
        # tuning options
        timeout connect 30s
        timeout server 450s
        http-reuse never
        server acme_challenge_host 127.0.0.1:43580

    # Backend: sub1_http ()
    backend sub1_http
        # health checking is DISABLED
        mode tcp
        balance source
        # stickiness
        stick-table type ip size 50k expire 30m 
        stick on src
        # tuning options
        timeout connect 30s
        timeout server 450s
        server sub1-http 192.168.1.150:80

    # Backend: sub1_https ()
    backend sub1_https
        # health checking is DISABLED
        mode tcp
        balance source
        # stickiness
        stick-table type ip size 50k expire 30m 
        stick on src
        # tuning options
        timeout connect 30s
        timeout server 450s
        server sub1-https 192.168.1.150:443

    # Backend: proxy_ssl ()
    backend proxy_ssl
        # health checking is DISABLED
        mode tcp
        balance source
        # stickiness
        stick-table type ip size 50k expire 30m 
        stick on src
        # tuning options
        timeout connect 30s
        timeout server 450s
        server loopback-for-tls 127.0.0.1:4443 send-proxy-v2 check-send-proxy

    # Backend: sub2 ()
    backend sub2
        # health checking is DISABLED
        mode tcp
        balance source
        # stickiness
        stick-table type ip size 50k expire 30m 
        stick on src
        # tuning options
        timeout connect 30s
        timeout server 450s
        server sub2 192.168.1.180:443

    listen local_statistics
        bind            127.0.0.1:8822
        mode            http
        stats uri       /haproxy?stats
        stats realm     HAProxy\ statistics
        stats admin     if TRUE


Wenn Du Letsencrypt eingerichtet hast, sollte im HAProxy auch als Packendpool ein "acme_challenge_backend" eingerichtet worden sein.
Ausserdem sollte bei conditions ein "NO_find_acme_challenge" eingetragen worden sein.
Dann machst Du eine neue Condition "redirect_80_443" mit condition type "Traffic is SSL" und bei negation ein hacken rein.
Bei rules sollte ein "   redirect_acme_challenges" automatisch da sein. Zusätzlich machst ein "HTTP_Redirect" mit select Condition "NO_find_acme_challange" bei execute function "http-request-redirect" und http-redirect mit "scheme https code 301".

Dann unter public service den für Port 80 auswählen und unter selected rules eintragen "redirect-acme-chalange" sofern noch nicht drin und "HTTP_Redirect".
Dann wird automatisch umgeleitet auf Port 44 solange nichts mit acme (letsencrypt) kommt.

Hallo CoolTux, danke für die Antwort.. aber letsencrypt funktioniert ja .. Die rules dafür stehen ja drin und auch das backend.. das problem ist aber die umleitung der sub1.domain.com und sub2.domain.com.. was genau soll denn hier bei meiner config aus deiner sicht fehlen ?

Ich kann die Config nicht wirklich lesen.
Wenn Du mir zeigst wie Du an den Auszug gekommen bist kann ich Dir meinen zeigen.

Hi, du kannst den Auzug auf dem Opnsense bekommen, wenn du folgendes eingibst:

cat /usr/local/etc/haproxy.conf

Diese wird immer neu generiert, wenn du in der Gui Apply drückst.

Bei Bedarf helfe ich dir gern, wie du die Datei bekommst.. Aber beachte bitte das ich sowohl http als tcp mode als Frontend brauche..

Quote from: badzoo on January 21, 2021, 02:26:16 PM
Bei Bedarf helfe ich dir gern, wie du die Datei bekommst.. Aber beachte bitte das ich sowohl http als tcp mode als Frontend brauche..

Ah das wird dann wohl anders sein wie normaler SSL offloading. verstehe. Mist und ich dachte ich kann Dir da helfen. Sorry


Mach mal Screenshots von deiner HAProxy config
(Unoffial Community) OPNsense Telegram Group: https://t.me/joinchat/0o9JuLUXRFpiNmJk

PM for paid support

Wovon genau braucht du Bilder ? alle Frontends Backend rules conditions ??

Kannst du die Config oben lesen ?
Dort wo es nicht verständlich ist kann ich bilder

Ich stelle mal was zusammen an bildern