How to use absolute path in backend

Hi, I want to configure a HAProxy in front of other 2 load balancers which serve 2 k8s clusters. My issue seems to be the fact that HAProxy tries to use relative paths from backend. I would like to have absolute paths used, so instead of “/” I need https://fqdn/
For example, I have to use this check where an absolute path is set:
option httpchk GET https://as-infra-gtm.unicorn.infra/orchestrator_/api/status HTTP/1.1

using only this relative /orchestrator_/api/status, it doesn’t work.

my haproxy is 1.8
HA-Proxy version 1.8.27-493ce0b 2020/11/06
Copyright 2000-2020 Willy Tarreau willy@haproxy.org

Build options :
TARGET = linux2628
CPU = generic
CC = gcc
CFLAGS = -O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv -Wno-null-dereference -Wno-unused-label -Wno-stringop-overflow
OPTIONS = USE_LINUX_TPROXY=1 USE_CRYPT_H=1 USE_GETADDRINFO=1 USE_ZLIB=1 USE_REGPARM=1 USE_OPENSSL=1 USE_LUA=1 USE_SYSTEMD=1 USE_PCRE=1

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

Built with OpenSSL version : OpenSSL 1.1.1k FIPS 25 Mar 2021
Running on OpenSSL version : OpenSSL 1.1.1k FIPS 25 Mar 2021
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.4
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

And here is my haproxy config:

#---------------------------------------------------------------------

Example configuration for a possible web application. See the

full configuration options online.

https://www.haproxy.org/download/1.8/doc/configuration.txt

#---------------------------------------------------------------------

#---------------------------------------------------------------------

Global settings

#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the ‘-r’ option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2 debug

chroot      /var/lib/haproxy
pidfile     /var/run/haproxy.pid
maxconn     4000
user        haproxy
group       haproxy
daemon

# turn on stats unix socket
stats socket /var/lib/haproxy/stats mode 600 level admin

ca-base     /etc/haproxy/ca
crt-base    /etc/haproxy/crt

ssl-default-bind-options no-sslv3 prefer-client-ciphers

# utilize system-wide crypto-policies

#---------------------------------------------------------------------

common defaults that all the ‘listen’ and ‘backend’ sections will

use if not designated in their block

#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
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
maxconn 3000

#---------------------------------------------------------------------

main frontend which proxys to the backends

#---------------------------------------------------------------------
frontend main
bind *:443 ssl crt /etc/haproxy/all.pem
reqadd X-Forwarded-Proto:\ https
default_backend app
backend app
mode http
balance roundrobin
option httpchk GET https://as-infra-gtm.unicorn.infra/orchestrator_/api/status HTTP/1.1
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }

server as-infra.unicorn.infra 10.10.25.21:443 check check-ssl ssl check-sni as-infra-gtm.unicorn.infra ca-file /etc/haproxy/ca/CACert.crt port 443 ssl-max-ver TLSv1.2
server as-infra2.unicorn.infra 10.10.25.22:443 check check-ssl ssl check-sni as-infra-gtm.unicorn.infra ca-file /etc/haproxy/ca/CACert.crt port 443 ssl-max-ver TLSv1.2

[root@as-haproxy policies]# curl -I --http1.1 -X GET https://as-infra-gtm.unicorn.infra/
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html

[root@as-haproxy policies]# curl -I --http1.1 -X GET https://as-infra-gtm.unicorn.infra/ --resolve as-infra-gtm.unicorn.infra:443:10.10.25.21
HTTP/1.1 200 OK
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
set-cookie: UiPathBrowserId=85a449f1-7025-4f32-b9cc-5ff86b9ba073; Path=/; Expires=Tue, 19 Dec 2023 15:07:22 GMT; HttpOnly
set-cookie: .uipath.sso=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT
surrogate-control: no-store
cache-control: no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0
akamai-cache-control: max-age=0
pragma: no-cache
expires: 0
content-type: text/html; charset=utf-8
content-length: 11146
etag: W/“2b8a-4nQSnxo4G0YG1WNikvn8vMQIZaY”
date: Wed, 28 Dec 2022 15:07:22 GMT
x-envoy-upstream-service-time: 37
server: istio-envoy

In your backend, try adding option httpchk GET https://as-infra-gtm.unicorn.infra/

Source: HAProxy version 1.8.31 - Configuration Manual

Thanks, but I solved the health check issue by adding this line as you can see above:
option httpchk GET https://as-infra-gtm.unicorn.infra/orchestrator_/api/status HTTP/1.1

