Das PROXY-Protokoll ermöglicht es einem Proxy oder Load Balancer, die Verbindungsinformationen des ursprünglichen Clients, einschließlich dessen echter IP-Adresse und Port, an den Backend-Server zu übermitteln, indem ein kleiner, standardisierter Header an den Anfang der TCP-Verbindung angefügt wird.
Warum PROXY-Protokoll? Das Problem, das es löst
Standard-TCP-Proxys arbeiten, indem sie im Namen des Clients eine neue Verbindung zum Backend-Server herstellen. Aus Sicht des Backend-Servers stammt die Verbindung von der IP-Adresse des Proxys, nicht von der des ursprünglichen Clients. Dieses Verhalten verschleiert die wahre Identität des Clients und führt zu mehreren Herausforderungen:
- Protokollierung: Server-Zugriffsprotokolle erfassen die IP des Proxys, wodurch es unmöglich wird, Anfragen einzelnen Clients zuzuordnen.
- Sicherheit: Web Application Firewalls (WAFs), Ratenbegrenzer und Zugriffskontrolllisten (ACLs) auf Backend-Servern können bösartige Clients nicht genau anhand ihrer echten IP-Adressen identifizieren und blockieren.
- Analysen: Geo-Targeting, personalisierte Inhaltsbereitstellung und Missbrauchserkennungssysteme verlieren kritische Client-Standort- und Verhaltensdaten.
- Fehlerbehebung: Die Fehlerbehebung bei Netzwerkproblemen oder spezifischem Client-Verhalten wird ohne Sichtbarkeit der ursprünglichen Client-Quelle erheblich komplexer.
Das PROXY-Protokoll löst dies, indem es einen Mechanismus bereitstellt, mit dem der Proxy die Verbindungsdetails des Clients (Quell-IP, Quell-Port, Ziel-IP, Ziel-Port) über die Proxy-Schicht hinweg übertragen kann, sodass der Backend-Server den ursprünglichen Client korrekt identifizieren kann.
Wie das PROXY-Protokoll funktioniert
Das PROXY-Protokoll arbeitet auf der Transportschicht (Schicht 4) des OSI-Modells. Wenn ein Proxy oder Load Balancer, der das PROXY-Protokoll unterstützt, eine Verbindung von einem Client empfängt, stellt er eine neue Verbindung zum Backend-Server her. Bevor Anwendungsdaten (z. B. HTTP-Anfragen, Datenbankabfragen) gesendet werden, sendet der Proxy zuerst einen PROXY-Protokoll-Header. Dieser Header enthält die Verbindungsinformationen des Clients.
Damit das PROXY-Protokoll korrekt funktioniert, müssen zwei Bedingungen erfüllt sein:
1. Der Proxy oder Load Balancer muss so konfiguriert sein, dass er den PROXY-Protokoll-Header sendet.
2. Der Backend-Server muss so konfiguriert sein, dass er den PROXY-Protokoll-Header empfängt und parst, bevor er Anwendungsdaten verarbeitet. Wenn der Backend-Server den Header nicht versteht, interpretiert er ihn als fehlerhafte Anwendungsdaten, was zu Verbindungsfehlern führt.
PROXY-Protokoll-Versionen
Es gibt zwei primäre Versionen des PROXY-Protokolls: v1 und v2.
Version 1 (v1)
PROXY-Protokoll v1 ist ein ASCII-basiertes, menschenlesbares Format. Es unterstützt IPv4 und IPv6 über TCP.
Format:
PROXY <INET_PROTOCOL> <CLIENT_IP> <PROXY_IP> <CLIENT_PORT> <PROXY_PORT>\r\n
<INET_PROTOCOL>:TCP4für IPv4 oderTCP6für IPv6.<CLIENT_IP>: Die IP-Adresse des ursprünglichen Clients.<PROXY_IP>: Die IP-Adresse des Proxys (die IP, die das Backend als Quelle der Verbindung sieht).<CLIENT_PORT>: Der Quell-Port des ursprünglichen Clients.<PROXY_PORT>: Der Ziel-Port auf dem Proxy, mit dem sich der Client verbunden hat.
Beispiel (IPv4):
PROXY TCP4 192.168.1.1 10.0.0.1 52345 80\r\n
Dieser Header zeigt eine TCPv4-Verbindung vom Client 192.168.1.1:52345 zum Proxy an, der sich dann mit dem Backend unter 10.0.0.1:80 verbunden hat.
Einschränkungen von v1:
* Beschränkt auf TCP-Verbindungen.
* ASCII-Overhead kann etwas weniger effizient sein.
* Unterstützt keine zusätzlichen Metadaten.
Version 2 (v2)
PROXY-Protokoll v2 ist ein binäres Format, das auf Effizienz und Erweiterbarkeit ausgelegt ist. Es unterstützt IPv4, IPv6 und UNIX-Sockets über TCP und UDP und enthält einen Type-Length-Value (TLV)-Feldmechanismus zur Übertragung zusätzlicher Verbindungsmetadaten.
Vorteile von v2:
* Effizienz: Binäres Format reduziert die Header-Größe.
* Breitere Protokollunterstützung: Unterstützt TCP, UDP und UNIX-Sockets.
* IPv6-Unterstützung: Vollständige Integration von IPv6.
* Erweiterbarkeit (TLV): Ermöglicht die Übergabe beliebiger Metadaten, wie z. B. SSL-Verbindungsinformationen, eindeutige Verbindungs-IDs oder andere anwendungsspezifische Daten.
Strukturübersicht (vereinfacht):
Der v2-Header beginnt mit einer 13-Byte-Signatur, gefolgt von einem 1-Byte-Versions-/Befehlsfeld, einem 1-Byte-Protokollfeld, einem 2-Byte-Adresslängenfeld und dann den variablen Adressinformationen und optionalen TLV-Feldern.
Obwohl das rohe Binärformat komplex ist, ist die wichtigste Erkenntnis seine Fähigkeit, mehr Informationen effizient und über eine breitere Palette von Protokollen zu übertragen.
PROXY-Protokoll vs. X-Forwarded-For (XFF)
Sowohl das PROXY-Protokoll als auch der X-Forwarded-For (XFF) HTTP-Header zielen darauf ab, Client-IP-Informationen über einen Proxy zu übergeben. Sie arbeiten jedoch auf verschiedenen Schichten und haben unterschiedliche Eigenschaften.
| Merkmal | PROXY-Protokoll | X-Forwarded-For (XFF) Header |
|---|---|---|
| Betriebsschicht | Transportschicht (L4) | Anwendungsschicht (L7 - speziell HTTP) |
| Protokollumfang | Jedes TCP/UDP-basierte Protokoll (HTTP, FTP, SSH, SMTP, etc.) | Nur HTTP/HTTPS |
| Mechanismus | Vorangestellter Header zum rohen TCP/UDP-Stream | HTTP-Anfrage-Header |
| Client-Kontrolle | Kann von einem bösartigen Client nach dem ersten vertrauenswürdigen Proxy nicht gefälscht werden | Kann von einem bösartigen Client gefälscht werden, wenn nicht ordnungsgemäß vom ersten vertrauenswürdigen Proxy behandelt |
| Informationen | Client-IP, Client-Port, Proxy-IP, Proxy-Port, (v2: TLVs) | Client-IP (und potenziell frühere Proxy-IPs) |
| Overhead | Minimal, feste Größe (v1) oder kleines Binärformat (v2) | Kleiner String, der zu HTTP-Headern hinzugefügt wird |
| Anwendungsfälle | Jeder TCP/UDP-Dienst, der eine echte Client-IP benötigt | HTTP/HTTPS-Dienste, die eine echte Client-IP benötigen |
Das PROXY-Protokoll bietet eine robustere und universellere Lösung zur Weitergabe von Client-IP-Informationen, insbesondere für Nicht-HTTP-Dienste oder Szenarien, in denen starke Garantien gegen Client-IP-Spoofing auf der Netzwerkschicht erforderlich sind.
Implementierung des PROXY-Protokolls
Die Implementierung des PROXY-Protokolls erfordert eine Konfiguration sowohl auf dem sendenden Proxy/Load Balancer als auch auf dem empfangenden Backend-Server.
Proxy/Load Balancer Konfiguration (Senden des PROXY-Protokolls)
HAProxy:
HAProxy ist eine gängige Wahl für Load Balancing und unterstützt das PROXY-Protokoll vollständig.
frontend http_in
bind *:80
mode tcp
default_backend web_servers
backend web_servers
mode tcp
server s1 192.168.1.10:80 send-proxy-v2 # Sendet PROXY-Protokoll v2
server s2 192.168.1.11:80 send-proxy # Sendet PROXY-Protokoll v1
AWS Network Load Balancer (NLB):
Bei der Konfiguration einer Zielgruppe für einen NLB können Sie die Unterstützung für PROXY-Protokoll v2 aktivieren. Diese Einstellung wird auf die gesamte Zielgruppe angewendet. Alle Ziele in dieser Gruppe müssen so konfiguriert sein, dass sie das PROXY-Protokoll akzeptieren.
Cloudflare Spectrum:
Für Dienste, die über Cloudflare Spectrum proxied werden, können Sie die PROXY-Protokoll-Unterstützung aktivieren. Cloudflare sendet PROXY-Protokoll v2-Header an Ihre Ursprungsserver.
Nginx (Stream Module - als Proxy):
Das ngx_stream_proxy_module von Nginx kann so konfiguriert werden, dass es das PROXY-Protokoll sendet, hauptsächlich in seiner kommerziellen Version oder spezifischen Builds.
stream {
upstream backend_servers {
server 192.168.1.10:80;
server 192.168.1.11:80;
}
server {
listen 12345;
proxy_pass backend_servers;
proxy_protocol on; # Nginx sendet PROXY-Protokoll v1
}
}
Backend-Server Konfiguration (Empfangen und Parsen des PROXY-Protokolls)
Nginx (als Backend-Webserver):
Nginx kann so konfiguriert werden, dass es PROXY-Protokoll-Header abhört und parst.
http {
server {
listen 80 proxy_protocol; # Hört auf PROXY-Protokoll v1/v2 auf Port 80
listen 443 ssl proxy_protocol;
set_real_ip_from 10.0.0.0/8; # Vertraue IPs aus deinem Proxy-Netzwerk
real_ip_header proxy_protocol; # Verwende die IP aus dem PROXY-Protokoll-Header
location / {
root /var/www/html;
index index.html;
# Die echte IP des Clients ist nun in $remote_addr verfügbar
# und $proxy_protocol_addr kann für die Protokollierung oder spezifische Logik verwendet werden
log_format custom_log '$proxy_protocol_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log custom_log;
}
}
}
In Nginx wird $remote_addr auf die IP des Proxys gesetzt, aber die Variablen $proxy_protocol_addr und $proxy_protocol_port enthalten die echte IP und den Port des Clients. Die Direktiven set_real_ip_from und real_ip_header proxy_protocol ermöglichen es Nginx, $remote_addr korrekt mit der tatsächlichen IP des Clients zu füllen.
Apache HTTP Server:
Apache kann das Modul mod_remoteip verwenden, um PROXY-Protokoll-Header zu parsen.
<IfModule mod_remoteip.c>
# PROXY-Protokoll-Parsing aktivieren
RemoteIPProxyProtocol On
# Vertrauenswürdige Proxys definieren
RemoteIPTrustedProxy 10.0.0.0/8
RemoteIPTrustedProxy 192.168.0.0/16
# Das Log-Format so konfigurieren, dass die echte Client-IP verwendet wird
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
</IfModule>
Mit RemoteIPProxyProtocol On erwartet Apache den PROXY-Protokoll-Header. Die Variable %a im LogFormat spiegelt dann korrekt die echte IP des Clients wider.
Benutzerdefinierte Anwendungen:
Für benutzerdefinierte Anwendungen, die in Sprachen wie Python, Node.js, Go oder Java geschrieben sind, muss die Anwendung selbst den eingehenden TCP-Stream lesen, auf den PROXY-Protokoll-Header prüfen, diesen parsen und dann mit dem anwendungsspezifischen Protokoll fortfahren.
- Erkennung: Die Anwendung muss zuerst einige Bytes (z. B. 100-200 Bytes) vom Socket lesen, um zu prüfen, ob sie mit der PROXY-Protokoll v1-Signatur (
PROXY) oder der v2-Signatur übereinstimmen. - Parsen: Wenn ein PROXY-Protokoll-Header erkannt wird, parst die Anwendung ihn, um die Client-IP, den Port usw. zu extrahieren.
- Fortsetzung: Nach dem Parsen verarbeitet die Anwendung die verbleibenden Daten auf dem Socket als ihr natives Protokoll.
- Kein Header: Wenn kein PROXY-Protokoll-Header gefunden wird, geht die Anwendung davon aus, dass die Verbindung direkt von einem Client oder einem Nicht-PROXY-Protokoll-Proxy stammt und verarbeitet die Daten direkt.
Viele Netzwerkbibliotheken und Frameworks bieten Middleware oder integrierte Unterstützung für das Parsen des PROXY-Protokolls.
Vorteile der Verwendung des PROXY-Protokolls
- Genaue IP-Protokollierung: Stellt sicher, dass Server-Zugriffsprotokolle, Firewalls und Überwachungssysteme die wahre Client-IP-Adresse erfassen.
- Verbesserte Sicherheit: Ermöglicht Sicherheitstools (WAFs, DDoS-Mitigation, Ratenbegrenzer) auf Backend-Servern, Richtlinien basierend auf der echten Identität des Clients durchzusetzen.
- Verbesserte Analysen: Bietet genaue geografische und demografische Daten für Analysen, A/B-Tests und Personalisierung.
- Vereinfachte Netzwerkarchitektur: Konsolidiert die Client-IP-Behandlung auf der Transportschicht, wodurch die Notwendigkeit anwendungsspezifischer Header wie XFF reduziert wird.
- Breite Kompatibilität: Funktioniert mit jeder TCP/UDP-basierten Anwendung, nicht nur mit HTTP.
Überlegungen und Best Practices
- Vertrauensgrenzen: Aktivieren Sie das PROXY-Protokoll nur von vertrauenswürdigen Proxys oder Load Balancern, die Sie kontrollieren. Wenn eine nicht vertrauenswürdige Entität einen gefälschten PROXY-Protokoll-Header sendet, könnte Ihr Backend-Server über den Ursprung des Clients irregeführt werden.
- End-to-End-Kompatibilität: Stellen Sie sicher, dass sowohl der Proxy als auch der Backend-Server korrekt konfiguriert sind, um die spezifische PROXY-Protokoll-Version (v1 oder v2) zu senden und zu empfangen. Nichtübereinstimmungen führen zu Verbindungsfehlern.
- Leistung: Der durch den PROXY-Protokoll-Header verursachte Overhead ist minimal, insbesondere mit dem binären Format von v2. Das Parsen bei jeder Verbindung verursacht jedoch geringe, vernachlässigbare Verarbeitungskosten.
- Überwachung: Überwachen Sie die Protokolle Ihres Backend-Servers und den Netzwerkverkehr, um zu überprüfen, ob Client-IPs korrekt identifiziert werden und keine unerwarteten PROXY-Protokollfehler auftreten.