HAProxy ist ein hochperformanter Load Balancer und Reverse Proxy. Er verteilt Traffic auf mehrere Server und erhöht damit Verfügbarkeit und Skalierbarkeit.

Warum HAProxy?

Vorteile

- Hochperformant (C-basiert)
- SSL/TLS-Terminierung
- Health Checks
- Session Persistence
- Statistiken und Monitoring
- Kostenlos (Open Source)

Anwendungsfälle

- Lastverteilung für Webserver
- Hochverfügbarkeit
- SSL-Offloading
- API Gateway
- Database Load Balancing

Installation

Debian/Ubuntu

apt update
apt install haproxy

# Version prüfen
haproxy -v

CentOS/RHEL

dnf install haproxy

# Oder neuere Version
dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
dnf install haproxy

Service starten

systemctl enable --now haproxy
systemctl status haproxy

Grundkonfiguration

Konfigurationsdatei

# /etc/haproxy/haproxy.cfg

Basis-Struktur

global          # Globale Einstellungen
defaults        # Standard-Einstellungen
frontend        # Eingehende Verbindungen
backend         # Server-Pool
listen          # Kombiniert Frontend + Backend

Einfache Konfiguration

# /etc/haproxy/haproxy.cfg

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

    # Performance
    maxconn 4096

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000

frontend http_front
    bind *:80
    default_backend http_back

backend http_back
    balance roundrobin
    server web1 192.168.1.10:80 check
    server web2 192.168.1.11:80 check
    server web3 192.168.1.12:80 check

Konfiguration prüfen

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

Load Balancing Algorithmen

Round Robin

backend http_back
    balance roundrobin
    server web1 192.168.1.10:80 check
    server web2 192.168.1.11:80 check

Least Connections

backend http_back
    balance leastconn
    server web1 192.168.1.10:80 check
    server web2 192.168.1.11:80 check

Source IP Hash

backend http_back
    balance source
    server web1 192.168.1.10:80 check
    server web2 192.168.1.11:80 check

URI Hash

backend http_back
    balance uri
    server web1 192.168.1.10:80 check
    server web2 192.168.1.11:80 check

Gewichtung

backend http_back
    balance roundrobin
    server web1 192.168.1.10:80 check weight 3
    server web2 192.168.1.11:80 check weight 2
    server web3 192.168.1.12:80 check weight 1

Health Checks

HTTP Health Check

backend http_back
    option httpchk GET /health
    http-check expect status 200

    server web1 192.168.1.10:80 check inter 5000 rise 2 fall 3
    server web2 192.168.1.11:80 check inter 5000 rise 2 fall 3

TCP Health Check

backend tcp_back
    mode tcp
    option tcp-check

    server db1 192.168.1.20:3306 check
    server db2 192.168.1.21:3306 check

Health Check Parameter

inter:  Intervall zwischen Checks (ms)
rise:   Erfolgreiche Checks für "gesund"
fall:   Fehlgeschlagene Checks für "krank"

SSL/TLS Terminierung

SSL-Zertifikat vorbereiten

# Zertifikat und Key kombinieren
cat /etc/letsencrypt/live/example.com/fullchain.pem \
    /etc/letsencrypt/live/example.com/privkey.pem > \
    /etc/haproxy/certs/example.com.pem

chmod 600 /etc/haproxy/certs/example.com.pem

HTTPS Frontend

frontend https_front
    bind *:443 ssl crt /etc/haproxy/certs/example.com.pem

    # HTTP/2 aktivieren
    bind *:443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1

    default_backend http_back

HTTP zu HTTPS Redirect

frontend http_front
    bind *:80
    http-request redirect scheme https unless { ssl_fc }

frontend https_front
    bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
    default_backend http_back

SSL-Hardening

global
    # Moderne SSL-Einstellungen
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

Session Persistence

backend http_back
    balance roundrobin
    cookie SERVERID insert indirect nocache
    server web1 192.168.1.10:80 check cookie s1
    server web2 192.168.1.11:80 check cookie s2

Stick Tables

backend http_back
    stick-table type ip size 200k expire 30m
    stick on src
    server web1 192.168.1.10:80 check
    server web2 192.168.1.11:80 check

ACLs und Routing

Host-basiertes Routing

frontend http_front
    bind *:80

    # ACLs definieren
    acl host_api hdr(host) -i api.example.com
    acl host_app hdr(host) -i app.example.com
    acl host_static hdr(host) -i static.example.com

    # Routing
    use_backend api_back if host_api
    use_backend app_back if host_app
    use_backend static_back if host_static
    default_backend app_back

backend api_back
    server api1 192.168.1.20:8080 check

backend app_back
    server app1 192.168.1.30:80 check

backend static_back
    server static1 192.168.1.40:80 check

Pfad-basiertes Routing

frontend http_front
    bind *:80

    acl path_api path_beg /api
    acl path_static path_beg /static
    acl path_admin path_beg /admin

    use_backend api_back if path_api
    use_backend static_back if path_static
    use_backend admin_back if path_admin
    default_backend web_back

Kombinierte ACLs

frontend http_front
    bind *:80

    acl is_api path_beg /api
    acl is_post method POST
    acl is_internal src 192.168.0.0/16

    # Nur interne POST-Requests an API
    use_backend api_write if is_api is_post is_internal
    use_backend api_read if is_api
    default_backend web_back

