Las conexiones a Webmin a través de HAProxy se reenvían al puerto 10000 (HAProxy escucha en 443)

Las conexiones a Webmin a través de HAProxy se reenvían al puerto 10000 (HAProxy escucha en 443)

EDITAR

Solución propia al final de la pregunta.

Estoy usando un HAProxy (en una máquina virtual alquilada) para poder conectarme a algunas aplicaciones que ejecuto en casa. Esto funciona perfectamente bien para casi todos mis servidores. Lo que no funciona muy bien es la siguiente configuración: HAProxy se ejecuta en el puerto 443 en modo http y tiene un backend con el puerto de servidor 10000 (Webmin) porque la conexión funciona, pero después de iniciar sesión me redirigen al puerto 10000 y después de volver a cambiar el puerto. al 443 puedo usar Webmin. Este no es el comportamiento esperado.

Valores predeterminados de HAProxy

defaults
    mode                    http
    log                     global
    log /dev/log local0 info
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    #option forwardfor
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    balance                 leastconn

    stats enable
    stats hide-version
    stats uri /haproxy/stats
    stats refresh 10s
    stats show-node

Definición de interfaz HAProxy Esta es una interfaz general porque solo tengo una IP en la máquina virtual alquilada y estoy usando diferentes servidores según el encabezado del host.

frontend catchall_http
    bind *:80
    bind *:443 ssl crt MY_CERT
    acl letsencrypt path_beg /.well-known/acme-challenge/
    acl app_ns1 req.hdr(host) -i ns1.example.com
    http-response set-header Strict-Transport-Security max-age=31536000;\ includeSubDomains;\ preload; if { ssl_fc }
    use_backend ns1.home.example.com if app_ns1
    default_backend backend-not-found

Definición del backend de HAProxy

http-request set-header X-Forwarded-Port %[dst_port] está comentado porque probé con y sin.

backend ns1.home.example.com
    acl valid_http_method method GET HEAD POST
    http-request deny unless valid_http_method
    #http-request set-header X-Forwarded-Port %[dst_port]
    redirect scheme https code 301 if !{ ssl_fc }
    server ns1.home.example.com ns1.home.example.com:10000 ssl check check-ssl verify required ca-file CA_CERT

# just to get the initial necessary cookies for login
curl --request GET --cookie-jar webmin_curl_cookies --cookie webmin_curl_cookies https://ns1.example.com/
curl --request POST --data @webmin_request_payload --cookie-jar webmin_curl_cookies --cookie webmin_curl_cookies https://ns1.example.com/session_login.cgi

El resultado es:

Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying HAProxyIP:443...
* Connected to ns1.example.com (HAProxyIP) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=ns1.example.com
*  start date: Aug 14 10:55:38 2020 GMT
*  expire date: Nov 12 10:55:38 2020 GMT
*  subjectAltName: host "ns1.example.com" matched cert's "ns1.example.com"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
> POST /session_login.cgi HTTP/1.1
> Host: ns1.example.com
> User-Agent: curl/7.69.1
> Accept: */*
> Cookie: redirect=1; testing=1; sid=SESS_ID
> Content-Length: 31
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 31 out of 31 bytes
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 302 Moved Temporarily
< Date: Mon, 17 Aug 2020 09:40:48 GMT
< Server: MiniServ/1.953
* Replaced cookie sid="SESS_ID" for domain ns1.example.com, path /, expire 0
< Set-Cookie: sid=SESS_ID; path=/; secure; httpOnly
< Location: https://ns1.example.com:10000/
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
< 
* TLSv1.3 (IN), TLS alert, close notify (256):
* Closing connection 0
* TLSv1.3 (OUT), TLS alert, close notify (256):

Creo que la causa principal del comportamiento no deseado es laUbicaciónencabezado en la respuesta. ¿Cómo puedo resolver este comportamiento?


Propia respuesta a mi pregunta:

En el backend agregar

http-response replace-value Location ^https://ns1.example.com:10000/$ https://ns1.example.com/

y funciona. No sé si esta es una solución de mejores prácticas y definitivamente me gustaría saberlo, pero funciona para mí.

Respuesta1

Respondiendo mi propia pregunta aquí.

Tuve que agregar la siguiente línea al backend.

http-response replace-value Location ^https://ns1.example.com:10000/$ https://ns1.example.com/

información relacionada