HAProxy is an open-source software capable of processing Layer 4 and Layer 7 traffic. It supports high-availability, load-balancing, and proxying traffic to one or more backend servers.

Installation

Requirements

HAProxy can be installed and run on any platform that HAProxy supports. In this article we focus on the installation of HAProxy on centOS and RHEL.

If possible, install HAProxy on a dedicated server for security and performance reasons. However, you can also install it on the same server where a censhare Server is running. In this case, make sure that the following ports are not in use so that HAProxy can bind to them:

  • 80  - Plain HTTP. It is redirects to port 443.

  • 443  - Default HTTPs port.

  • 30546  - By default, censhare RMI uses port 30546. Therefore, when running HAProxy on a dedicated server, we recommend to use port 30546 here as well. However, when running HAProxy on the same machine as a censhare Server, for example the Master server, use another port such as 30545. Also, ensure that your hosts.xml contains the correct port defined to use with HAProxy.

  • 8080  - HAProxy statistics.

How to verify that the ports are available:

ss -tulnp | egrep '80|443|30546|8080'


Installation command

To install HAProxy on centos 7 and RHEL 7 and later versions, install the package from the distribution repository. Run the following command:

yum install haproxy

Configuration

Note : For a complete guide how to configure HAProxy, see the   Configuration Manual   for the Community Edition.

Find an example of a configuration file for HAProxy that you can use for load-balancing and high-availability for censhare. The configuration file defines an environment with two censhare Servers, one of them as the Master server.

First, identify the appropriate custom values for your environment for the following items. Then adapt the example configuration file:

  1. If the application has a custom context path that is different from the default  /censhare5/client, check all entries of  /censhare5/client  in the configuration file. Replace the entries with the appropriate context path. For example, if the base URL is:

    https://customer.example.com/censhareapp 

    The custom context path is   censhareapp . Then, set the   http-request redirect   line in the configuration file:

    http-request redirect code 301 location https://%[hdr(host)]/censhareapp
  2. Upload a PEM-formatted SSL certificate file to the server. This file should contain both the private key and the certificate chain bundle. This means: When a certificate is signed by an intermediate certificate authority (CA), also include the certificate of the intermediate CA in addition to the actual certificate.

    Example of a PEM-format certificate:

    -----BEGIN ENCRYPTED PRIVATE KEY-----
    MBQGCCqGSIb3DQMHBAgD1kGN4ZslJgSCBMi1xk9jhlPxPc
    9g73NQbtqZwI+9X5OhpSg/2ALxlCCjbqvzgSu8gfFZ4yo+
    A .... MANY LINES LIKE THAT .... 
    X0R+meOaudPTBxoSgCCM51poFgaqt4l6VlTN4FRpj+c/Wc 
    blK948UAda/bWVmZjXfY4Tztah0CuqlAldOQBzu8TwE7WD 
    H0ga/iLNvWYexG7FHLRiq5hTj0g9mUPEbeTXuPtOkTEb/0
    GEs=
    -----END ENCRYPTED PRIVATE KEY-----
    -----BEGIN CERTIFICATE-----
    MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiIMA0GCSqGSIb3Df
    BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVx 
    aWRnaXRzIFB0eSBMdGQwHhcNMTExMjMxMDg1OTQ0WhcNMT
    A .... MANY LINES LIKE THAT ....
    JjyzfN746vaInA1KxYEeI1Rx5KXY8zIdj6a7hhphpj2E04 
    C3Fayua4D
    RHyZOLmlvQ6tIChY0ClXXuefbmVSDeUHwc8Yu B7xxt8BVc69rLe
    HV15A0qyx77CLSj3tCx2IUXVqRs5mlSbvA==
    -----END CERTIFICATE-----
    -----BEGIN CERTIFICATE-----
    MIIElDCCA3ygAwIBAgIQAf2j627KdciIQ4tyS8+8kTANBgkqhkiG9w0
    BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA
    1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
    A .... MANY LINES LIKE THAT ....
    YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj
    CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
    -----END CERTIFICATE-----


    Additionally, for security reasons, the PEM-format certificate file and the directory where the file is located should not be readable by non-root users. For example:

    drwxrw----. 2 root root 26 Apr 23 15:38 
    /etc/haproxy/ssl -r-------- 1 root root 7086 Mar 6 12:08 
    /etc/haproxy/ssl/certificatefile.pem
  3. censhare Server IP addresses or domain/host names and HTTPs ports: In the configuration example below, the servers are:

    cust-prodns-css01 port 9443 
    cust-prodns-css02 port 9443
  4. censhare Server IP addresses or domain/host names and RMI ports: In the configuration example below, the servers are

    cust-prodns-css01 port 30546 
    cust-prodns-css02 port 30545

