Redirect - Grommunio

Started by dima1002, July 03, 2024, 06:21:49 PM

Previous topic - Next topic
July 03, 2024, 06:21:49 PM Last Edit: July 06, 2024, 07:27:58 PM by dima1002
Hallo,

kann jemand bitte mal über meine Konfiguration drüber schauen.
Beim Grommunio Server bekomme ich immer ein Redirect, wieso?

#
# Automatically generated configuration.
# Do not edit this file manually.
#

global
    uid                         80
    gid                         80
    chroot                      /var/haproxy
    daemon
    stats                       socket /var/run/haproxy.socket group proxy mode 775 level admin
    nbthread                    6
    hard-stop-after             60s
    no strict-limits
    tune.ssl.ocsp-update.mindelay 300
    tune.ssl.ocsp-update.maxdelay 3600
    httpclient.resolvers.prefer   ipv4
    tune.ssl.default-dh-param   2048
    spread-checks               2
    tune.bufsize                16384
    tune.lua.maxmem             0
    log                         /var/run/log local0 info
    lua-prepend-path            /tmp/haproxy/lua/?.lua
cache opnsense-haproxy-cache
    total-max-size 4
    max-age 60
    process-vary off

defaults
    log     global
    option redispatch -1
    timeout client 60s
    timeout connect 60s
    timeout server 60s
    retries 3
    default-server init-addr last,libc

# autogenerated entries for ACLs


# autogenerated entries for config in backends/frontends

# autogenerated entries for stats




# Frontend: Letsencrypt_80 ()
frontend Letsencrypt_80
    bind 192.168.252.253:80 name 192.168.252.253:80
    mode tcp
    default_backend acme_challenge_backend

    # logging options
    # ACL: find_acme_challenge
    acl acl_6546b7f7e92430.59551874 path_beg -i /.well-known/acme-challenge/

    # ACTION: redirect_acme_challenges
    use_backend acme_challenge_backend if acl_6546b7f7e92430.59551874

# Frontend: LetsEncrypt_443 (LetsEncrypt_443)
frontend LetsEncrypt_443
    http-response set-header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
    bind 192.168.252.253:443 name 192.168.252.253:443 ssl prefer-client-ciphers ssl-min-ver TLSv1.2 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-ECDSA-AES128-SHA256 ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/657480646e0916.14570670.certlist
    mode http
    option http-keep-alive
    default_backend acme_challenge_backend
    option forwardfor

    # logging options
    # ACL: find_acme_challenge
    acl acl_6546b7f7e92430.59551874 path_beg -i /.well-known/acme-challenge/
    # ACL: grom
    acl acl_664c906453f702.68929731 hdr(host) -i mail.test.de



    # ACTION: redirect_acme_challenges
    use_backend acme_challenge_backend if acl_6546b7f7e92430.59551874
    # ACTION: Grommunio
    use_backend Grommunio if acl_664c906453f702.68929731



# Backend: acme_challenge_backend (Added by ACME Client 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
    http-reuse safe
    server acme_challenge_host 127.0.0.1:43580


# Backend: Grommunio ()
backend Grommunio
    # health checking is DISABLED
    mode http
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m 
    stick on src
    # WARNING: pass through options below this line
    http-request set-header X-Real-IP %[src]
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request cache-use opnsense-haproxy-cache
    http-response cache-store opnsense-haproxy-cache
    http-reuse safe
    option forwarded proto host for
    option forwardfor
    http-request cache-use opnsense-haproxy-cache
    http-response cache-store opnsense-haproxy-cache
    server Grommunio 192.168.133.33:443 ssl alpn h2,http/1.1 verify none



# statistics are DISABLED


July 04, 2024, 04:04:56 PM #1 Last Edit: July 04, 2024, 04:09:10 PM by JeGr
> Beim Grommunio Server bekomme ich immer ein Redirect, wieso?

Einen Redirect WORAUF? Was wird aufgerufen? Wohin wird umgeleitet? Ein klein wenig mehr Input wäre hier schon sinnvoll, um das analysieren zu können.

Zusätzlich heißt und läuft das 443 Frontend LetsEncrypt. Das ist etwas verwirrend, da LE nicht auf 443 arbeitet. Der Zertifikatscheck wird nur über 80 durchgeführt - 443 macht hier keinen Sinn, da du ja gerade nen Zert ausstellen willst zur Nutzung. Da macht dann auch Acme Challenge als Default Backend keinen Sinn da es schlicht nie stattfindet.

