Anleitung - HAProxy
von Alec Höfler, 5/28/2023, 11:59:22 AMInstallation und Konfiguration von HAProxy und acme.sh
HaProxy ist einer der meist verbreitetsten und schnellsten HTTP/TCP Load-Balancer. In dieser Anleitung wird kurz erklärt, wie man HAProxy inklusive dem LetsEncrypt/ZeroSSL Client acme.sh und ein paar custom scripts installiert.
Als Basis wird ein Alpine (3.15) LXC verwendet.
Installation
Zuerst setze ich meinen eigenen Alpine Mirror. Grund dafür ist die deutlich bessere Performance. Ich setze hier auf die Edge Repository. Danach wird die Package liste aktualisiert und die erforderlichen Pakete installiert. HaProxy wird als OpenRC Service aktiviert und acme.sh installiert. Hier sollte dringend die eigene E-Mail-Adresse gesetzt werden, da darüber der LetsEncrypt Account erstellt wird und an diese Mail die Notify E-Mails versendet werden. Anschließend wird temporär ein selbst signiertes SSL Zertifikat erstellt. Sobald man das erste echt SSL Zertifikat ausgestellt hat, wird dieses gelöscht. Bei den OpenSSL Commands kann alles auf Standard belassen werden. Hierzu bei jeder Frage einfach die ENTER Taste drücken.
1#Set mirrors (optional) 2echo 'https://mirror.itbyhf.xyz/alpine/edge/main' > /etc/apk/repositories 3echo 'https://mirror.itbyhf.xyz/alpine/edge/community' >> /etc/apk/repositories 4# Update package cache 5apk update 6# Install packages 7apk add curl wget socat haproxy python3 py3-pip nano vim bash openssl 8# Enable HAProxy on Boot 9rc-update add haproxy 10# Install acme.sh ; CHANGE EMAIL 11curl https://get.acme.sh | sh -s email=le@a-hoefler.eu 12# Create Symlink 13ln -s /root/.acme.sh/acme.sh /usr/bin/acme.sh 14# Prepare HAProxy dir 15rm -rv /etc/haproxy/* 16mkdir /etc/haproxy/ssl 17# Issue a selfsigned cert 18openssl genrsa -out domain.key 2048 19openssl req -new -key domain.key -out domain.csr 20openssl x509 -req -days 365 -in domain.csr -signkey domain.key -out domain.crt 21bash -c 'cat domain.key domain.crt >> /etc/haproxy/ssl/domain.pem'
Nun werden noch ein paar einfache Bash und Python Skripte heruntergeladen. Die issue_* Skripte erleichtern das Ausstellen der Zertifikate deutlich. Das gen_crt Script verwandelt die PEM Formate der von acme.sh generierten Zertifkate in die passende Syntax von HAProxy. Anschließend werden die Skripte noch ausführbar gemacht.
1mkdir /root/scripts 2cd /root/scripts 3wget https://s3.itbyhf.xyz/cdn/xDR72k5NxZI/config -O config 4wget https://s3.itbyhf.xyz/cdn/xDR72k5NxZI/gen_crt -O gen_crt 5wget https://s3.itbyhf.xyz/cdn/xDR72k5NxZI/issue_dns_cf -O issue_dns_cf 6wget https://s3.itbyhf.xyz/cdn/xDR72k5NxZI/issue_dns_cf_wildcard -O issue_dns_cf_wildcard 7wget https://s3.itbyhf.xyz/cdn/xDR72k5NxZI/issue_dns_pdns -O issue_dns_pdns 8wget https://s3.itbyhf.xyz/cdn/xDR72k5NxZI/issue_dns-pdns_wildcard -O issue_dns_pdns_wildcard 9wget https://s3.itbyhf.xyz/cdn/xDR72k5NxZI/issue_http -O issue_http 10chmod +x issue* 11chmod +x gen_crt
Konfiguration
- In der
/root/scripts/config
PowerDNS bzw CloudFlare Login Informationen für DNS Verifizierung einstellen. Details siehe Schritt 5 - Hier ist eine Beispiel-HAProxy Konfiguration zu finden. Diese beinhaltet die wichtigsten und meist verwendeten Features für einen HTTP Proxy. Alles Weitere lässt sich in der HAProxy Config Dokumentation nachschlagen. Die HAProxy Konfigurationsdatei ist standardmäßig
/etc/haproxy/haproxy.cfg
. Als Editor zum Bearbeiten kann ich VSCode mit dem HAProxy Plugin empfehlen.
1global 2 # Storage 3 log /dev/log local0 4 log /dev/log local1 notice 5 chroot /var/lib/haproxy 6 7 stats timeout 30s 8 # Stats Socket; WI siehe frontend stats 9 stats socket ipv4@0.0.0.0:8085 expose-fd listeners 10 # Als service ausführen 11 user haproxy 12 group haproxy 13 daemon 14 15 ca-base /etc/ssl/certs 16 crt-base /etc/ssl/private 17 ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS 18 ssl-default-bind-options no-sslv3 19 20# Default Settings for each front-/backend 21defaults 22 log global 23 mode http 24 option httplog 25 option dontlognull 26 timeout connect 5000 27 timeout client 50000 28 timeout server 50000 29 30# HaProxy Stats WI at :8404 31frontend stats 32 bind *:8404 33 stats enable 34 stats uri / 35 stats refresh 20s 36 stats admin if TRUE 37 38# HTTP Frontend @Port 80 39frontend http 40 bind :::80 v4v6 41 #für HTTP Verifizierung erforderlich 42 use_backend acmesh if { path_beg /.well-known/acme-challenge/ } 43 # Alles andere auf SSL weiterleiten 44 default_backend ssl_redirect 45 46# HTTPS Frontend @Port 443 47frontend https 48 bind :::443 v4v6 name HaProxy ssl crt /etc/haproxy/ssl/ 49 mode http 50 capture request header Host len 32 51 log global 52 option httplog 53 timeout client 300s 54 maxconn 1000 55 56 # X- Headers 57 http-request set-header X-Forwarded-Proto https if { ssl_fc } 58 http-request set-header X-Forwarded-Proto http if !{ ssl_fc } 59 http-request set-header X-Forwarded-For %[src] 60 61 # CORS Headers (use with caution :D) 62 #http-response set-header Access-Control-Allow-Origin "*" 63 #http-response set-header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization, JSNLog-RequestId, activityId, applicationId, applicationUserId, channelId, senderId, sessionId" 64 #http-response set-header Access-Control-Max-Age 3628800 65 #http-response set-header Access-Control-Allow-Methods "GET, DELETE, OPTIONS, POST, PUT, PATCH" 66 67 # Einfache Weiterleitung 68 # redirect prefix https://neue.domain.de code 301 if { hdr(host) -i alte.domain.de } 69 70 # Auswahl eines Backends (Servers) über die Domain des Requests 71 use_backend website if { hdr(host) -i example.com } 72 use_backend proxmox if { hdr(host) -i pve.example.com } 73 74 # Nutzung eines Backends, falls die Domain https://example.com/demo aufruft 75 use_backend website if { hdr(host) -i example.com } { path_beg -i /demo } 76 77 # Nutzung eines Backends, falls die Domain example.de oder example.com ist; Durch || wird ein ODER symbolisiert 78 use_backend website if { hdr(host) -i example.de } || { hdr(host) -i example.com } 79 80 # Falls bis jetzt kein passender Server gefunden wurde, wird das backend 'default_bk' genutzt 81 default_backend default_bk 82 83# Einfaches Backend 'website' 84backend website 85 server website_srv01 10.10.2.45:80 # 'website_srv_01' ist der Servername (irrelevant), dahinter steht der Server. Wenn nicht extra angegeben, wird HTTP und nicht HTTPS benutzt 86 87backend proxmox 88 server proxmox_srv01 10.0.12.1:8006 check ssl verify none # Hier wird als Beispiel auch intern SSL verwendet. Als Beispiel ein Proxmox mit einem selbst signierten Zertifikat 89 90# Backend für HTTP Verifizierung (acme.sh) 91backend acmesh 92 server acmesh 10.10.2.51:60001 93 94# Default Backend 95backend default_bk 96 server default_bk_srv01 10.10.2.51:8088 97 98#Weiterleitung auf HTTPS 99backend ssl_redirect 100mode http 101redirect scheme https
- Die soeben erstellte Konfigurationsdatei sollte vor dem Einsatz auf korrekte Syntax geprüft werden. Dies kann mit dem Befehl
haproxy -c -f /path/to/haproxy.cfg
gemacht werden. Beispiel-Ausgabe:
1$:~ haproxy -c -f /etc/haproxy/haproxy.cfg 2Configuration file is valid
- Nun können wir HAProxy starten bzw neu laden:
1/etc/init.d/haproxy start 2/etc/init.d/haproxy reload
SSL Zertifikate ausstellen und verwalten
Nun können wir damit beginnen, unsere Zertifikate auszustellen. Unter /root/scripts wurden bereits die nötigen Skripte hinterlegt und die Konfigurationsdatei präpariert. Hier werden nun mehrere Beispiele für die Ausstellung aufgezeigt.
DNS - CloudFlare
Wer die DNS-Verwaltung von CloudFlare benutzt wird die DNS Verifizierung über deren Domains sicher gerne nutzen. Dies ist bei allen Domains außer welche mit den Top-Level-Domains .cf, .ga, .gq, .ml, or .tk möglich, da Cloudflare bei diesen die DNS-API blockiert hat. Die DNS Verifizierung wird durch einen TXT Eintrag realisiert. Der CloudFlare Token kann unter Account->API Keys erstellt werden. Die Verwendung des globalen Tokens ist auch möglich. Sobald es konfiguriert wurde, kann man Zertifikate AUSSTELLEN: Durch Ausführen von /root/scripts/issue_dns_cf
kann man ein Zertifikat für eine (Sub)Domain ausstellen. Das Script /root/scripts/issue_dns_cf_wildcard
wiederum stellt ein Wildcard Zertifikat aus, das für alle Subdomains genutzt werden kann. Diese Skripte können einfach über die Eingabe ihres Pfades in der Konsole aufgerufen werden. Nach dem Starten wird nach einer Domain gefragt. Achtung: Eine Domain; auch für Wildcards gilt dies. Hier wird example.com eingeben, um ein Wildcard Zertifikat für example.com anzufordern Nach der Ausstellung des Zertifikates müssen über /root/scripts/gen_crt
die Zertifikate in die korrekte Syntax konvertiert werden. Ohne diesen Schritt werden diese nicht von HAProxy wahrgenommen.
DNS - PowerDNS
FÜr die, die einen oder mehr PowerDNS Nameserver betreiben, ist auch die Verifizierung über die PowerDNS-API möglich. Diese muss zuerst aktiviert werden, und ein API Key erstellt werden. Dies kann durch die Eingabe folgendes Befehls auf dem PowerDNS-Server gemacht werden. Achtung: Der Key sollte dringend geändert werden!
1echo "webserver-port=8081 2api=yes 3api-key=f5ee4390-6542-48c9-a2a0-e5d0bd399490" >> /etc/powerdns/pdns.conf 4systemctl restart pdns
Die DNS Verifizierung wird durch einen TXT Eintrag realisiert. In der /root/scripts/config
muss nun PDNS_Url zu der URL des PowerDNS-API-Servers geändert werden, und PDNS_Token natürlich entsprechen angepasst werden. Die PDNS_ServerId und PDNS_Ttl kann gleich bleiben, außer man hat andere Einstellungen getroffen. Sobald es konfiguriert wurde, kann man Zertifikate AUSSTELLEN: Durch Ausführen von /root/scripts/issue_dns_pdns
kann man ein Zertifikat für eine (Sub)Domain ausstellen. Das Script /root/scripts/issue_dns_pdns_wildcard
wiederum stellt ein Wildcard Zertifikat aus, das für alle Subdomains genutzt werden kann. Diese Skripte können einfach über die Eingabe ihres Pfades in der Konsole aufgerufen werden. Nach dem Starten wird nach einer Domain gefragt. Achtung: Eine Domain; auch für Wildcards gilt dies. Hier wird example.com eingeben, um ein Wildcard Zertifikat für example.com anzufordern Nach der Ausstellung des Zertifikates müssen über /root/scripts/gen_crt
die Zertifikate in die korrekte Syntax konvertiert werden. Ohne diesen Schritt werden diese nicht von HAProxy wahrgenommen.
HTTP Verifizierung
Steht kein passendes DNS Plugin zur verfügung, ist die HTTP Verifizierung eine gute Möglichkeit. Hierbei wird im Unterordner /.well-known/acme-challenge/ eine Datei von acme.sh hinterlegt, die dann öffentlich überprüft wird. Hierzu ist es nötig, das Backend acmesh
und die use_backend acmesh if ...
Anweisung nicht zu entfernen. Achtung: für die HTTP Verifizierung muss Port 80/TCP geöffnet sein.