My issue now is that I cannot make the traffic goes to the backend servers. I need something to replace / from the path with https://as-infra-gtm.unicorn.infra/
I’ve tried this 2 lines, but no luck
http-request set-path https://as-infra-gtm.unicorn.infra/%[path]
http-request set-uri https://as-infra-gtm.unicorn.infra/%[path]?%[query]

Okay, so HAProxy is responding with “503 Service Unavailable” even though the servers are passing healthchecks? Are you certain HAProxy actually sees your backends as up?

Edit: I’d be tempted to remove the check from one or both of your backend servers to see if it responds the same way.

Yes, I get the same error when check is removed. Here is the log, you can see that it tries to reach “/” which is not working for me. It should try “https://as-infra-gtm.unicorn.infra/” , but I don’t know how to add something in front of “/”

00000000:main.accept(0008)=000c from [10.98.1.2:63868] ALPN=
00000000:main.clireq[000c:ffffffff]: GET / HTTP/1.1
00000000:main.clihdr[000c:ffffffff]: Host: as-infra-gtm.unicorn.infra
00000000:main.clihdr[000c:ffffffff]: Connection: keep-alive
00000000:main.clihdr[000c:ffffffff]: sec-ch-ua: “Not?A_Brand”;v=“8”, “Chromium”;v=“108”, “Google Chrome”;v=“108”
00000000:main.clihdr[000c:ffffffff]: sec-ch-ua-mobile: ?0
00000000:main.clihdr[000c:ffffffff]: sec-ch-ua-platform: “Windows”
00000000:main.clihdr[000c:ffffffff]: Upgrade-Insecure-Requests: 1
00000000:main.clihdr[000c:ffffffff]: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
00000000:main.clihdr[000c:ffffffff]: Sec-Purpose: prefetch;prerender
00000000:main.clihdr[000c:ffffffff]: Purpose: prefetch
00000000:main.clihdr[000c:ffffffff]: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
00000000:main.clihdr[000c:ffffffff]: Sec-Fetch-Site: none
00000000:main.clihdr[000c:ffffffff]: Sec-Fetch-Mode: navigate
00000000:main.clihdr[000c:ffffffff]: Sec-Fetch-User: ?1
00000000:main.clihdr[000c:ffffffff]: Sec-Fetch-Dest: document
00000000:main.clihdr[000c:ffffffff]: Accept-Encoding: gzip, deflate, br
00000000:main.clihdr[000c:ffffffff]: Accept-Language: en-US,en;q=0.9
00000000:main.clihdr[000c:ffffffff]: Cookie: UiPathBrowserId=dc16aabc-c5b9-44e5-998f-58aa0fa2311b; ai_user=0WanBAu/Qoi+hFcmZ+NpkW|2022-12-29T13:13:02.542Z; language-k8s=en; PORTAL_LOC_CONTEXT_DATE=1672319690794

Can you rewrite the request before passing it to the backend servers?

backend app
    # Previous configuration
    ...
    # Rewrite the request
    reqrep ^GET\ /(.*) GET\ https://as-infra-gtm.unicorn.infra/\1
    # Continued config
    server as-infra.unicorn.infra 10.10.25.21:443 check...
    server as-infra2.unicorn.infra 10.10.25.22:443 check...

Source: HAProxy version 1.8.31 - Configuration Manual - reqrep

Note: In newer versions of HAProxy, reqrep is not supported. For this, you would use something like

    http-request replace-uri ^/(.*) https://as-infra-gtm.unicorn.infra/\1

Source: HAProxy version 2.6.7-5 - Configuration Manual - http-request replace-uri

It seems that for some reason haproxy doesn’t send the backend requests to my servers. I’ve captured the traffic using tcpdump and I can see the https check and response (200), but no more packets after that.

That sounds like a configuration issue. Double-check your config and make sure there’s no ACL in place that would prevent it from ever using the backend. Your original config looks solid, but I only see one backend server showing “L7OK”, but the original had 2 backend servers. Perhaps something has changed.

Another recommendation: 1.8 is a bit old and is only getting critical fixes. Your version is 1.8.27 but the latest is 1.8.31. If you can’t upgrade to the latest LTS release (2.6.7), maybe try upgrading to 1.8.31?

If you decide to upgrade to 2.2+, please note that reqrep and several commands like it were deprecated in favor of http-request <action>.

Yep, you’re right, I’ve removed one server from the original config.

I have a rhel 8.7 and this is the latest version I could install using yum. Do you know if it’s possible to install latest ha proxy on rhel ?

I’m would think it’s possible, but I wouldn’t have exact instructions. I’m running 2.6.6 that I built on Debian 11 (I wanted to experiment with QUIC), and that wasn’t too bad beyond reading a lot of instructions about build options. If you’re feeling adventurous, you could always go for building it on the machine.