Da dein Default BE aber Acme ist und das nen Redirect macht vermute ich zwei Möglichkeiten.
a) deine ACL matcht nicht und du läufst ins Acme Backend (wie gesagt nutzlos auf 443) und bekommst nen Redirect von dem
b) du biegst richtig ab und der Redir kommt vom Grommunio Server selbst.

Cheers
"It doesn't work!" is no valid error description! - Don't forget to [applaud] those offering time & brainpower to help you!
Better have some *sense as no(n)sense! ;)

If you're interested in german-speaking business support, feel free to reach out via PM.

July 06, 2024, 07:21:02 PM #2 Last Edit: July 07, 2024, 08:54:08 AM by dima1002
Achso sorry, der Grommunio Server hat einen Keycloack für 2FA installiert.
Ich melde mich erst mit Benutzername und Passwort an, dann kommt die 2FA Anmeldung, die ist auch noch erfolgreich und dann macht er irgendwie 2-3 redirects / loops.

Was für Infos bräuchtet ihr da noch? oder wie kann ich helfen?

https://www.keycloak.org/server/reverseproxy

Kann ich eigentlich die Datei in der Shell direkt bearbeiten?
/usr/local/etc/haproxy.conf oder /usr/local/etc/haproxy.conf.staging?
Irgendwie überschreibt die GUI meine Konfiguration immer.

hier wäre noch meine Aktuelle Konfiguration, habe nun schon etwas angepasst:

global
    uid                         80
    gid                         80
    chroot                      /var/haproxy
    daemon
    stats                       socket /var/run/haproxy.socket group proxy mode 775 level admin
    nbthread                    6
    hard-stop-after             60s
    no strict-limits
    tune.ssl.ocsp-update.mindelay 300
    tune.ssl.ocsp-update.maxdelay 3600
    httpclient.resolvers.prefer   ipv4
    tune.ssl.default-dh-param   2048
    spread-checks               2
    tune.bufsize                16384
    tune.lua.maxmem             0
    log                         /var/run/log local0 info
    lua-prepend-path            /tmp/haproxy/lua/?.lua

defaults
    log     global
    option redispatch -1
    timeout client 60s
    timeout connect 60s
    timeout server 60s
    retries 3
    default-server init-addr last,libc

# Frontend: Letsencrypt_80
frontend Letsencrypt_80
    bind 192.168.252.122:80 name 192.168.252.122:80
    mode tcp
    default_backend acme_challenge_backend

    # logging options
    # ACL: find_acme_challenge
    acl acl_6546b7f7e92430.59551874 path_beg -i /.well-known/acme-challenge/
    # ACTION: redirect_acme_challenges
    use_backend acme_challenge_backend if acl_6546b7f7e92430.59551874

# Frontend: LetsEncrypt_443 (LetsEncrypt_443)
frontend LetsEncrypt_443
    http-response set-header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
    bind 192.168.252.122:443 name 192.168.252.122:443 ssl crt /var/etc/acme-client/certs/33747d8d955811.89930809/fullchain.pem key /var/etc/acme-client/keys/33747d8d955811.89930809/private.key
    mode http
    option http-keep-alive
    default_backend acme_challenge_backend

    # logging options
    # ACL: find_acme_challenge
    acl acl_6546b7f7e92430.59551874 path_beg -i /.well-known/acme-challenge/
    # ACL: Grommunino
    acl acl_664c906453f702.68929731 hdr(host) -i mail.test.de

    # ACTION: redirect_acme_challenges
    use_backend acme_challenge_backend if acl_6546b7f7e92430.59551874
    # ACTION: Grommunio
    use_backend Grommunio if acl_664c906453f702.68929731


# Backend: acme_challenge_backend (Added by ACME Client 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
    http-reuse safe
    server acme_challenge_host 127.0.0.1:43580

# Backend: Grommunio
backend Grommunio
    # health checking is DISABLED
    mode http
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m 
    cookie KC_ROUTE insert indirect nocache
    # WARNING: pass through options below this line
    http-request set-header X-Real-IP %[src]
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request set-header X-Forwarded-For %[src]
    http-reuse safe
    option forwardfor
    server Grommunio 192.168.130.33:443 ssl alpn h2,http/1.1 verify none crt /var/etc/acme-client/certs/33747d8d955811.89930809/fullchain.pem key /var/etc/acme-client/keys/33747d8d955811.89930809/private.key

# statistics are DISABLED


