G DATA XDR

Traffic-Reduzierung durch Update-Caching mit HAProxy

Einleitung

Dieser Artikel beschreibt, wie Sie den Netzwerk-Traffic zwischen den G DATA Agenten und dem G DATA Backend reduzieren. Dazu speichert ein lokal betriebener HAProxy die eigentlichen Datei-Downloads von Updates zwischen (Caching) über Port 80. Der vorgelagerte Abgleich von Dateiliste und Hashsummen ist davon nicht betroffen, dieser wird über Port 443 unabhängig durchgeführt und nicht gecacht.

Ein Caching-Proxy bringt den Vorteil, dass die Downloadmenge auf Kundenseite sinkt. Updates werden nur einmal aus dem Internet geladen und danach lokal an alle Agenten im Netzwerk verteilt.

Dieser Artikel richtet sich vor allem an Administratoren mit Linux- und Netzwerk-Kenntnissen. Technische Fachbegriffe werden zusätzlich kurz erklärt. So können auch Leser ohne tiefes IT-Hintergrundwissen dem Ablauf folgen.

Hintergrundwissen: Was ist HAProxy und was macht ein Caching-Proxy?

Wenn viele G DATA Agenten im selben Netzwerk laufen, lädt normalerweise jeder Agent einzeln die Signatur- und Programm-Updates direkt aus dem Internet vom G DATA Update-Server herunter. Bei hundert Endpunkten bedeutet das hundert identische Downloads über Ihre Internetleitung.

Ein Proxy ist ein Vermittler zwischen den G DATA Agenten und dem G DATA Backend. Ein Cache ist ein Zwischenspeicher. Die erste Anfrage nach einer Update-Datei wird normal ins Internet weitergeleitet. Die Antwort wird zusätzlich lokal gespeichert. Jede weitere Anfrage nach derselben Datei wird direkt aus diesem lokalen Speicher beantwortet. Das Internet wird dabei nicht erneut belastet.

HAProxy ist eine weit verbreitete, quelloffene Software. Sie übernimmt diese Aufgabe zuverlässig als TCP/HTTP-Proxy mit Caching-Funktion.

Voraussetzungen

  • Ein Linux-Server (z. B. Debian/Ubuntu) im Netzwerk. Alle G DATA Agenten müssen diesen Server erreichen können.

  • Root- bzw. sudo-Rechte auf diesem Server.

  • Ein gültiges TLS-Zertifikat, inklusive Zertifikatskette. Es gilt für den Hostnamen, unter dem die Agenten den Proxy per HTTPS ansprechen (Index- und Metadaten-Anfragen).

  • Netzwerkfreigaben:

    • Der Proxy-Server muss den G DATA Update-Server agent-update-server.gdatasecurity.de erreichen können. Dafür sind zwei Ports nötig: HTTPS Port 443 und HTTP Port 80.

    • Die G DATA Agenten müssen den Proxy-Server ebenfalls über HTTPS Port 443 und HTTP Port 80 erreichen können.

  • Grundkenntnisse im Umgang mit HAProxy-Konfigurationsdateien sind hilfreich, auch wenn diese Dokumentation eine fertige Vorlage bereitstellt.

Erreichbarkeit der G DATA Cloud

Zur Sicherstellung des der zuverlässigen und zeitnahen Meldung von Ereignissen und Vorfällen muss die G DATA Cloud erreichbar sein und darf nicht durch eine Firewall blockiert werden. Dafür sind folgend aufgeführten Einstellungen notwendig. Es muss sichergestellt werden, dass *.gdatasecurity.de und *.gdatasoftware.com aufgelöst werden können und erreichbar sind.

  • Portfreigaben

    • Die G DATA Agenten auf den Endpunkten müssen die IPs unserer Backend-Server über Port TCP/443, IP-Range 194.156.84.0/22 (194.156.84.0 - 194.156.87.255) erreichen können.

  • Protokolle

    • Die Systeme müssen über die Protokolle HTTPS:// sowie auch WSS:// kommunizieren können.

  • TLS

Einrichtung des HAProxys

Schritt 1: HAProxy installieren

