Skip to main content
Version: v44

Example Load Balancer Configuration: HAProxy

You can use HAProxy as a load balancer in PrivX high availability (HA) deployments. This article provides an example configuration for an HAProxy load balancer running on Rocky Linux 9.

Preparing HAProxy Host

Before applying the example configuration, make sure the HAProxy host has the required SELinux policy, firewall rules, session-affinity settings, and TLS files.

tip

For more information on ports and protocols, see Load Balancer Ports and Protocols.

  1. Configure SELinux to allow HAProxy to listen the required ports by running the following commands:

    semanage port -a -t http_port_t -p tcp 1080 # Native SSH proxy
    semanage port -a -t http_port_t -p tcp 2222 # Native SSH
    semanage port -a -t http_port_t -p tcp 2322 # Extender service
    semanage port -a -t http_port_t -p tcp 3389 # Native RDP
    semanage port -a -t http_port_t -p tcp 20080 # API proxy
    note

    Ports 80 (HTTP), 443 (HTTPS), and 8443 (for client-certificate authentication) should be allowed by default.

  2. Run the following commands to open firewall ports for incoming connections:

    firewall-cmd --zone=public --permanent --add-service=http
    firewall-cmd --zone=public --permanent --add-service=https
    firewall-cmd --zone=public --permanent --add-port=1080/tcp # Native SSH proxy
    firewall-cmd --zone=public --permanent --add-port=2222/tcp # Native SSH
    firewall-cmd --zone=public --permanent --add-port=2322/tcp # Extender service
    firewall-cmd --zone=public --permanent --add-port=3389/tcp # Native RDP
    firewall-cmd --zone=public --permanent --add-port=8443/tcp # Client certificate authentication
    firewall-cmd --zone=public --permanent --add-port=20080/tcp # API proxy
    firewall-cmd --reload
  3. Configure the load balancer to keep HTTPS sessions and API proxy TCP connections from the same client on the same PrivX node. Use cookie-based affinity for HTTPS traffic on port 443 and client IP-based affinity for API proxy TCP connections on port 20080. This example configuration uses the route cookie for HTTPS traffic and source IP-based balancing for the API proxy backend.

  4. Install the TLS certificate and private key at the following paths:

    • /etc/ssl/certs/privx-lb.crt
    • /etc/ssl/certs/privx-lb.crt.key
  5. After installing HAProxy, set the configuration to /etc/haproxy/haproxy.cfg to satisfy all the load balancer requirements described in PrivX High-Availability Deployment.

  6. Reload the HAProxy configuration:

    # systemctl reload haproxy

Example Configuration

The following configuration has been tested on Rocky Linux 9.5 with HAProxy 2.4.

note

Replace 192.0.2.100 and 192.0.2.101 with the IP addresses of your PrivX Servers.

# HAProxy load balancer example configuration.
# Requests are distributed between servers using sticky sessions.
# In this example two instances of PrivX are running
# with private IP addresses 192.0.2.100 and 192.0.2.101
# HTTP requests except for CRLs are redirected to HTTPS.
#
# See the full configuration options online.
#
# https://www.haproxy.org/download/2.4/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to add the following to /etc/rsyslog.d/99-haproxy.conf:

# $AddUnixListenSocket /var/lib/haproxy/dev/log
# # Send HAProxy messages to a dedicated logfile
# :programname, startswith, "haproxy" {
# /var/log/haproxy.log
# stop
# }

log /dev/log/ local0

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

# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
log global
option dontlognull
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

# Windows smartcard CRL and web traffic redirect port
frontend privx_lb_http
bind *:80
mode http


option httplog
option http-server-close
option forwardfor except 127.0.0.0/8

default_backend privx_http

# PrivX https port
# Needs to be 'mode http' for PrivX components
frontend privx_lb_https
bind *:443 ssl crt /etc/ssl/certs/privx-lb.crt ssl-min-ver TLSv1.3
mode http

option httplog
option http-server-close
option forwardfor except 127.0.0.0/8

default_backend privx_https

# Native clients and certificate authentication
# 'mode tcp' required for native protocol traffic
frontend privx_lb_native_ssh
bind *:2222
mode tcp

option tcplog

default_backend privx_native_ssh

frontend privx_lb_native_rdp
bind *:3389
mode tcp

option tcplog

default_backend privx_native_rdp

frontend privx_lb_client_certificate_auth
bind *:8443
mode tcp

option tcplog

default_backend privx_client_certificate_auth

frontend privx_lb_native_ssh_proxy
bind *:1080
mode tcp

option tcplog

default_backend privx_native_ssh_proxy

frontend privx_lb_extender_service
bind *:2322
mode tcp

option tcplog

default_backend privx_extender_service

frontend privx_lb_api_proxy
bind *:20080
mode tcp

option tcplog

timeout client 8h

default_backend privx_api_proxy

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------

# Windows smart-card CRL endpoint and url redirection http -> https
backend privx_http
mode http

option httpchk GET /authorizer/api/v1/cas

balance roundrobin
server node1 192.0.2.100:80
server node2 192.0.2.101:80

backend privx_https
mode http

# Health check PrivX instance endpoint.
option httpchk GET /monitor-service/api/v1/instance/status
log global

# 'balance roundrobin' is required by PrivX components
balance roundrobin

# Sticky sessions are required by PrivX components.
# Setting the affinity cookie name to 'route', so no additional cookie configuration needed for PrivX components config files.
cookie route insert indirect nocache

# Backend SSL cert not verified, you should consider using 'verify required' in production environments.
server node1 192.0.2.100:443 check inter 30s ssl verify none cookie node1
server node2 192.0.2.101:443 check inter 30s ssl verify none cookie node2

# Native client traffic can use whatever load balancing, using roundrobin in this example.
backend privx_native_ssh
mode tcp

stick-table type ip size 1m expire 8h
stick on src
balance roundrobin

server node1 192.0.2.100:2222 check inter 30s
server node2 192.0.2.101:2222 check inter 30s

backend privx_native_rdp
mode tcp

stick-table type ip size 1m expire 8h
stick on src
balance roundrobin

server node1 192.0.2.100:3389 check inter 30s
server node2 192.0.2.101:3389 check inter 30s

backend privx_client_certificate_auth
mode tcp

stick-table type ip size 1m expire 8h
stick on src
balance roundrobin

server node1 192.0.2.100:8443 check inter 30s
server node2 192.0.2.101:8443 check inter 30s

backend privx_native_ssh_proxy
mode tcp

stick-table type ip size 1m expire 8h
stick on src
balance roundrobin

server node1 192.0.2.100:1080 check inter 30s
server node2 192.0.2.101:1080 check inter 30s

backend privx_extender_service
mode tcp

balance roundrobin

server node1 192.0.2.100:2322 check inter 5s
server node2 192.0.2.101:2322 check inter 5s

backend privx_api_proxy
mode tcp

balance source

timeout server 8h

server node1 192.0.2.100:20080 check inter 5s send-proxy-v2
server node2 192.0.2.101:20080 check inter 5s send-proxy-v2

Known Issues

PrivX supports the PROXY protocol for API proxy traffic. When the PROXY protocol is enabled, PrivX can detect the client IP address through a TCP load balancer. This does not apply to native SSH and RDP service traffic:

  • When a user connects to a host with a native SSH or RDP client instead of the PrivX web UI, PrivX audit logs record the load balancer IP address instead of the client IP address.
  • As a result, PrivX cannot detect the original client IP address for native SSH or RDP connections that pass through a TCP load balancer.

There is currently no workaround for this limitation.