> Irgendwie überschreibt die GUI meine Konfiguration immer.

Das ist ja auch der Sinn der UI. Wenn du den proxy selbst händisch konfigurieren willst, kein Problem, dann würde ich den aber entweder in nen Container oder ne VM packen. Aber wenn du ne GUI hast, machts ja auch Sinn dass die den Ton angibt und du nicht irgendwas dann unten drunter anpasst was die UI dann nicht sieht - wie soll sie das sonst mitbekommen?

> Achso sorry, der Grommunio Server hat einen Keycloack für 2FA installiert.

wenn da noch OAUTH o.ä. mit dazwischen hängt, dann würde ich aber erstmal da die Pfade kontrollieren, dann ist ein Redirect ja aber auch normal, oder wie soll die Anmeldung sonst funktionieren? Evtl. nutzt dein keycloak schlicht die falsche Exit oder Übergabe URI dass du nicht zum Grommunio zurück geworfen wirst? Hört sich zumindest erstmal eher nach einem Problem der Auth via Keycloak und Grommunio an als spezifische ein HAproxy Problem zumal keycloak ja auch nichtmal via Proxy gehostet wird.

Cheers
"It doesn't work!" is no valid error description! - Don't forget to [applaud] those offering time & brainpower to help you!
Better have some *sense as no(n)sense! ;)

If you're interested in german-speaking business support, feel free to reach out via PM.

Der Keycloak Server ist auf dem Grommunio installiert. Hilft das dann evtl. weiter um das Thema besser zu verstehen?

Hier mal die Nginx von dem Grommunio Server:

#user  nginx;
worker_processes  1;
load_module lib64/nginx/modules/ngx_http_brotli_static_module.so;
load_module lib64/nginx/modules/ngx_http_brotli_filter_module.so;
load_module lib64/nginx/modules/ngx_http_vhost_traffic_status_module.so;

# load_module lib64/nginx/modules/ngx_http_fancyindex_module.so;
# load_module lib64/nginx/modules/ngx_http_headers_more_filter_module.so;
# load_module lib64/nginx/modules/ngx_http_image_filter_module.so;
# load_module lib64/nginx/modules/ngx_http_perl_module.so;
# load_module lib64/nginx/modules/ngx_http_xslt_filter_module.so;
# load_module lib64/nginx/modules/ngx_mail_module.so;
# load_module lib64/nginx/modules/ngx_rtmp_module.so;
# load_module lib64/nginx/modules/ngx_stream_module.so;

#error_log  /var/log/nginx/error.log;
#error_log  /var/log/nginx/error.log  notice;
#error_log  /var/log/nginx/error.log  info;

#pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
    use epoll;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    include conf.d/*.conf;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  /var/log/nginx/host.access.log  main;

        location / {
            root   /srv/www/htdocs/;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           /srv/www/htdocs/;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   /srv/www/htdocs/;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    Allow TLS version 1.2 only, which is a recommended default these days
    #    by international information security standards.
    #    ssl_protocols        TLSv1.2;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   /srv/www/htdocs/;
    #        index  index.html index.htm;
    #    }
    #}

    include vhosts.d/*.conf;

}


Keycloak Konfiguration

mail:~ # cat /etc/grommunio-keycloak/keycloak.conf
# SPDX-License-Identifier: AGPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 grommunio GmbH

db=mariadb
proxy=edge
http-port=9080
http-relative-path=/auth
http-host=localhost
db-username=grommunio_keycloak
db-password=xxxxxxxxxxxx
db-url-database=grommunio_keycloak
db-url-host=localhost
hostname=mail.test.com


Habe inzwischen auch eine andere HA Proxy Konfiguration:

#
# Automatically generated configuration.
# Do not edit this file manually.
#

global
    uid                         80
    gid                         80
    chroot                      /var/haproxy
    daemon
    stats                       socket /var/run/haproxy.socket group proxy mode 775 level admin
    nbthread                    6
    hard-stop-after             60s
    no strict-limits
    tune.ssl.ocsp-update.mindelay 300
    tune.ssl.ocsp-update.maxdelay 3600
    httpclient.resolvers.prefer   ipv4
    tune.ssl.default-dh-param   2048
    spread-checks               2
    tune.bufsize                16384
    tune.lua.maxmem             0
    log                         /var/run/log local0 info
    lua-prepend-path            /tmp/haproxy/lua/?.lua

defaults
    log     global
    option redispatch -1
    timeout client 60s
    timeout connect 60s
    timeout server 60s
    retries 3
    default-server init-addr last,libc

# autogenerated entries for ACLs


# autogenerated entries for config in backends/frontends

# autogenerated entries for stats

# Frontend: Letsencrypt_80 ()
frontend Letsencrypt_80
    bind 192.168.200.253:80 name 192.168.200.253:80
    mode tcp
    default_backend acme_challenge_backend

    # logging options
    # ACL: find_acme_challenge
    acl acl_6546b7f7e92430.59551874 path_beg -i /.well-known/acme-challenge/

    # ACTION: redirect_acme_challenges
    use_backend acme_challenge_backend if acl_6546b7f7e92430.59551874

# Frontend: LetsEncrypt (LetsEncrypt)
frontend LetsEncrypt
    http-response set-header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
    bind 192.168.200.253:443 name 192.168.200.253:443 ssl prefer-client-ciphers ssl-min-ver TLSv1.2 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-ECDSA-AES128-SHA256 ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/657480646e0916.14570670.certlist
    mode http
    option http-keep-alive
    default_backend acme_challenge_backend

    # ACL: find_acme_challenge
    acl acl_6546b7f7e92430.59551874 path_beg -i /.well-known/acme-challenge/
    # ACL: Grommunino
    acl acl_664c906453f702.68929731 hdr(host) -i mail.test.com
    # ACL: Keycloak
    acl acl_668a627a78cb38.48749184 path_beg -i /auth

    # ACTION: redirect_acme_challenges
    use_backend acme_challenge_backend if acl_6546b7f7e92430.59551874
    # ACTION: Grommunio
    use_backend Grommunio if acl_664c906453f702.68929731
    # ACTION: Keycloak
    use_backend Keycloak if acl_668a627a78cb38.48749184
    # WARNING: pass through options below this line
    redirect scheme https code 301 if !{ ssl_fc }

# Backend: acme_challenge_backend (Added by ACME Client 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
    http-reuse safe
    server acme_challenge_host 127.0.0.1:43580

# Backend: Grommunio ()
backend Grommunio
    # health checking is DISABLED
    mode http
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m 
    cookie KC_ROUTE insert indirect nocache
    # WARNING: pass through options below this line
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Forwarded-Port 443
    http-request set-header X-Forwarded-For %[src]
    option forwardfor
    http-reuse safe
    option forwardfor
    server Grommunio 192.168.120.33:443 ssl alpn h2,http/1.1 verify none cookie 6607c74887063778516557

# Backend: Keycloak ()
backend Keycloak
    # health checking is DISABLED
    mode http
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m 
    cookie KC_ROUTE insert indirect nocache
    # WARNING: pass through options below this line
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Forwarded-Port 443
    http-request set-header X-Forwarded-For %[src]
    option forwardfor
    http-reuse safe
    option forwardfor
    server Keycloak 192.168.120.33:8080 cookie 668a62bcb6c3f299187837

# statistics are DISABLED

> Hier mal die Nginx von dem Grommunio Server:

Das ist aber nur die default nginx.conf, oder? Ich sehe da nichts drin zu keycloak oder Grommunio? Vermutlich wird deren config eher in den conf.d Verzeichnissen sein. Der Rest ist ja fast alles auskommentiert.


> Der Keycloak Server ist auf dem Grommunio installiert. Hilft das dann evtl. weiter um das Thema besser zu verstehen?

Ja und nein. Das stützt den Verdacht, dass es zwischen der Übergabe von keycloak und grommunio scheitert, warum weiß ich deshalb aber leider nicht. Das könnte je nach Config völlig unterschiedlich sein. Möglich wäre irgendwo fehlt die korrekte Domain vom einen zum anderen und der Aufruf geht dann gar nicht zum korrekten Host in HAproxy oder geht unterwegs verloren. Oder es fehlt ein Header damit der von irgendeinem der beiden ausgewertet werden kann.

Das ist eigentlich mehr Sache der Doku zwischen "wie mache ich dass Keycloak und grommunio miteinander reden" und "wie betreibe ich beide korrekt hinter einem proxy" wo u.a. dann genau diese Pitfalls besprochen werden wie "ich brauche Header X sonst kann  Komponente Y nicht wissen dass das via Z aufgerufen wird".

Cheers
"It doesn't work!" is no valid error description! - Don't forget to [applaud] those offering time & brainpower to help you!
Better have some *sense as no(n)sense! ;)

If you're interested in german-speaking business support, feel free to reach out via PM.