How to Load balance multiple UCS portal servers

Scenario

You have multiple UCS portal servers, and one server with haproxy installed and you want to balance the connections to the portal servers.

TL;DR

The UCS Portal is a normal dynamic website, that is accessible with both http and https. To place multiple Portalservers behind a loadbalancer, we recommend to provide the SSL certificate

/etc/univention/ssl//$FQDN/cert.pem

and the corresponding private key

/etc/univention/ssl/$FQDN/private.key

to the loadbalancer and decrypt the traffic. Attach a cookie in order to route packages of concurrent sessions to the same portal server. Note that the default UCS certificate is self signed and might not be accepted unless specifically allowed.

Recommendation

In this article we will focus on HAProxy as the loadbalancer because we have made good experiences with it, but the principles will likely also work for other products. Every scenario is different and the steps described here might not be optimal for yours. This is only meant as an example.

The UCS portal is basically just a website that is being hosted per default on the standard http (80) and https (443) ports.

We can use haproxy to direct users to either portal server. As a loadbalancing method we use “least connected” (leastconn) because we expect long lived connections of varying size and “least connected” trys to balance the amount of concurrent connections on either side.

The site is not static and user will login to sessions. If we were to direct each request or package randomly users with running sessions would have to login again when they are directed to another portal than before. In order to make the loadbalancer aware of this we want to save a cookie and configure haproxy to always direct users to the same portal if the cookie stays the same.

backend portalbackend_http
  ...
  cookie SERVERUSED insert indirect nocache
  server por1 10.200.50.21:80 cookie por1
  server por2 10.200.50.22:80 cookie por2

backend portalbackend_https
  ...
  cookie SERVERUSED insert indirect nocache
  server por1 10.200.50.21:443 cookie por1 ssl verify none 
  server por2 10.200.50.22:443 cookie por2 ssl verify none

If https is used the packages are encrypted with the certificate of UCS. In order to save a cookie to a session haproxy needs to be aware of more than just the tcp packages. For this it needs to be able to decrypt the package stream. We need to provide haproxy with a copy of this certificate in order for it to do this.

frontend portalfrontend_https
  bind 10.200.50.21:10443 ssl crt /etc/univention/ssl/ucs01.ucs-test.intranet/ucs01.pem
  ...

haproxy expects both the private.key and the public certificate to be in one file. UCS however saves them separately. We have to create the combination with

cat /etc/univention/ssl/ucs01.ucs-test.intranet/cert.pem /etc/univention/ssl/ucs01.ucs-test.intranet/private.key > /etc/univention/ssl/ucs01.ucs-test.intranet/ucs01.pem

Lastly we can tell haproxy to encrypt the packages again for delivery to the UCS portal servers.

backend portalbackend_https
  ...
  server por1 10.200.50.21:443 cookie por1 ssl verify none 
  server por2 10.200.50.22:443 cookie por2 ssl verify none

All together we get a configuration file like:

global
	log /dev/log	local0
	log /dev/log	local1 notice
	chroot /var/lib/haproxy
	stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
	stats timeout 30s
	user haproxy
	group haproxy
	daemon

	# Default SSL material locations
	ca-base /etc/ssl/certs
	crt-base /etc/ssl/private

	# Default ciphers to use on SSL-enabled listening sockets.
	# For more information, see ciphers(1SSL). This list is from:
	#  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
	# An alternative list with additional directives can be obtained from
	#  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
	ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
	ssl-default-bind-options no-sslv3

defaults
	log	global
	mode	http
	option	httplog
	option	dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
	errorfile 400 /etc/haproxy/errors/400.http
	errorfile 403 /etc/haproxy/errors/403.http
	errorfile 408 /etc/haproxy/errors/408.http
	errorfile 500 /etc/haproxy/errors/500.http
	errorfile 502 /etc/haproxy/errors/502.http
	errorfile 503 /etc/haproxy/errors/503.http
	errorfile 504 /etc/haproxy/errors/504.http

frontend portalfrontend_http
  bind 10.200.50.21:10080
  mode http
  default_backend portalbackend_http

backend portalbackend_http
  mode http
  balance leastconn
  default-server check maxconn 200
  cookie SERVERUSED insert indirect nocache
  server por1 10.200.50.21:80 cookie por1
  server por2 10.200.50.22:80 cookie por2

frontend portalfrontend_https
  bind 10.200.50.21:10443 ssl crt /etc/univention/ssl/ucs01.ucs-test.intranet/ucs01.pem
  mode http
  default_backend portalbackend_https

backend portalbackend_https
  mode http
  balance leastconn
  default-server check maxconn 200
  cookie SERVERUSED insert indirect nocache
  server por1 10.200.50.21:443 cookie por1 ssl verify none 
  server por2 10.200.50.22:443 cookie por2 ssl verify none

Further Reading

Questions?

If you’re not sure whether the recommendations will fit into your scenario, please ask your Professional Services contact person, or create a new topic referencing this article.

3 Likes
Mastodon