Installieren Sie HAProxy über den Paketmanager Ihrer Linux-Distribution, zum Beispiel unter Debian/Ubuntu:

sudo apt update
sudo apt install haproxy
Schritt 2: Zertifikat vorbereiten

HAProxy terminiert die TLS-Verbindung der Agenten. Dafür benötigt es ein Zertifikat samt zugehörigem privaten Schlüssel.

HAProxy erwartet Zertifikat, Zertifikatskette und privaten Schlüssel in einer einzigen PEM-Datei, kombiniert in dieser Reihenfolge. Die einzelnen Bestandteile sind:

Reihenfolge Bestandteil

1

Das eigentliche Zertifikat (Server-Zertifikat).

2

Die Zwischenzertifikate, auch Bundle oder Chain genannt.

3

Das Root-CA-Zertifikat, sofern separat vorhanden.

4

Der private Schlüssel.

Fügen Sie die Dateien in genau dieser Reihenfolge zu einer PEM-Datei zusammen. Beispiel:

cat server.crt intermediate.crt root-ca.crt server.key > /etc/haproxy/certs/haproxy-cache.pem
chmod 640 /etc/haproxy/certs/haproxy-cache.pem
chown root:haproxy /etc/haproxy/certs/haproxy-cache.pem
Schritt 3: HAProxy-Konfiguration erstellen

Legen Sie die Konfigurationsdatei haproxy.cfg unter /etc/haproxy/ an. Nutzen Sie dafür die unten stehende Vorlage (siehe Vollständige Beispielkonfiguration). Ersetzen Sie eine bestehende Datei durch diese Vorlage.

Passen Sie dabei folgende Platzhalter an:

Platzhalter Bedeutung

{{ haproxy_caching_bind }}

Die IP-Adresse, auf der HAProxy lauscht. Das ist die IP, unter der die Agenten den Proxy erreichen.

{{ haproxy_caching_server_cert }}

Der vollständige Pfad zur PEM-Zertifikatsdatei aus Schritt 2, z. B. /etc/haproxy/certs/haproxy-cache.pem.

{{ haproxy_caching_server }}

Der interne Hostname, unter dem die Agenten den Caching-Server ansprechen. Dieser Name wird im Host-Header erwartet.

Schritt 4: HAProxy (neu) starten

Starten Sie den Dienst neu, nachdem Sie die Konfiguration erstellt oder geändert haben:

sudo systemctl restart haproxy
sudo systemctl enable haproxy
Schritt 5 (optional): Konfiguration prüfen

Prüfen Sie die Syntax der Konfigurationsdatei, bevor Sie HAProxy neu starten. So erkennen Sie Tippfehler frühzeitig:

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

Eine fehlerfreie Prüfung meldet Configuration file is valid.

Vollständige Beispielkonfiguration

Die folgende Datei haproxy.cfg dient als Vorlage. Ersetzen Sie die drei Platzhalter. Die Bedeutung der Platzhalter steht in Einrichtung des HAProxys.

global
  log /dev/log  sample 1:10 local0
  log /dev/log  sample 1:10 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                     256000
  hard-stop-after             15m
  tune.ssl.default-dh-param   2048

defaults
  log     global
  mode    http
  option  httplog
  option  dontlognull
  option  http-keep-alive
  option  forwardfor
  timeout     http-request 10s
  timeout     queue 1m
  timeout     connect 10s
  timeout     client 20s
  timeout     server 20s
  timeout     http-keep-alive 10s
  timeout     check 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

frontend stats
  bind {{ haproxy_caching_bind }}:8404 ssl crt {{ haproxy_caching_server_cert }} alpn h2,http/1.1
  stats enable
  stats uri /
  stats refresh 10s
  http-request set-log-level silent
  http-request use-service prometheus-exporter if { path /metrics }

