Heute bauen wir einen hochverfügbaren Socks-Proxy. Dazu brauchen wir vier VMs:
2 x Loadbalancer
2 x Socks Proxy
In diesem Beispiel nehme ich dafür Debian LXC Container unter Proxmox VE. LXC Container sind tatsächlich wenn man das richtig macht einfacher zu handhaben als Docker-Container und der Ressourcenverbrauch ist ähnlich gering. Die Maschinen laufen verteilt in einem Proxmox VE Cluster Verband. Wie man das macht, schreib ich nochmal, da gibts aber auch echt brauchbare Youtube-Tutorials.
Die verwendeten Programme gibts alle als Debian-Paket. Ohne zwingende Gründe selbst compilieren ist nicht zu empfehlen, denn das erhöht den Verwaltungsaufwand erheblich.
Innerhalb der Container lässt man am besten unattended-upgrades laufen und ja, man kann die Maschinen auch (scheduled) booten lassen, wenn sie das z.B. nach nem Kernel-Update müssen.
Konfiguration Loadbalancer
Der Loadbalancer ist ein VRRP-Cluster mit keepalived. Der hat eine VIP (192.168.12.14), auf der ein haproxy als Frontend läuft. Den haproxy lässt man am besten (siehe unten) vom keepalived notify-Skript starten und stoppen, wenn der Cluster Member zum Master bzw. Backup wird. Das vermeidet unnötige systemd-Fehler. 😉
keepalived.conf
Das ist die Keepalived Konfiguration des Master-Knotens:
global_defs {
router_id proxy
script_user root
enable_script_security
}
vrrp_instance proxy {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass safe234
}
virtual_ipaddress {
192.168.12.14
}
notify /etc/keepalived/notify.sh
}
Die Konfiguration des Backup-Knotens ist bis auf diese zwei Ausnahmen mit der Master-Konfiguration identisch: Der Backup-Knoten kriegt den initialen Status “BACKUP” und eine niedrigere Priorität, so dass er wirklich erst aktiv wird, wenn er keinen Master mehr sieht.
state BACKUP
priority 90
Hinweis: Dies ist eine ganz simple Beispiel-Konfiguration. In einer produktiven Umgebung sollte man unter Anderem andere Authentisierungsmechanismen verwenden und man könnte den VRRP-Traffic auch mit iptables/nftables filtern. Da gibts Einiges zu “feilen”.
notify.sh
Das Notify-Skript wird bei einem Status-Wechsel aufgerufen, also zum Beispiel wenn der Backup-Knoten zum Master wird etc.
#!/bin/bash
ENDSTATE=$3
NAME=$2
TYPE=$1
case $ENDSTATE in
"BACKUP") # Perform action for transition to BACKUP state
systemctl stop haproxy
echo $ENDSTATE > /var/run/keepalived.state
exit 0
;;
"FAULT") # Perform action for transition to FAULT state
echo $ENDSTATE > /var/run/keepalived.state
exit 0
;;
"MASTER") # Perform action for transition to MASTER state
systemctl start haproxy
echo $ENDSTATE > /var/run/keepalived.state
exit 0
;;
*) echo "Unknown state ${ENDSTATE} for VRRP ${TYPE} ${NAME}"
echo $ENDSTATE > /var/run/keepalived.state
exit 1
;;
esac
Das Sichern des aktuellen Status ist optional, ich frage den mit CheckMK ab und das geht schneller, wenn man da einfach eine Datei ausliest anstatt die kompletten Runtime Daten mit kill -USR1 $(cat /var/run/keepalived.pid) in eine Datei zu ballern und die da wieder rauszugreppen.
haproxy.cfg
Die haproxy-Konfiguration ist auf beiden Knoten identisch, denn der läuft eh nur immer auf dem aktiven Knoten und lauscht auf die Cluster-VIP.
frontend socks
bind 192.168.12.14:1080
mode tcp
option tcplog
default_backend sockies
[...]
backend sockies
option tcp-check
tcp-check connect
tcp-check send-binary 050100
tcp-check expect binary 0500
balance source
hash-type consistent
server pix1 192.168.12.21:1080 check inter 30s weight 100
server pix2 192.168.12.22:1080 check inter 30s weight 0`
Die tcp-check Zeilen machen einen Layer7-Check auf die Backend-Systeme, bei dem geprüft wird, ob der Socks-Proxy unauthentisierte Zugriffe unterstützt (0x050100), was dieser - wenn ja - mit einem 0x0500 beantwortet.
Ob der Zugriff funktioniert, kann vom Load Balancer geprüft werden:
curl --insecure --socks5 102.168.12.21:1080 https://www.google.de/
Konfiguration Socks Proxy
Auf den Proxy VMs (tatsächlich läuft da noch ein Http Proxy, aber das ist eine andere Geschichte) ist der Socks Proxy dante installiert, welcher im Standard-Repository von Debian enthalten ist.
Fun fact: Die Firma, die dante gebaut hat, heisst “Inferno Nettverk A/S”.
danted.conf
Die Konfiguration des Socks Proxy liegt in /etc/danted.conf und unterscheidet sich einzig im Punkt “external”, da muss die lokale IP-Adresse der jeweiligen Maschine rein.
logoutput: stderr
internal: 0.0.0.0 port = 1080
external: 192.168.12.21
socksmethod: none
clientmethod: none
user.privileged: proxy
user.unprivileged: nobody
user.libwrap: nobody
client pass {
from: 0.0.0.0/0 port 1-65535 to: 0.0.0.0/0
log: connect disconnect error
}
socks pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
protocol: tcp udp
log: connect disconnect error
}
Dokumentation siehe Dante Website.
Die Konfiguration ist nur ein Beispiel und sehr “offen”. Im produktiven Betrieb würde man mindestens via “pass” Regeln die Zugriffe einschränken sowie eventuell noch irgendeine Art von Authentisierung verwenden.
Wer sich jetzt fragt. wozu man denn einen Socks Proxy braucht: Den braucht man, wenn man andere (Socks-Fähige!) Applikationen als Http(s) durch einen Proxy leiten will. Zum Beispiel, wenn mir irgendein Compliance-Mist vorschreibt, dass mein Traffic immer durch ein “Application Level Gateway” gehen muss. Erläuterungen dazu hat Wikipedia parat.