Statistiken

Stats-Seite aktivieren

listen stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats refresh 30s
    stats auth admin:sicheres-passwort
    stats admin if LOCALHOST

Zugriff: http://server-ip:8404/stats

Stats über Socket

# Socket in global section
stats socket /run/haproxy/admin.sock mode 660 level admin

# Abfragen
echo "show stat" | socat stdio /run/haproxy/admin.sock
echo "show info" | socat stdio /run/haproxy/admin.sock

Logging

Rsyslog konfigurieren

# /etc/rsyslog.d/49-haproxy.conf

$AddUnixListenSocket /var/lib/haproxy/dev/log

local0.* /var/log/haproxy/haproxy.log
local1.* /var/log/haproxy/haproxy-info.log
mkdir -p /var/lib/haproxy/dev
systemctl restart rsyslog

Log-Format anpassen

defaults
    log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"

Access Log

frontend http_front
    option httplog
    log global
    capture request header Host len 50
    capture request header User-Agent len 100

Rate Limiting

Verbindungslimits

frontend http_front
    bind *:80

    # Max Verbindungen pro IP
    stick-table type ip size 100k expire 30s store conn_cur
    acl too_many_conns src_conn_cur gt 20
    http-request deny if too_many_conns

Request Rate Limiting

frontend http_front
    bind *:80

    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    acl too_fast src_http_req_rate gt 100
    http-request deny deny_status 429 if too_fast

Komplette Produktions-Konfiguration

# /etc/haproxy/haproxy.cfg

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 4096
    tune.ssl.default-dh-param 2048

    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    option  forwardfor
    option  http-server-close

    timeout connect 5s
    timeout client  30s
    timeout server  30s
    timeout http-request 10s
    timeout http-keep-alive 10s

    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

# Stats
listen stats
    bind *:8404
    mode http
    stats enable
    stats uri /stats
    stats refresh 30s
    stats auth admin:sicheres-passwort
    stats hide-version

# HTTP -> HTTPS Redirect
frontend http_front
    bind *:80
    http-request redirect scheme https unless { ssl_fc }

# HTTPS Frontend
frontend https_front
    bind *:443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1

    # Security Headers
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
    http-response set-header X-Frame-Options "SAMEORIGIN"
    http-response set-header X-Content-Type-Options "nosniff"

    # Rate Limiting
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    http-request deny deny_status 429 if { src_http_req_rate gt 100 }

    # ACLs
    acl host_api hdr(host) -i api.example.com
    acl path_api path_beg /api

    # Routing
    use_backend api_back if host_api or path_api
    default_backend web_back

# Web Backend
backend web_back
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200

    cookie SERVERID insert indirect nocache

    server web1 192.168.1.10:80 check cookie s1 weight 3
    server web2 192.168.1.11:80 check cookie s2 weight 3
    server web3 192.168.1.12:80 check cookie s3 backup

# API Backend
backend api_back
    balance leastconn
    option httpchk GET /api/health
    http-check expect status 200

    server api1 192.168.1.20:8080 check
    server api2 192.168.1.21:8080 check

Hochverfügbarkeit mit Keepalived

Installation

apt install keepalived

Master-Konfiguration

# /etc/keepalived/keepalived.conf (Master)

vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 101
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass geheim123
    }

    virtual_ipaddress {
        192.168.1.100/24
    }

    track_script {
        chk_haproxy
    }
}

Backup-Konfiguration

# /etc/keepalived/keepalived.conf (Backup)

vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass geheim123
    }

    virtual_ipaddress {
        192.168.1.100/24
    }

    track_script {
        chk_haproxy
    }
}
systemctl enable --now keepalived

Troubleshooting

Verbindungsprobleme

# HAProxy-Status prüfen
systemctl status haproxy

# Konfiguration testen
haproxy -c -f /etc/haproxy/haproxy.cfg

# Logs prüfen
tail -f /var/log/haproxy/haproxy.log

# Backend-Status
echo "show stat" | socat stdio /run/haproxy/admin.sock | grep -v "^#"

Server offline schalten

# Server deaktivieren
echo "disable server web_back/web1" | socat stdio /run/haproxy/admin.sock

# Server aktivieren
echo "enable server web_back/web1" | socat stdio /run/haproxy/admin.sock

Zusammenfassung

| Algorithmus | Verwendung | |-------------|------------| | roundrobin | Standard, gleichmäßige Verteilung | | leastconn | Verbindungsintensive Anwendungen | | source | Session Persistence ohne Cookies | | uri | Cache-Server |

| Befehl | Funktion | |--------|----------| | haproxy -c -f config | Konfiguration prüfen | | systemctl reload haproxy | Konfiguration neu laden | | show stat | Backend-Status anzeigen | | disable/enable server | Server verwalten |

Fazit

HAProxy ist ein leistungsstarker Load Balancer für Produktivumgebungen. Die Konfiguration ist flexibel und erlaubt komplexe Routing-Szenarien. Mit SSL-Terminierung, Health Checks und der integrierten Statistikseite haben Sie volle Kontrolle über Ihren Traffic. Für Hochverfügbarkeit kombinieren Sie HAProxy mit Keepalived.