# ---------------------------------------------------------------------------
# Port 80 (HTTP): eigentlicher Datei-Download - HIER findet das Caching statt.
# ---------------------------------------------------------------------------
frontend http_update_server
  bind {{ haproxy_caching_bind }}:80
  acl is_update_download path_beg /api/v2/update/download/
  acl is_caching_host req.hdr(host) -i {{ haproxy_caching_server }}
  http-request set-header X-Forwarded-Host %[req.hdr(Host)]
  http-request set-header Host %[req.hdr(Host)]
  # Nur Download-Anfragen an den bekannten Hostnamen werden gecacht bedient.
  use_backend http_update_server_backend if is_update_download is_caching_host
  # Alle anderen Anfragen auf Port 80 sicherheitshalber auf HTTPS umleiten.
  http-request redirect scheme https code 301 unless is_update_download
  default_backend nomatch

# ---------------------------------------------------------------------------
# Port 443 (HTTPS): Index-/Hash-Abgleich - reiner Pass-through OHNE Caching.
# Diese Antworten sind klein, ändern sich häufig und werden von G DATA
# bewusst nicht für das Caching vorgesehen.
# ---------------------------------------------------------------------------
frontend https_update_server
  bind {{ haproxy_caching_bind }}:443 ssl crt {{ haproxy_caching_server_cert }} alpn h2,http/1.1
  http-request set-header X-Forwarded-Host %[req.hdr(Host)]
  http-request set-header Host %[req.hdr(Host)]
  use_backend https_update_server_backend if { req.hdr(host) -i {{ haproxy_caching_server }} }
  default_backend nomatch

cache objectcache_update_server
  total-max-size 3000
  max-object-size 200000000
  max-age 86400

backend http_update_server_backend
  balance roundrobin
  http-request set-header Connection keep-alive
  http-request set-header Host agent-update-server.gdatasecurity.de
  http-request set-header X-Forwarded-Proto http
  http-request cache-use objectcache_update_server if { path_beg /api/v2/update/download/ }
  http-response cache-store objectcache_update_server
  option httpchk GET /api/status
  http-check send hdr Host agent-update-server.gdatasecurity.de
  http-check expect status 200
  server agent-update-server.gdatasecurity.de agent-update-server.gdatasecurity.de:80 check inter 10s

backend https_update_server_backend
  balance roundrobin
  http-request set-header Connection keep-alive
  http-request set-header Host agent-update-server.gdatasecurity.de
  http-request set-header X-Forwarded-Proto https
  option httpchk GET /api/status
  http-check send hdr Host agent-update-server.gdatasecurity.de
  http-check expect status 200
  server agent-update-server.gdatasecurity.de agent-update-server.gdatasecurity.de:443 check inter 10s check-sni agent-update-server.gdatasecurity.de sni str(agent-update-server.gdatasecurity.de) ssl verify required ca-file /etc/ssl/certs/ca-certificates.crt

backend nomatch
  errorfile 503 /etc/haproxy/errors/503.http

Erläuterung der Konfiguration

Die wichtigsten Abschnitte werden hier einzeln erklärt. So können auch Leser mit weniger HAProxy-Erfahrung die Konfiguration nachvollziehen.

Abschnitt Erläuterung

global / defaults

Grundlegende Prozess- und Verbindungseinstellungen. Beispiele: Logging, maximale Anzahl gleichzeitiger Verbindungen (maxconn), Standard-Timeouts. Diese Werte müssen Sie in der Regel nicht anpassen.

frontend stats

Stellt eine Statusseite auf Port 8404 bereit. Über diese Seite können Sie den Zustand von HAProxy beobachten, unter anderem im Prometheus-Format (/metrics).

frontend http_update_server

Der Eingangspunkt für die eigentlichen Datei-Downloads auf Port 80. Nur Anfragen unterhalb von /api/v2/update/download/ an den bekannten Hostnamen gehen an das cachende Backend. Alle anderen Anfragen auf Port 80 werden sicherheitshalber auf HTTPS umgeleitet.

frontend https_update_server

Der Eingangspunkt für die Index- und Hash-Abgleiche auf Port 443 (TLS). Hier prüft HAProxy, ob der angefragte Hostname ({{ haproxy_caching_server }}) zum Update-Backend passt. Nur dann leitet HAProxy die Anfrage weiter. Andernfalls landet die Anfrage im Backend nomatch und erhält den Fehler 503. An dieser Stelle findet kein Caching statt.

