HAProxy community

Windows Server 2019 AD FS problems

Hi!

I’m struggling with HAProxy and ADFS in SSL offloading mode.

I already followed this advice:
https://hochwald.net/microsoft-ad-fs-behind-load-balancer/

As well as:

My setup still shows all servers as down. I’m using HAProxy 2.0.13.

If I set the IP of my ADFS host in my hosts file with the SSO-Domain as host, I can view “https://sso.srvfarm.net/adfs/ls/idpinitiatedsignon.aspx” and get http 200 in Chrome (computer in same network).

My config:

global
	log /dev/log local0
	log /dev/log local1 notice
	chroot /var/lib/haproxy
	stats socket /run/haproxy/admin.sock mode 660 level admin
	stats timeout 30s
	user haproxy
	group haproxy
	daemon
	maxconn 40000
	ulimit-n 81000
	# Default ciphers to use on SSL-enabled listening sockets.
	ssl-default-bind-ciphers EECDH+AESGCM:EDH+AESGCM
	ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
	ssl-default-server-ciphers EECDH+AESGCM:EDH+AESGCM
	ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
	tune.ssl.default-dh-param 2048

defaults
	log global
	mode http
	option dontlognull
	option tcplog
	option redispatch
	option contstats
	option http-use-htx
	option forwardfor except 127.0.0.0/8
	maxconn 50000
	balance roundrobin
	timeout connect 10s
	timeout queue 1m
	timeout client 15m
	timeout server 15m
	timeout http-request 10s
	timeout http-keep-alive 10s
	timeout check 10s
	default-server inter 3s rise 2 fall 3
	backlog 10000

# START WebAccess
frontend WebAccess
	maxconn 50000
	bind :::80 v4v6
	bind :::443 v4v6 ssl crt /etc/haproxy/fullchain.pem curves X25519:secp521r1:secp384r1:prime256v1 ciphers EECDH+AESGCM:EDH+AESGCM no-sslv3 no-tlsv10 no-tlsv11 alpn h2
	mode http
	option httplog
	log global
	no option httpclose

	redirect scheme https code 301 if !{ ssl_fc } # redirect 80 -> 443

	http-response add-header Strict-Transport-Security max-age=31536000;\ includeSubDomains;\ preload
	http-response add-header X-Frame-Options sameorigin
	http-response add-header X-Content-Type-Options nosniff
	
	http-request set-header X-MS-Forwarded-Client-IP %[src]

	acl acme-challenge path_beg /.well-known/acme-challenge/
	
	use_backend AcmeForward if acme-challenge

	default_backend ADFSWeb

backend AcmeForward
	mode http
	balance roundrobin
	option httpchk GET /
	option log-health-checks
	http-check expect status 200
	server app01 185.118.197.130:80 check port 80

backend ADFSWeb
	mode http
	balance roundrobin
	option httpchk GET /adfs/ls/idpinitiatedsignon.aspx
	http-check expect status 200
	option httpclose
	option forwardfor header X-Client
	reqadd X-Forwarded-Proto:\ https if { ssl_fc }
	server swde5721 192.168.127.1:443 ssl verify none check check-sni sso.srvfarm.net sni str(sso.srvfarm.net) inter 3s rise 2 fall 3
	server swde5821 192.168.128.1:443 ssl verify none check check-sni sso.srvfarm.net sni str(sso.srvfarm.net) inter 3s rise 2 fall 3

# END WebAccess

userlist UsersFor_HAProxyStatistics
	group admin users admin
	user admin insecure-password redacted
	user stats insecure-password redacted

listen stats
	bind :::7000
	stats enable
	stats uri /
	option httpclose
	acl AuthOkay_ReadOnly http_auth(UsersFor_HAProxyStatistics)
	acl AuthOkay_Admin http_auth_group(UsersFor_HAProxyStatistics) admin
	stats http-request auth realm HAProxy-Statistics unless AuthOkay_ReadOnly
	stats admin if AuthOkay_Admin
	stats show-node
	stats show-legends

I don’t understand whats going wrong here. IMHO “check check-sni sso.srvfarm.net” should be the trick here but the servers still show “Layer7 wrong status: HTTP status check returned code <400>” (same when accessing it via IP instead).

Any ideas?

Thank you!

I’ve moved to using “/FederationMetadata/2007-06/FederationMetadata.xml” as check url. That works perfectly fine. Server is up, if I stop the service it gets marked as down and vice versa.

Works!

1 Like

Presumably your backend did not like the missing Host header in the health check, which would look like this:

option httpchk GET /adfs/ls/idpinitiatedsignon.aspx HTTP/1.1\r\nHost:\ sso.srvfarm.net
1 Like

I thought I tested this by setting “http-request set-header Host sso.srvfarm.net”.
Does http check ignore backend settings like this?

Correct, none of the other options impact http checks, so when you want to send a Host header in a health check, you need to specify it like mentioned above.