
✨ Behandelt das Thema HAProxy und Keepalived zusätzlich zum Load Balancer und Cluster auch Sicherheit (Schutz vor der Schwachstelle schwache SSL/Krypto-Nutzung (LOGJAM) (CVE-2015-4000)) und hohe Lasten.

HAProxy ist eine Open-Source-Software, die als Proxy-Server für TCP- und HTTP-basierte Anwendungen mit hoher Verfügbarkeit (High Availability) und Lastverteilung (Load Balancing) dient.
Keepalived ist eine Open-Source-Software, die in der Lage ist, IP-Failover (Übernahme) für mehr als zwei Server bereitzustellen. Keepalived verwendet untereinander die Multicast-Kommunikationstechnik.
In unserer Struktur werden wir HAProxy für den Load Balancer verwenden und Keepalived zur IP-Übernahme, also um unsere HAProxy-Struktur in ein Cluster zu verwandeln.
In unserem Szenario gibt es 3 Server. Auf diesen 3 Servern installieren wir HAProxy, um sie zu Load Balancern zu machen. Anschließend installieren wir den Keepalived-Dienst, damit bei Ausfall eines Servers ein IP-Failover zu einem anderen Server erfolgt und unser Load-Balancer-Dienst unterbrechungsfrei weiterläuft.
Dafür verwenden wir 4 IPs (die IPs sind rein fiktiv):
Jetzt installieren wir den HAProxy- und Keepalived-Dienst auf allen 3 Servern wie folgt:
sudo add-apt-repository ppa:vbernat/haproxy-2.7 -y
sudo apt update
sudo apt install haproxy keepalived -y
sudo openssl dhparam -out /etc/haproxy/dhparams.pem 2048
Hinweis1: Auf den Servern muss „net.ipv4.ip_nonlocal_bind=1“ gesetzt sein. Andernfalls kann die für HAProxy verwendete Konfiguration nicht gleichzeitig dieselbe IP binden, was zu einem Bind-Fehler führt und der Dienst nicht startet. Dazu müssen Sie wie folgt vorgehen.
Bearbeiten Sie zunächst die Datei „vi /etc/sysctl.conf“ und fügen Sie den folgenden Parameter ein, speichern und beenden Sie.
net.ipv4.ip_nonlocal_bind=1
Führen Sie dann den folgenden Befehl aus.
sysctl -p
Hinweis2: Wenn Sie 443 SSL verwenden möchten, muss im Verzeichnis „/etc/ssl/private/“ die Datei „haproxy.pem“ mit Ihren gebündelten SSL-Zertifikaten (.crt,.ca,*.key) vorhanden sein.
Schauen wir uns nun als Beispiel die HAProxy-Konfiguration unten an. Sie werden auf jedem HAProxy dieselbe Konfiguration verwenden.
Bearbeiten Sie dazu die Datei „/etc/haproxy/haproxy.cfg“. Die folgende Konfiguration unterstützt mindestens HAv2.
vi /etc/haproxy/haproxy.cfg
Unten sind auch die Standardwerte enthalten.
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
# maxconn 100000 #replaceable
# 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
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-dh-param-file /etc/haproxy/dhparams.pem
#tune.ssl.default-dh-param 2048
# nbproc 1
# nbthread 8
tune.maxrewrite 16384
tune.bufsize 32768
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
# maxconn 1000000 #replaceable
timeout connect 3000000
timeout client 6000000
timeout server 6000000
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
Dashboard-Konfigurationsabschnitt für HAProxy (Prometheus-Integration für das Monitoring hinzugefügt)
listen stats
bind fatlan.com:8989
mode http
stats enable
stats uri /stats
option http-use-htx
http-request use-service prometheus-exporter if { path /metrics }
#stats hide-version
stats realm HAProxy\ Statistics
stats auth admin:admin
In der folgenden Konfiguration werden in zwei Blöcken ACLs verwendet. Wenn im Link an irgendeiner Stelle das Wort „rest“ vorkommt, wird der Block middleware-fatlan-backend ausgeführt; bei einer Anfrage an eine andere Domain (forum.fatlan.com) wird backend fatlan-forum-backend ausgeführt; alle anderen Anfragen werden im Block fatlan-backend443 verarbeitet. Abgesehen von anderen Portweiterleitungen.
Umleitung von Port 80 auf Port 443:
frontend fatlan80
bind fatlan.com:80
mode http
redirect scheme https if !{ ssl_fc }
frontend fatlan443
bind fatlan.com:443 ssl crt /etc/ssl/private/haproxy.pem ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
option httplog
option forwardfor
#http-request set-header X-Client-IP req.hdr_ip([X-Forwarded-For])
#option forwardfor except 127.0.0.0/8
option http-server-close
http-request set-header X-Forwarded-Proto https
# reqadd X-Forwarded-Proto:\ https #old config
mode http
default_backend fatlan-backend443
Beispiel einer ACL-Konfiguration (Proxypass): Wenn im Link an irgendeiner Stelle das Wort rest vorkommt, weiterleiten.
acl middleware-fatlan path_beg /rest
use_backend middleware-fatlan-backend if middleware-fatlan
ACL: Weiterleitung zu einem anderen forum-Host:
acl host_fatlanforum hdr(host) -i forum.fatlan.com
use_backend fatlan-forum-backend if host_fatlanforum
Standardmäßig weitergeleiteter Abschnitt für 443:
backend fatlan-backend443
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk HEAD /
server frontend_01 10.10.37.12:8001 check port 8001 inter 3000 rise 2 fall 3
server frontend_02 10.10.37.13:8001 check port 8001 inter 3000 rise 2 fall 3
Von ACL kommender, zu rest weitergeleiteter Abschnitt:
backend middleware-fatlan-backend
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk OPTIONS /login HTTP/1.0
http-check expect status 200
http-request replace-path (.*)(?:rest\/)(.*) \1\2
# reqrep ^([^\ :]*)\ /rest[/]?(.*) \1\ //\2 #old config
server middleware_01 10.10.37.34:3000 check port 4000 inter 12000 rise 3 fall 3
server middleware_02 10.10.37.35:3000 check port 4000 inter 12000 rise 3 fall 3
Von ACL kommender, zu forum weitergeleiteter Abschnitt:
backend fatlan-forum-backend
mode http
option forwardfor
# option httplog
option httpchk HEAD /
server forum_01 10.10.37.45:8080 check port 8080 inter 3000 rise 2 fall 3
Weitere externe Beispiele können wie folgt konfiguriert werden.
Beispiel für Port 5000:
frontend Panel5000
bind fatlan.com:5000
# option httplog
option forwardfor except 127.0.0.0/8
#option http-server-close
http-request set-header X-Forwarded-Proto https
# reqadd X-Forwarded-Proto:\ https #old config
mode http
default_backend panel-backend5000
Weitergeleiteter Abschnitt für Port 5000:
backend panel-backend5000
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk HEAD /
server panel_01 10.10.37.43:5000 check port 5000 inter 12000 rise 3 fall 3
server panel_02 10.10.37.44:5000 check port 5000 inter 12000 rise 3 fall 3
Beispiel für MySQL (3306):
frontend fatlanmysql
bind fatlan.com:3306
mode tcp
default_backend fatlanmysql-backend3306
Weitergeleiteter Abschnitt für Port 3306:
backend fatlanmysql-backend3306
mode tcp
server mysql_01 10.10.37.60:3306 check
server mysql_02 10.10.37.61:3306 check backup
server mysql_03 10.10.37.62:3306 check backup
Sie können die Weiterleitung für andere Domains, Subdomains oder Ports ebenfalls über denselben HAProxy vornehmen. Allerdings haben wir oben bereits die ACL-Weiterleitung für Subdomains gesehen.
Beispiel für die Subdomain egitim.fatlan.com auf Port 4444:
frontend egitim4444
bind egitim.fatlan.com:4444
# option httplog
option forwardfor except 127.0.0.0/8
#option http-server-close
http-request set-header X-Forwarded-Proto https
# reqadd X-Forwarded-Proto:\ https #old config
mode http
default_backend egitim-backend4444
Weitergeleiteter Abschnitt für Subdomain egitim.fatlan.com auf Port 4444:
backend egitim-backend4444
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk HEAD /
server egitim_01 10.10.37.77:4444 check port 4444 inter 12000 rise 3 fall 3
server egitim_02 10.10.37.78:4444 check port 4444 inter 12000 rise 3 fall 3
Ich habe oben einige HAProxy-Konfigurationsbeispiele genannt. Ich habe meine eigene Konfiguration erstellt und auf allen 3 Servern identisch eingefügt.
Jetzt konfigurieren wir Keepalived. Für Keepalived wird es auf 3 Servern teilweise unterschiedliche parametrische Einstellungen geben. Dazu erstellen und konfigurieren wir die Datei „/etc/keepalived/keepalived.conf“. Übrigens: Je höher die „priority“, desto höher die Priorität.
Hinweis1: Keepalived kommuniziert mit seinen anderen Peers per Multicast und bestimmt auf diese Weise Master und Backup.
Mit tcpdump können Sie die Multicast-Kommunikation zwischen den Peers capture (tcpdump -n "multicast").
1. Server (HAProxy+Keepalived)
vrrp_sync_group haproxy {
group {
VI_01
}
}
vrrp_script haproxy_check_script {
script "killall -0 haproxy"
interval 2 # checking every 2 seconds (default: 5 seconds)
fall 3 # require 3 failures for KO (default: 3)
rise 6 # require 6 successes for OK (default: 6)
}
#Virtual interface
vrrp_instance VI_01 {
state MASTER
interface ens3
### 61 id'sini degistirin, diger peer'lerde de aynı olacak
virtual_router_id 61
### 103 id'sini degistirin, diger peer'lerde azalan şekilde olacak
priority 103
authentication {
auth_type PASS
auth_pass 123456
}
# Virtual ip address – floating ip
virtual_ipaddress {
10.10.5.5
}
track_script {
haproxy_check_script
}
}
2. Server (HAProxy+Keepalived) (Ich schreibe nur die Unterschiede)
state BACKUP
priority 102
3. Server (HAProxy+Keepalived) (Ich schreibe nur die Unterschiede)
state BACKUP
priority 101
Hinweis2: Falls eine Multicast-Kommunikation zwischen den Servern nicht möglich ist (z.B. KVM, Cloud-Umgebungen usw.), müssen Sie die Konfiguration mit Unicast-Kommunikation vornehmen, da sie sonst nicht funktioniert.
Unicast-Konfiguration: Kann wie folgt in die Konfiguration eingefügt werden:
###Für jeden Server müssen die anderen Peers als IP angegeben werden
...
#Virtual interface
...
unicast_peer {
<anaother_peer_ip>
<anaother_peer_ip>
}
# Virtual ip address – floating ip
...
Das war es mit der Konfiguration. Auf allen Servern sollte HAProxy störungsfrei laufen, ebenso der Keepalived-Dienst. Bei Ausfällen von Servern oder Diensten wird der Load-Balancer-Dienst auf einem anderen funktionierenden Server weiterlaufen.
Einstellungen für HAProxy und Linux-Kernel bei hohen Lasten
sudo vi /etc/security/limits.conf
* soft no le 1000000
* hard no le 1000000
root soft no le 1000000
root hard no le 1000000
sudo vi /etc/default/haproxy
ulimit 1000000
sudo vi /lib/systemd/system/haproxy.service
LimitNOFILE=1000000
sudo vi /etc/sysctl.conf
net.ipv4.ip_local_port_range=1024 65535
net.ipv4.tcp_max_syn_backlog = 100000
net.core.somaxconn = 100000
net.core.netdev_max_backlog = 100000
sudo vi /etc/haproxy/haproxy.cfg
global
nbproc 1
nbthread 8
tune.maxrewrite 16384
tune.bufsize 32768
maxconn 1000000
tune.ssl.cachesize 1000000
defaults
maxconn 1000000
Danach Reboot, falls Reboot nicht sofort möglich:
sudo systemctl daemon-reload
sudo systemctl restart haproxy.service
Sie können auch den folgenden Befehl verwenden, um Sicherheitstests wie die Nutzung schwacher SSL/Kryptografie (LOGJAM) (CVE-2015-4000) durchzuführen, oder https://www.ssllabs.com/ssltest/:
sudo nmap -sV --script ssl-enum-ciphers -p 443 fatlan.com
sudo nmap -p 443 --script ssl-cert fatlan.com
openssl s_client -connect fatlan.com:443
Außerdem können Sie in den obigen Konfigurationen die x-forwarder-for-(option forwardfor)-Konfiguration zur Erfassung der Client-IPs mit tcpdump auf der haproxy-Seite validieren bzw. die IPs capturen.
sudo tcpdump -i ens3 -A -s 10240 | grep -v IP | egrep --line-buffered "..(GET |\.HTTP\/|POST |HEAD )|^[A-Za-z0-9-]+: " |sed -r 's/..(GET |HTTP\/|POST |HEAD )/\n\n\1/g'