cache objectcache_update_server

Definiert den Zwischenspeicher. Drei Werte sind wichtig: die maximale Gesamtgröße des Caches (total-max-size, in MB), die maximale Größe einer einzelnen Datei (max-object-size, in Byte) und die maximale Verweildauer eines Objekts im Cache (max-age, in Sekunden). Die Vorlage nutzt rund 3 GB Gesamtgröße, bis zu 200 MB pro Datei und 24 Stunden Gültigkeit. Nur das HTTP-Backend nutzt diesen Cache.

backend http_update_server_backend

Leitet die Download-Anfragen unverschlüsselt (Port 80) an agent-update-server.gdatasecurity.de weiter. Die Zeile http-request cache-use …​ if { path_beg /api/v2/update/download/ } sorgt dafür, dass nur dieser Pfad gecacht wird. Der http-check prüft laufend, ob der G DATA Server erreichbar ist.

backend https_update_server_backend

Leitet die Index- und Hash-Anfragen verschlüsselt (Port 443, mit Zertifikatsprüfung) an denselben G DATA Server weiter. Dieses Backend enthält weder cache-use noch cache-store. Die Antworten werden durchgereicht, aber nicht gespeichert.

backend nomatch

Fängt alle Anfragen ab, die zu keinem bekannten Host passen. Diese Anfragen erhalten den Fehler 503. So verhindert die Konfiguration Missbrauch als offener Proxy.

HAProxy speichert nur Anfragen unterhalb des Pfads /api/v2/update/download/ über HTTP. Die Index- und Hash-Anfragen über HTTPS laufen unverändert weiter. Andere Kommunikationswege der Agenten, zum Beispiel Telemetrie oder Meldungen an das XDR-Backend, sind vom Caching nicht betroffen.

Agenten auf den Caching-Server umstellen

Wenn Sie die G DATA Agenten bereits auf den Endpunkten installiert haben, kontaktieren Sie den technischen Support unter der Telefonnummer +49 234 9762-901. Die Kollegen des Support werden Ihre G DATA Agenten gerne umstellen.

Haben Sie noch keine G DATA Agenten ausgerollt, erstellen Sie eine Setup-Konfiguration mit der Angabe der Proxy-Adresse. Alle Endpunkte, die mit der dazugehörigen SetupID installiert werden, erhalten Ihre Updates über Ihren Proxy.

Prüfen Sie unbedingt, ob die Konfiguration funktioniert. Endpunkte, die keine Updates erhalten, stellen ein Sicherheitsrisiko dar. Lassen Sie in der Konfiguration den Fallbackserver unbedingt an (er sollte nur in begründeten Ausnahmefällen abgeschaltet werden). Mit eingeschaltetem Fallbackserver erhalten Ihre Endpunkte auch Updates, wenn sie das Netzwerk verlassen (zum Beispiel Laptops) oder wenn Ihr Reverse-Proxyserver ausfällt.

Fehlersuche

Symptom Vorgehen

HAProxy startet nicht

Prüfen Sie die Konfiguration mit haproxy -c -f /etc/haproxy/haproxy.cfg. Kontrollieren Sie zusätzlich den Dienststatus mit systemctl status haproxy und journalctl -u haproxy.

Agenten erhalten Zertifikatsfehler

Prüfen Sie zwei Dinge: Enthält die PEM-Datei Zertifikat, Zwischenzertifikate und privaten Schlüssel in der korrekten Reihenfolge? Passt der Hostname im Zertifikat zu {{ haproxy_caching_server }}?

Kein Rückgang des Internet-Traffics erkennbar

Prüfen Sie über die Statusseite (frontend stats, Port 8404), ob die Download-Anfragen über das Backend http_update_server_backend laufen und ob dort Cache-Treffer entstehen. Das Backend https_update_server_backend cacht bewusst nicht.

Anfragen landen im Backend nomatch

Der Host-Header der eingehenden Anfrage stimmt nicht mit {{ haproxy_caching_server }} überein. Prüfen Sie die Agenten-Konfiguration und die DNS-Auflösung.