Here is the complete /etc/haproxy/haproxy.cfg example which includes the items discussed above:

global
    log         127.0.0.1:514  local0  info
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon    tune.ssl.default-dh-param   2048
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 
    no-tls-tickets
    ssl-default-bind-ciphers  ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:
ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
defaults
    log     global
    mode    http
    balance leastconn
    #option  tcplog
    log-format {"type":"haproxy","request_id":"%rt","timestamp":%Ts,"http_status":%ST,
   "http_request":"%r",
    "remote_addr":"%ci/%cp","bytes_read":%B,"upstream_addr":"%si","bytes_uploaded":%U,
    "upstream_response_time":"%Tr","session_duration":"%Tt"}
    option  dontlognull
    option  redispatch
    option  log-health-checks
    retries 3
    maxconn 2000
    timeout connect  60000
    timeout client   60000
    timeout server   60000
    default-server inter 10s


###################### RMI Protocol Start ######################
frontend rmi30545-in
        mode tcp
        bind *:30545
        #option tcplog
        #option http-server-close
        default_backend rmi30546-out

backend rmi30545-out
        mode tcp
        stick-table type ip size 1m expire 30m
        stick on src
        balance leastconn
        default-server inter 1s downinter 3s rise 15 fall 15

        server cust-prodns-css01 cust-prodns-css01:30546 check
        server cust-prodns-css02 cust-prodns-css02:30546 check

###################### RMI Protocol Finish ######################

 
###################### HTTP/S Protocol Start ######################
frontend web80-in *:80
   http-request redirect code 301 location https://%[hdr(host)]/censhare5/client

frontend web443-in
    mode http
    bind *:443 ssl crt /etc/haproxy/ssl/certificatefile.pem
    default_backend web443-out
    option forwardfor

    timeout client          60m
    timeout http-keep-alive 10s    timeout http-request    5s
    timeout tarpit          60s

    acl is_websocket path_beg /censhare5/client/
    acl is_websocket hdr(Upgrade) -i WebSocket
    acl is_websocket hdr_beg(Host) -i ws

    acl is_root path /

    capture request  header Host len 64
    http-request redirect scheme https code 301 if !{ ssl_fc }
    http-request redirect code 301 location https://%[hdr(host)]/censhare5/client
    if is_root

backend web443-out
    cookie SRVID insert indirect nocache maxidle 30m maxlife 1h
    option forwardfor
    balance leastconn

    option ssl-hello-chk

    option httpchk GET /censhare5/client/img/favicon.ico
    http-check expect status 200
    default-server inter 1s downinter 3s rise 15 fall 15
    timeout check 1s

    timeout server          60m
    timeout tunnel        3600s
    timeout queue           30s
    timeout connect          5s
    #option http-server-close  # KRED es muss disabled

    http-request add-header X-Forwarded-Proto https if { ssl_fc }

    redirect scheme https if !{ ssl_fc }

    http-response add-header Strict-Transport-Security max-age=31536000;\ includeSubdomains
    http-response add-header X-Content-Type-Options nosniff
    http-response add-header X-XSS-Protection 1;\ mode=block
    http-response add-header Referrer-Policy no-referrer
    http-response add-header Feature-Policy accelerometer\ 'none';\ 
       ambient-light-sensor\ 'none';\ autoplay\ 'none';\ camera\ 'none';\ 
       display-capture\ 'none';\ document-domain\ 'none';\ fullscreen\ 'none';\ 
       execution-while-not-rendered\ 'none';\ execution-while-out-of-viewport\ 'none';\ 
       gyroscope\ 'none';\ magnetometer\ 'none';\ microphone\ 'none';\ midi\ 'none';\
      payment\'none';\ picture-in-picture\ 'none';\ publickey-credentials\ 'none';\ sync-xhr\
     'none';\ usb\'none';\ wake-lock\ 'none'

    server cust-prodns-css01 cust-prodns-css01:9443 weight 5 check ssl verify none cookie s1
    server cust-prodns-css01 cust-prodns-css01:9443 weight 5 check ssl verify none cookie s2

###################### HTTP/S Protocol Finish ######################


###################### Statistics ######################
frontend statistics-8000
  bind *:8000
  mode http
  #option  httplog  # not needed !!!
  stats enable
  stats uri /haproxy
  stats auth admin:password
  stats admin if TRUE
###################### Statistics Finish ######################
  

Validate the configuration file:

haproxy -f /etc/haproxy/haproxy.cfg -c

