HAProxy community

HAProxy select server based on url path not working

i have a working configuration (HA-Proxy version 1.8.8-1ubuntu0.4 2019/01/24) and i’ve been trying every conceivable technique to use the path after the domain to select a specific server e.g.
foobar-nd-ha.ddns.net/ha -> 192.168.1.123:19999
foobar-nd-ha.ddns.net/pihole -> 192.168.5.2:19999
foobar-nd-ha.ddns.net/unifi -> 192.168.1.16:19999
i need to remove the path as the server doesn’t recognise it using reqrep ^([^\ ]\ /)ha[/]?(.) \1\2 then using use-server to the select the correct server which fails with 503 Service Unavailable due to some lack of understand of the inner workings of haproxy… the backend that isn’t work is called backend “backend-nd”

below is my cfg and trace … any help is appreciated

haproxy

SCCS: @(#)haproxy.cfg 1.5 06/01/19

global
maxconn 100
daemon
tune.ssl.default-dh-param 2048
defaults
mode http
log global
# option tcplog
# option httplog
# option logasap
option http-keep-alive
timeout connect 5000
timeout client 50000
timeout server 50000
timeout tunnel 1h

listen stats
bind 192.168.1.235:9000
mode http
log global
maxconn 10
stats enable
stats hide-version
stats refresh 30s
stats show-node
# stats auth admin:password
stats uri /haproxy?stats

frontend https
bind *:443
mode tcp
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use_backend openvpn-backend if { req.ssl_sni -i foobar.ddns.net }
default_backend https-back

frontend https-front
bind unix@/var/run/haproxy.sock ssl crt /etc/letsencrypt/live/foobar.ddns.net/haproxy.pem accept-proxy
mode http
use_backend home-assistant-backend if { ssl_fc_sni -i foobar-ha.ddns.net }
use_backend nextcloud-backend if { ssl_fc_sni -i foobar-nc.ddns.net }
use_backend genmon-backend if { ssl_fc_sni -i foobar-genmon.ddns.net }
use_backend blueiris-backend if { ssl_fc_sni -i foobar-bi.ddns.net }
use_backend pihole-backend if { ssl_fc_sni -i foobar-dns.ddns.net }
use_backend unifi-backend if { ssl_fc_sni -i foobar-unifi.ddns.net }
use_backend unms-backend if { ssl_fc_sni -i foobar-unms.ddns.net }
use_backend haproxy-backend if { ssl_fc_sni -i foobar-haproxy.ddns.net }

# Netdata
use_backend backend-nd if { ssl_fc_sni -i foobar-nd-ha.ddns.net }

frontend http
bind *:80 
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl

backend letsencrypt-backend
server letsencrypt 127.0.0.1:8888

backend https-back
mode tcp
server https-front unix@/var/run/haproxy.sock send-proxy-v2

# Openvpn
backend openvpn-backend
mode tcp
timeout server 2h
server openvpn 192.168.1.235:444

# Netdata backend
backend backend-nd
mode http
http-request set-var(txn.server) path
reqrep ^([^\ ]*\ /)ha[/]?(.*) \1\2
reqrep ^([^\ ]*\ /)pihole[/]?(.*) \1\2
reqrep ^([^\ ]*\ /)unifi[/]?(.*) \1\2

use-server ha if { path_beg -i var(txn.server) /ha }
use-server pihole if { path_beg -i var(txn.server) /pihole }
use-server unifi if { path_beg -i var(txn.server) /unifi }

server ha 192.168.1.123:19999 check weight 0
server pihole 192.168.5.2:19999 check weight 0
server unifi 192.168.1.16:19999 check weight 0

# Haproxy Stats
backend haproxy-backend
mode http
server haproxy 192.168.1.235:9000 no-ssl check
http-request redirect location /haproxy?stats if { path / } 
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }

# Pi-hole DNS Ad-blocker
backend pihole-backend
mode http
server pi-hole 192.168.5.2:80 check no-ssl
rspadd X-Frame-Options:\ SAMEORIGIN
http-request redirect location /admin/ if { path / }
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }

# Genmon
backend genmon-backend
mode http
server unifi 192.168.1.198:8000 no-ssl check
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }

# Unifi 
backend unifi-backend
mode http
server unifi 192.168.1.16:8443 ssl verify none check
http-request redirect location /manage/site/kab9w4dv/dashboard if { path / } 
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }

# UNMS
backend unms-backend
mode http
server unms 192.168.1.207 ssl verify none
http-request redirect location /dashboard if { path / } 
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }

# Home Assistant
backend home-assistant-backend
mode http
server home-assistant 192.168.1.123:8123 check
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }

# Nextcloud
backend nextcloud-backend
mode http
server nextcloud 192.168.1.123:80 check
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }

# Blue Iris Security Server
backend blueiris-backend
mode http
server blueiris 192.168.1.36:1050 check
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc } 

---------------- trace
Available filters :

[SPOE] spoe
[COMP] compression
[TRACE] trace
Using epoll() as the polling mechanism.
00000000:https.accept(0005)=000a from [192.168.1.1:59162] ALPN=
00000001:https.accept(0005)=000d from [192.168.1.1:59163] ALPN=
00000002:https-front.accept(0006)=000c from [192.168.1.1:59162] ALPN=
00000003:https-front.accept(0006)=000f from [192.168.1.1:59163] ALPN=
00000002:https-front.clireq[000c:ffffffff]: GET /ha HTTP/1.1
00000002:https-front.clihdr[000c:ffffffff]: Host: foobar-nd-ha.ddns.net
00000002:https-front.clihdr[000c:ffffffff]: Connection: keep-alive
00000002:https-front.clihdr[000c:ffffffff]: Upgrade-Insecure-Requests: 1
00000002:https-front.clihdr[000c:ffffffff]: User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
00000002:https-front.clihdr[000c:ffffffff]: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3
00000002:https-front.clihdr[000c:ffffffff]: Purpose: prefetch
00000002:https-front.clihdr[000c:ffffffff]: Accept-Encoding: gzip, deflate, br
00000002:https-front.clihdr[000c:ffffffff]: Accept-Language: en-US,en;q=0.9
00000002:https-front.clihdr[000c:ffffffff]: Cookie: _ga=GA1.3.592449160.1559126922; _gid=GA1.3.690682874.1559491313
00000002:backend-nd.clicls[adfd:ffffffff]
00000002:backend-nd.closed[adfd:ffffffff]
00000000:https-back.srvcls[adfd:adfd]
00000000:https-back.clicls[adfd:adfd]
00000000:https-back.closed[adfd:adfd]
00000004:https.accept(0005)=000a from [192.168.1.1:59166] ALPN=
00000005:https-front.accept(0006)=000c from [192.168.1.1:59166] ALPN=
00000003:https-front.clireq[000f:ffffffff]: GET /favicon.ico HTTP/1.1
00000003:https-front.clihdr[000f:ffffffff]: Host: foobar-nd-ha.ddns.net
00000003:https-front.clihdr[000f:ffffffff]: Connection: keep-alive
00000003:https-front.clihdr[000f:ffffffff]: User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
00000003:https-front.clihdr[000f:ffffffff]: Accept: image/webp,image/apng,image/,/*;q=0.8
00000003:https-front.clihdr[000f:ffffffff]: Referer: https://foobar-nd-ha.ddns.net/ha
00000003:https-front.clihdr[000f:ffffffff]: Accept-Encoding: gzip, deflate, br
00000003:https-front.clihdr[000f:ffffffff]: Accept-Language: en-US,en;q=0.9
00000003:https-front.clihdr[000f:ffffffff]: Cookie: _ga=GA1.3.592449160.1559126922; _gid=GA1.3.690682874.1559491313
00000003:backend-nd.clicls[adfd:ffffffff]
00000003:backend-nd.closed[adfd:ffffffff]
00000001:https-back.srvcls[adfd:adfd]
00000001:https-back.clicls[adfd:adfd]
00000001:https-back.closed[adfd:adfd]

Forget it, this is a terrible idea.

Who well rewrite the internal links in the html page that point to the wrong URL? Haproxy certainly will not.

Use different hostnames so you can route based on the Host header.

Thanks that’s what I’m doing now … I thought there was a way to use one domain vs the ten addition

Hello,

You need to define an acl :

acl your-acl-name path_beg /url/path

and then

 use_backend your-backend if your-acl-name