1

Trying to redirect certain domain names to specific backends using catchall wildcard entry[A, A1] in haproxy.cfg (HAproxy v1.8.12 Host OS:Alpine Linux v3.9 version details [B] posted at the end in case it has to do with different versions behaving differently[C]):

frontend http
        bind *:80
        reqadd X-Forwarded-Proto:\ http
        redirect scheme https code 301 if !{ ssl_fc }
        ### specific domains ###
        acl host_specificdomain hdr(host) -m reg -i  ^[^\.]+\.specific.domain$
        #Redirect all other domains with all extensions and all ports to:
        acl host_catchall hdr(host) -m reg -i ^[^\.]+\.^[^\.].^[^\.](:[0-9]+)?$
        ### clusters ###
        use_backend specificdomain_cluster if host_specificdomain
        use_backend catchall_cluster if host_catchall

frontend https
        bind       *:443 ssl no-sslv3 crt-list /etc/haproxy/ssl/ssl.lst
        rspadd Strict-Transport-Security:\ max-age=31536000;\ includeSubDomains;\ preload
        rspadd X-Frame-Options:\ DENY
        reqadd X-Forwarded-Proto:\ https
        acl app_letsencrypt  path_beg   /.well-known/acme-challenge/
        use_backend bk-letsencrypt if app_letsencrypt

backend bk-letsencrypt
    log global
    mode http
    server srv_letsencrypt 127.0.0.1:63443

backend catchall_cluster
        redirect scheme https if !{ ssl_fc }
        mode http
        balance roundrobin
        option forwardfor
        server server1 192.168.200.101:80 check
        server server2 192.168.200.102:80 check

backend specificdomain_cluster
        redirect scheme https if !{ ssl_fc }
        mode http
        balance roundrobin
        option forwardfor
        server server1 192.168.200:103:80 check
        server server2 192.168.200.104:80 check 

haproxy stats shows all servers alive, fyi.

The above posed three issues:

  1. The catchall domains option with wildcards (acl host_catchall hdr(host) -m reg -i ^[^.]+.^[^.].^^.?$) did not redirect all but not specific.domain (acl host_specificdomain hdr(host) -m reg -i ^[^.]+.specific.domain$).

  2. Even the specific.domain gives 503 error "service unavailable, no server is available to handle this request" when:

$ curl -v --resolve specific.domain:443:127.0.0.1 https://specific.domain
* Expire in 0 ms for 6 (transfer 0x55c2bc8bc4c0)
* Added specific.domain:443:127.0.0.1 to DNS cache
* Hostname specific.domain was found in DNS cache
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55c2bc8bc4c0)
* Connected to specific.domain (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.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=specific.domain
*  start date: Jun 17 08:00:34 2019 GMT
*  expire date: Sep 15 08:00:34 2019 GMT
*  subjectAltName: host "specific.domain" matched cert's "specific.domain"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: specific.domain
> User-Agent: curl/7.64.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* HTTP 1.0, assume close after body < HTTP/1.0 503 Service Unavailable < Cache-Control: no-cache < Connection: close < Content-Type: text/html <  <html><body><h1>503 Service Unavailable</h1> No server is available to handle this request. </body></html>
* TLSv1.3 (IN), TLS alert, close notify (256):
* Closing connection 0

The same domain was readily available over http as follows:

$ curl -v --resolve specific.domain:80:127.0.0.1 http://specific.domain
* Expire in 0 ms for 6 (transfer 0x55cecf76c4c0)
* Added specific.domain:80:127.0.0.1 to DNS cache
* Hostname specific.domain was found in DNS cache
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55cecf76c4c0)
* Connected to specific.domain (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: specific.domain
> User-Agent: curl/7.64.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx
< Date: Sat, 22 Jun 2019 18:58:31 GMT
< Content-Type: text/html
< Content-Length: 17832
< Last-Modified: Wed, 19 Jun 2019 09:19:57 GMT
< Connection: close
< Vary: Accept-Encoding
< ETag: "5d09fe3d-45a8"
< Accept-Ranges: bytes
< 
<!doctype html>
...
  1. Haproxy fails to pull additional domain certs which were pointed by DNS to the specific IP of the machine:
Failed authorization procedure. www.specific.domain (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://www.specific.domain/.well-known/acme-challenge/APRETTYLONGID [PUBLIC IP]: "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n   \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<ht"

Btw, I am using a script [D] to generate LE certs, fyi.

Any pointers appreciated,

Thanks and cheers, /z

References:

A. https://serverfault.com/a/909483/528889

A1. https://unix.stackexchange.com/questions/166169/how-to-configure-haproxy-to-redirect-multiple-domain

B. HAproxy version details:

 haproxy -vvvvv
HA-Proxy version 1.8.12-8a200c7 2018/06/27
Copyright 2000-2018 Willy Tarreau <willy@haproxy.org>

Build options :
  TARGET  = linux2628
  CPU     = generic
  CC      = gcc
  CFLAGS  = -Os -fomit-frame-pointer
  OPTIONS = USE_ZLIB=1 USE_OPENSSL=1 USE_LUA=1 USE_PCRE=1 USE_NS=1

Default settings :
  maxconn = 2000, bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with OpenSSL version : OpenSSL 1.1.1a  20 Nov 2018
Running on OpenSSL version : OpenSSL 1.1.1b  26 Feb 2019
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with Lua version : Lua 5.3.5
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Encrypted password support via crypt(3): yes
Built with multi-threading support.
Built with PCRE version : 8.42 2018-03-20
Running on PCRE version : 8.42 2018-03-20
PCRE library supports JIT : no (USE_PCRE_JIT not set)
Built with zlib version : 1.2.11
Running on zlib version : 1.2.11
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with network namespace support.

Available polling systems :
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

Available filters :
        [SPOE] spoe
        [COMP] compression
        [TRACE] trace

C. https://superuser.com/questions/1195012/haproxy-1-7-2-refuses-to-match-host-in-acl

D. https://github.com/tisc0/letsHAP

1

First of all, your https frontend lack of backend.

Also, my advice is to use a default backend in your frontends, rather than a complicated regex to catch "all the others domains".

And about acls with regex on host header, I've been more successful with hdr_reg(host) than hdr(host) -m reg -i.

I would propose you another piece of advice: - make things less complex - comment unnecessary options to facilitate troubleshooting

Ah : I'm not sure your regex lines are read in http frontend, since you used the redirect scheme https before : I would say all your request go to https, which has no backend.

Hope it helps.

Cheers,

  • You whacked the mole precisely. Thanks for your invaluable input. – user28163 Jun 23 at 9:01
  • Great, so check it as the right answer ;) – tisc0 Jul 5 at 23:05
0

A backend to the frontend https is appended to the earlier config as of below, yet all traffic is sent to host_catchall server!? Any clues? Thanks!


frontend http
        bind *:80
        reqadd X-Forwarded-Proto:\ http
        redirect scheme https code 301 if !{ ssl_fc }
        ### specific domains ###
        acl host_specificdomain hdr(host) -i subdomain.specific.domain -
        #Redirect all other domains with all extensions and all ports to:
        acl host_catchall hdr(host) -i subdomain.catchall.domain
        ### clusters ###
        use_backend specificdomain_cluster if host_specificdomain
        use_backend catchall_cluster if host_catchall

frontend https
        bind       *:443 ssl no-sslv3 crt-list /etc/haproxy/ssl/ssl.lst
        rspadd Strict-Transport-Security:\ max-age=31536000;\ includeSubDomains;\ preload
        rspadd X-Frame-Options:\ DENY
        reqadd X-Forwarded-Proto:\ https
        acl app_letsencrypt  path_beg   /.well-known/acme-challenge/
        use_backend bk-letsencrypt if app_letsencrypt

        ### specific domains ###
        acl host_specificdomain hdr(host) -i subdomain.specific.domain$
        #Redirect all other domains with all extensions and all ports to:
        acl host_catchall hdr(host) -i subdomain.catchall.domain
        ### clusters ###
        use_backend specificdomain_cluster if host_specificdomain
        use_backend catchall_cluster if host_catchall

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.