Fix any issues, then start HAProxy and make sure that it starts on server reboot:

systemctl enable haproxy && systemctl start haproxy

Redirects for censhare WP

If you use censhare WP with a load balancer, such as NGINX or HAProxy, set the following redirects:

/tempDownload/ should be routed from the proxy directly to the censhare Server. As it does not have a separate mapping in the Cloud Gateway setup and does not use the usual login session.

Details and options

The following section contains details and explanations about the haproxy.cfg configuration file. Keep these configuration options, and customize them only if you are certain of the implications of the changes!

Load-balancing algorithms

HAProxy supports a number of load-balancing algorithms to determine how to distribute traffic to multiple backend servers.

The algorithm used above for HTTPs is  leastconn:  The backend server with the least number of connections is used, and then for all servers with the same amount of connections, round-robin is performed. The configuration entry:

balance leastconn


Currently, RMI cannot handle  leastconn.   Hence, sessions must be sent to the same backend server and being tracked by the client IP addresses. The configuration entry:

stick-table type ip size 1m expire 30m stick on src


Other algorithms are  roundrobin   or   static-rr . For more information on all supported load-balancing algorithms, see the   HAProxy Configuration Manual .

Sticky sessions

For the  leastconn  load-balancing algorithm, cookies are used to ensure that clients are always sent to the same backend server. The following lines in the  backend  section of the configuration file define this:

cookie SRVID insert indirect nocache maxidle 30m maxlife 1h 
... 
server cust-prodns-css01 cust-prodns-css01:9443 weight 5 check ssl verify none cookie s1 
server cust-prodns-css01 cust-prodns-css01:9443 weight 5 check ssl verify none cookie s2


Please also note of the following parameters, which manages the timeout between the client (browser) and HAProxy, and HAProxy and the backend servers (censhare).

timeout client 60m 
... 
timeout server 60m

WebSocket

WebSocket support is required. The following configuration entries define this:

acl is_websocket path_beg /censhare5/client/ 
acl is_websocket hdr(Upgrade) -i WebSocket 
acl is_websocket hdr_beg(Host) -i ws

HAProxy statistics

The use of HAProxy statistics is optional but recommended. This is helpful for troubleshooting web traffic issues and for capacity planning.

To encrypt traffic for the statistics URL, use the following lines instead:

###################### Statistics ###################### 
fontend statistics-8443 
  bind *:8443 ssl crt /etc/haproxy/ssl/certificatefile.pem 
  mode http 
  #option httplog 
  stats enable 
  stats uri /haproxy 
  stats auth admin:password 
  stats admin if TRUE 
###################### Statistics Finish ######################

This uses the same PEM-encoded SSL certificate and the port 8443 that must be available.

CSP Headers

For security, you can also add Content-Security-Policy HTTP headers. For example:

http-response add-header Content-Security-Policy default-src\ 'none';\
http-response add-header Content-Security-Policy connect-src\ 'self'\ wss://%[capture.req.hdr(0)]\ 
https://nominatim.openstreetmap.org;\
http-response add-header Content-Security-Policy script-src\ 'self'\ 'unsafe-eval'\
https://connect.facebook.net\ 
https://platform.twitter.com\ 'sha256-mutaUHp7a6TAHBx7UkKbOet7lfkvyPk131k92oPYqEQ=';\
http-response add-header Content-Security-Policy img-src\ 'self'\ data:\
https://*.tile.openstreetmap.org;\
http-response add-header Content-Security-Policy worker-src\ 'self'\ blob:;\ 
     child-src\ 'self'\ blob:;\ style-src\ 'self'\ 'unsafe-inline';\ frame-src\ *;\ 
    media-src\ 'self';\ base-uri\ 'self';\ frame-ancestors\ 'self';\ form-action\ 
    'none';\ font-src\ 'self'\ data:;\ upgrade-insecure-requests


Restart HAProxy:

systemctl restart haproxy

SSL protocol versions

The HAProxy example configuration only allows HAProxy to accept TLSv1.2. The following entry in the configuration file removes the support for the SSL versions SSLv3, TLSv1.0 and TLSv1.1:

ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets

Note on TLS 1.3

HAProxy 1.8 and newer introduce support for 0-RTT, also known as TLS 1.3. If a customer requires TLS 1.3 support, check if the current OS provides a compiled version of HAProxy 1.8. For example, you can check if the RPM repository contains this version. By default, RHEL/CentOS 7 do not include version 1.8 in their base repositories, but RHEL/CentOS 8 do.

If version 1.8 is not available in the base RPM repository, you must compile HAProxy from source.

Cipher suites

Supported cipher suites:

ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS

Further configuration