This article gives an outline of how to build HAProxy with OpenSSL so it can use TLS v1.3 on centos or ubuntu.
1. Build and install OpenSSL 1.1.1
In order to have TLS 1.3 support, you will need to install version 1.1.1 of OpenSSL.
These instructions build OpenSSL into a directory /usr/local/openssl-1.1.1 shared to ensure that it’s separate from any other OpenSSL installs on the machine. If you want you can upgrade your existing OpenSSL to version 1.1.1
OpenSSL will require GCC. Install GCC using either of the commands
#The command installs a bunch of new packages including gcc, g++ and make
sudo yum group install "Development Tools"
#This will just install gcc package
yum -y install gcc
wget https://www.openssl.org/source/openssl-1.1.1.tar.gz
tar -xzf openssl-1.1.1.tar.gz
cd openssl-1.1.1
./config --prefix=/usr/local/openssl-1.1.1 shared
make
sudo make install
Build and install HAProxy
You need HAProxy 1.8.1 or later to enable TLS 1.3 support. We are using 2.4.4
For Ubuntu follow this instruction.
Uninstall the existing haproxy installation first. I would suggest to take a backup of old haproxy configuration if you have one.
sudo mv /etc/haproxy /etc/haproxy-old
apt remove haproxy*
sudo apt install build-essential libpcre2-dev zlib1g-dev
cd ~
wget https://www.haproxy.org/download/2.4/src/haproxy-2.4.4.tar.gz
tar -xzf haproxy-2.4.4.tar.gz
cd haproxy-2.4.4/
make TARGET=linux2628 CPU=native USE_PCRE2=1 USE_PCRE2_JIT=1 USE_OPENSSL=1 SSL_LIB=/usr/local/openssl-1.1.1/lib SSL_INC=/usr/local/openssl-1.1.1/include USE_ZLIB=1
sudo make install
For Centos follow this instruction
sudo mv /etc/haproxy /etc/haproxy-old
yum remove haproxy*
yum install -y make gcc gcc-c++ pcre-devel openssl-devel readline-devel systemd-devel zlib-devel
cd ~
wget http://www.haproxy.org/download/2.4/src/haproxy-2.4.4.tar.gz
tar -xvzf haproxy-2.4.4.tar.gz
cd haproxy-2.4.4
make -j $(nproc) TARGET=linux-glibc USE_OPENSSL=1 SSL_LIB=/usr/local/openssl-1.1.1/lib SSL_INC=/usr/local/openssl-1.1.1/include USE_ZLIB=1 USE_PCRE=1 USE_SYSTEMD=1
make install
Adding haproxy user
useradd -M -r -s /sbin/nologin haproxy
Now create systemd file
LD_LIBRARY_PATH must be added because OpenSSL 1.1.1 is direct installed or else you will get an error.
nano /etc/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=network.target
[Service]
Environment=LD_LIBRARY_PATH=/usr/local/openssl-1.1.1/lib/
Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "EXTRAOPTS=-S /run/haproxy-master.sock"
ExecStartPre=/usr/local/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS
ExecStart=/usr/local/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE $EXTRAOPTS
ExecReload=/usr/local/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
Restart=always
SuccessExitStatus=143
Type=notify
[Install]
WantedBy=multi-user.target
Now create haproxy config directory in /etc.
mkdir -p /etc/haproxy
Now you can enable the systemd configuration
systemctl enable haproxy
systemctl start haproxy
Check Installed HAProxy version
haproxy -v
Add the following to the HAProxy config (Note the ssl-default-bind-ciphers and ssl-default-bind-options lines), updating any paths as required.
If you only want TLSv1.3 with no fallback to TLSv1.2 then set ssl-default-bind-options to force-tlsv13
global
log /dev/log local0
chroot /usr/local/var/lib/haproxy
user haproxy
group haproxy
maxconn 4000
pidfile /usr/local/var/run/haproxy.pid
tune.ssl.default-dh-param 2048
# Add below lines for tls 1.3 configuration rest you can ignore
ssl-default-bind-ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:EECDH+AESGCM:EECDH+CHACHA20
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
defaults
balance roundrobin
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout check 10s
listen dns
# Note the keycert.pem file is the concatenation of the certificate chain and key into one file which is what HAProxy requires.
bind :::853 v4v6 tfo ssl crt /etc/certs/keycert.pem
mode tcp
server server1 127.0.0.1:9999
If you are using above configuration. The above configuration sets HAProxy to run chroot in a directory /usr/local/var/lib/haproxy. It’s necessary to create this directory. OpenSSL also needs access to /dev/urandom and /dev/random in the chroot.
mkdir -p /usr/local/var/lib/haproxy/dev
cd /usr/local/var/lib/haproxy/dev
mknod urandom c 1 9
mknod random c 1 8
Restart again HAProxy
sudo service haproxy restart
sudo systemctl restart haproxy
Lastly, the firewall on CentOS is quite restrictive by default. If required use the following commands to allow the required services and reload the firewall.
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-port=8181/tcp
sudo firewall-cmd --reload
Note: If you get any below error related to path you can export the path using below command.
export PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64:/usr/local/openssl-1.1.1/lib