Aktualisiert am 31. Okt. 2026
Docker
Wenn Ihre Dienste mit Docker Compose laufen, fügen Sie dem Projekt unseren Container hinzu, und
sie sind über Ihre eigene öffentliche IPv4-Adresse aus dem Internet erreichbar, ohne dass Sie an
den Diensten selbst etwas ändern. Eingehender Verkehr kommt über den Tunnel an statt über einen
veröffentlichten Port. Sie fügen also keine ports:-Einträge hinzu, Sie brauchen keine routbare
Adresse von Ihrem Internetanbieter, und weder an Ihrem Router noch an Ihrer Host-Firewall muss
etwas geöffnet werden.
Bevor Sie beginnen
- Eine GetPublicIP-IP-Adresse und ihr API-Schlüssel. Siehe API-Schlüssel erstellen
- Linux: Docker Engine und Compose v2, also
docker composestatt des älteren Skriptsdocker-compose - macOS: Docker Desktop, auf Intel oder Apple Silicon
- Windows: Docker Desktop im Modus für Linux-Container, mit einem WSL2-Kernel 6.6. Prüfen
Sie das mit
wsl --versionund führen Siewsl --updateaus, falls eine ältere Version angezeigt wird, denn Kernels vor 6.6 fehlt ein Netfilter-Modul, das der Tunnel benötigt
Alles auf dieser Seite funktioniert unverändert unter Windows und macOS mit Docker Desktop, ohne dass Sie außer Docker Desktop selbst etwas installieren müssen. Docker Desktop ist kostenlos für die private Nutzung, für Bildung, für nicht kommerzielle Open-Source-Projekte und für kleine Unternehmen mit weniger als 250 Beschäftigten und unter 10 Mio. USD Jahresumsatz; größere Organisationen brauchen ein kostenpflichtiges Abonnement von Docker. Details zu den einzelnen Systemen finden Sie unter macOS und Windows.
Das Image wird für linux/amd64 und linux/arm64 unter
ghcr.io/getpublicip/getpublicip veröffentlicht.
API-Schlüssel in eine .env-Datei eintragen
Legen Sie neben Ihrer Compose-Datei eine Datei .env an. Weitere Informationen finden Sie
unter API-Schlüssel erstellen.
GETPUBLICIP_API_KEY=your-api-key-from-the-dashboard
Compose liest die .env-Datei automatisch. Deshalb verweisen die Compose-Dateien unten auf
${GETPUBLICIP_API_KEY}, statt den Schlüssel selbst zu enthalten. Tragen Sie .env in Ihre
.gitignore ein.
Zur Docker-Compose-Datei hinzufügen
Fügen Sie diesen Dienst neben den Containern hinzu, die Sie bereits betreiben:
services:
getpublicip:
image: ghcr.io/getpublicip/getpublicip:latest
restart: unless-stopped
environment:
GETPUBLICIP_API_KEY: "${GETPUBLICIP_API_KEY}"
GETPUBLICIP_MAPPINGS: "8080/tcp->web:80; 443/tcp->web:443"
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
sysctls:
net.ipv4.ip_forward: 1
net.ipv4.conf.all.src_valid_mark: 1
net.ipv6.conf.all.forwarding: 1
networks:
- appnet
Ersetzen Sie appnet durch das Netzwerk, in dem Ihre Dienste bereits laufen, und web durch
die Namen Ihrer eigenen Dienste. Alles andere kann bleiben, wie es ist.
Behalten Sie restart: unless-stopped bei. Darüber erholt sich der Agent von Fehlern, die er
nicht an Ort und Stelle beheben kann, wie unter
Verbindungsabbrüche beschrieben.
Ein vollständiges, funktionierendes Beispiel
Wenn Sie noch kein Compose-Projekt haben, ist diese Datei ein komplettes Setup: ein Webserver
auf Ihrer eigenen öffentlichen IP-Adresse, von überall erreichbar. Speichern Sie sie als
compose.yaml:
services:
web:
image: nginx:alpine
restart: unless-stopped
networks:
- appnet
getpublicip:
image: ghcr.io/getpublicip/getpublicip:latest
restart: unless-stopped
environment:
GETPUBLICIP_API_KEY: "${GETPUBLICIP_API_KEY}"
GETPUBLICIP_MAPPINGS: "80/tcp->web:80"
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
sysctls:
net.ipv4.ip_forward: 1
net.ipv4.conf.all.src_valid_mark: 1
net.ipv6.conf.all.forwarding: 1
networks:
- appnet
networks:
appnet:
Starten Sie es dann:
docker compose up -d
Warten Sie etwa 30 bis 60 Sekunden und öffnen Sie http://{YOUR IP ADDRESS} aus einem
beliebigen Netzwerk oder mit Ihrem Smartphone über mobile Daten. Sehen Sie die
Willkommensseite von nginx, hat eine Anfrage aus dem Internet Ihren Container erreicht.
web hat keinen ports:-Eintrag. Der Agent erreicht nginx über das interne Netzwerk
appnet, und beide Dienste sind Mitglied davon, weil der Agent web über den Dienstnamen
auflöst, was nur in einem Netzwerk funktioniert, das beide gemeinsam nutzen. Würden Sie die
networks:-Blöcke weglassen, legte Compose beide in das Standardnetzwerk des Projekts, und das
funktioniert genauso gut. Ein benanntes Netzwerk macht die Voraussetzung aber sichtbar.
Ports zuordnen
GETPUBLICIP_MAPPINGS legt fest, welche Ports Ihrer öffentlichen IP-Adresse an welchen Ihrer
Container gehen. Trennen Sie Einträge mit ; oder Zeilenumbrüchen:
publicPort[/proto[,proto]][/stack[,stack]]->service[:internalPort]
| Teil | Standard | Hinweise |
|---|---|---|
publicPort | keiner | ein einzelner Port oder ein Bereich wie 60000-60099 |
proto | tcp | tcp oder udp; für beide durch Komma trennen |
stack | ipv4 | ipv4 oder ipv6; für Dual-Stack durch Komma trennen |
service | keiner | das Ziel, zur Laufzeit aufgelöst: ein Compose-Dienstname, ein beliebiger auflösbarer Hostname oder eine feste IPv4-Adresse |
internalPort | wie publicPort | der Port am Ziel; bei einem Bereich weglassen oder denselben Bereich wiederholen |
| Beispiel | Bedeutung |
|---|---|
8080/tcp->web:80 | TCP 8080 auf Ihrer öffentlichen IP-Adresse geht an web auf Port 80 |
443/tcp,udp->web:443 | TCP und UDP 443 gehen an web auf Port 443 |
53/udp->dns:53 | UDP 53 geht an dns auf Port 53 |
9000/tcp/ipv4,ipv6->api | Dual-Stack; der interne Port ist standardmäßig 9000 |
60000-60099/udp->turn | UDP 60000 bis 60099 gehen an turn auf dieselben Ports |
Die Segmente nach dem Port werden anhand von Schlüsselwörtern erkannt, ihre Reihenfolge spielt
also keine Rolle. 8080/tcp/ipv4 und 8080/ipv4/tcp bedeuten dasselbe.
Sprechen Sie Ihre Container über den Dienstnamen an, niemals über die IP-Adresse. Compose vergibt Container-IPs dynamisch. Der Agent löst die Namen deshalb selbst auf und prüft sie alle 30 Sekunden erneut. Startet ein Container mit einer anderen IP-Adresse neu, passt der Agent die Weiterleitungsregeln an.
Ein Ziel kann auch ein beliebiger auflösbarer Hostname oder eine feste IPv4-Adresse sein, und alle drei Varianten verhalten sich gleich. Eine feste IPv6-Adresse wird nicht akzeptiert; verwenden Sie stattdessen einen Hostnamen mit einem AAAA-Eintrag.
Portbereiche
Manche Dienste brauchen statt eines einzelnen Ports einen ganzen Block: ein TURN-Server für Sprach- und Videoanrufe, FTP im passiven Modus oder alles, was RTP-Medien überträgt. Geben Sie den öffentlichen Port als Bereich an, und jeder Port darin wird an denselben Port Ihres Containers weitergeleitet:
GETPUBLICIP_MAPPINGS: "3478/tcp,udp->turn; 60000-60099/udp->turn"
Port 60042 auf Ihrer öffentlichen IP-Adresse kommt immer an Port 60042 von turn an. Diese
Dienste teilen der Gegenseite mit, welchen Port sie verwenden soll, und ein Port, der sich auf
dem Weg hinein geändert hat, würde die Verbindung ohne jede Fehlermeldung unterbrechen.
Aus demselben Grund kann ein Bereich nur an denselben Bereich gehen. Sie können den internen
Port weglassen, wie oben, oder den Bereich exakt wiederholen
(60000-60099/udp->turn:60000-60099). Eine Weiterleitung an andere Ports, etwa
->turn:61000-61099, wird beim Start des Containers mit
a port range must forward to the same range abgelehnt. Ein Bereich darf außerdem nicht
Port 51820 enthalten, den der Tunnel selbst verwendet.
Öffnen Sie nur so viele Ports, wie Ihr Dienst nutzen soll. Bei einem TURN-Server ist
das der Relay-Bereich, aus dem er laut Konfiguration Ports vergibt, und nicht alles oberhalb
von 49152. Dafür ist das Image 1.3.1 oder neuer erforderlich.
IPv6 weiterleiten
Zuordnungen gelten nur für IPv4, sofern Sie nichts anderes angeben. Fügen Sie also den Stack
ipv6 hinzu, um Ihre öffentliche IPv6-Adresse weiterzuleiten, oder ipv4,ipv6, um beide
weiterzuleiten. Damit das funktioniert, müssen zwei Dinge zusammenpassen.
In Ihrem Compose-Netzwerk muss IPv6 aktiviert sein. Docker-Bridge-Netzwerke sind
standardmäßig reine IPv4-Netzwerke, ein Container darin hat also keine IPv6-Adresse, an die der
Agent weiterleiten könnte. Geben Sie dem Netzwerk enable_ipv6: true und ein IPv6-Subnetz:
networks:
appnet:
enable_ipv6: true
ipam:
config:
- subnet: 172.29.7.0/24
- subnet: fd00:dead:beef::/64
Der Stack gilt für das Ziel ebenso wie für den öffentlichen Port. Die Weiterleitungsregeln
können nicht zwischen den beiden Adressfamilien übersetzen, eine IPv6-Anfrage muss Ihren
Container also über IPv6 erreichen. 8080/tcp/ipv4,ipv6->web:80 setzt daher voraus, dass web
sowohl eine IPv4- als auch eine IPv6-Adresse hat, und genau die liefert das Netzwerk oben.
Behalten Sie net.ipv6.conf.all.forwarding: 1 im sysctls-Block des Agenten bei. Es steht
bereits in den Beispielen auf dieser Seite und wird nur benötigt, wenn Sie IPv6 weiterleiten.
Fehlt etwas, nennt Ihnen der Agent mit
no destination resolved in the family its mapping asked for, welches Ziel und welche
Adressfamilie betroffen sind. Erscheint diese Zeile bei einer ipv6-Zuordnung in einem
ansonsten gesunden Setup, fehlt dem Netzwerk fast immer enable_ipv6.
SSL / TLS
GetPublicIP arbeitet auf Paketebene. Es leitet TCP und UDP an Ihre Container weiter, und Verschlüsselung und Zertifikate bleiben bei Ihnen: Wenn Sie HTTPS anbieten, terminiert Ihr eigener Dienst die TLS-Verbindung. Ordnen Sie Port 443 dem Container zu, der Ihr Zertifikat bereits hat, und Ihr TLS-Setup bleibt, wie es ist:
GETPUBLICIP_MAPPINGS: "443/tcp->web:443; 80/tcp->web:80"
Wir entschlüsseln Ihren Datenverkehr nicht
Ihre öffentliche IP-Adresse ist kein TLS-Proxy. Sie besitzt keines Ihrer Zertifikate oder privaten Schlüssel und hat daher nichts, womit sie entschlüsseln könnte. Die TLS-Sitzung wird direkt zwischen dem Browser Ihres Besuchers und Ihrem eigenen Dienst ausgehandelt und bleibt auf dem gesamten Weg verschlüsselt: aus dem Browser hinaus, über das Internet zu Ihrer öffentlichen IP-Adresse, durch den WireGuard-Tunnel und in Ihren Container, wo sie zum ersten Mal entschlüsselt wird.
Der Tunnel fügt zwischen unserem Netzwerk und Ihrem Rechner eine zweite, äußere Verschlüsselungsschicht hinzu, und darin wird derselbe TLS-Chiffretext transportiert, den Ihr Besucher gesendet hat. Ihre Zertifikate und privaten Schlüssel verlassen niemals Ihren Rechner, und Ihr Datenverkehr wird unterwegs nie entschlüsselt und neu verschlüsselt. Wir entschlüsseln keinen TLS-Datenverkehr und haben das auch nicht vor.
Ihr Dienst braucht ein gültiges Zertifikat
Da das Zertifikat bei dem Dienst liegt, der die Verbindung terminiert, braucht dieser Dienst ein gültiges Zertifikat, genau wie auf jedem anderen öffentlichen Host.
- Richten Sie eine Domain auf Ihre öffentliche IP-Adresse. Legen Sie einen
A-Eintrag für Ihre IPv4-Adresse an und einenAAAA-Eintrag, wenn Sie auch IPv6 anbieten. Zertifizierungsstellen stellen Zertifikate für Domainnamen aus, eine nackte IP-Adresse reicht also nicht. - Holen Sie sich das Zertifikat von Let's Encrypt. Das ist kostenlos und automatisiert. Caddy und Traefik beantragen und erneuern es für Sie, ohne dass Sie mehr als Ihren Domainnamen konfigurieren müssen; nginx und Apache kombinieren Sie mit certbot.
- Wenn Sie eine HTTP-01-Challenge verwenden, ordnen Sie neben Port 443 auch Port 80 demselben Dienst zu. Let's Encrypt verbindet sich mit Port 80 Ihrer öffentlichen IP-Adresse, um die Challenge zu prüfen, und scheitert, wenn nur 443 zugeordnet ist. Eine DNS-01-Challenge braucht Port 80 nicht.
- Lassen Sie diese Ports zugeordnet. Die Erneuerung wiederholt dieselbe Challenge etwa alle 60 Tage und schlägt ohne Hinweis fehl, wenn die Zuordnung verschwunden ist.
Unverschlüsseltes HTTP bleibt unverschlüsselt
Eine Zuordnung auf Port 80, über die unverschlüsseltes HTTP ausgeliefert wird, ist zwischen Ihrem Besucher und Ihrer öffentlichen IP-Adresse unverschlüsselt, genau wie überall sonst im Internet. Der WireGuard-Tunnel deckt nur die Strecke zwischen unserem Netzwerk und Ihrem Rechner ab. Wenn die Inhalte wichtig sind, aktivieren Sie TLS.
Weiterleitung an einen Dienst auf dem Host
Um einen Dienst, der direkt auf dem Docker-Host läuft, öffentlich zu machen, lassen Sie eine
Zuordnung auf host.docker.internal zeigen:
services:
getpublicip:
environment:
GETPUBLICIP_MAPPINGS: "8081/tcp->host.docker.internal:8081"
extra_hosts:
- "host.docker.internal:host-gateway" # needed on Linux; built in on Docker Desktop
- Der Dienst auf dem Host muss auf
0.0.0.0lauschen, nicht auf127.0.0.1. Ein Dienst, der an Loopback gebunden ist, lehnt die Verbindung aus dem Container ab. Prüfen Sie das mitss -lntp. - Eine Host-Firewall verwirft den Verkehr stillschweigend, sofern Sie das Bridge-Subnetz
nicht eingehend auf
docker0bzw. derbr-*-Schnittstelle erlauben.
Ziele auf dem Host und in Containern lassen sich in einem einzigen GETPUBLICIP_MAPPINGS
beliebig mischen, außer mit
Die echte Client-IP-Adresse sehen,
denn damit funktionieren Ziele auf dem Host nicht.
Docker-Compose-Netzwerke
Da Ziele über den Dienstnamen aufgelöst werden, muss der Container getpublicip im selben
Docker-Netzwerk sein wie die Container, an die er weiterleitet.
- Ein Standardnetzwerk. Es funktioniert so, wie es ist.
- Mehrere Netzwerke. Tragen Sie
getpublicipin jedes Netzwerk ein, in dem ein Dienst liegt, an den er weiterleitet. - Ziele in einem anderen Compose-Projekt. Beide Projekte müssen einem gemeinsamen externen
Netzwerk beitreten:
docker network create shared
Dann in jeder Compose-Datei:services: getpublicip: networks: - shared networks: shared: external: true
Stimmt hier etwas nicht, wiederholen die Logs waiting for destinations to resolve, und der
Agent versucht es weiter, statt sofort abzubrechen.
Logs prüfen
docker compose up -d
docker compose logs -f getpublicip
Bei einem gesunden Start baut der Agent den Tunnel auf der Schnittstelle pi0 auf, löst Ihre
Ziele auf, installiert die Weiterleitungsregeln und überträgt die Zuordnungen an GetPublicIP.
Danach läuft der Agent weiter und prüft die Ziele und den Tunnel selbst alle 30 Sekunden.
Ein gesunder Tunnel schreibt eine Zeile wie diese ins Log. Merken Sie sie sich als Vergleich, falls der Tunnel später Probleme macht:
tunnel status up=true interfaces=1 peers=1 healthy=true handshakeAge=31s rxDelta=0
Achten Sie auf healthy=true. up=true bedeutet nur, dass die Schnittstelle existiert, und
bleibt auch bei einem Tunnel true, der keinen Verkehr mehr durchlässt.
Testen
Warten Sie vor dem Testen etwa 30 bis 60 Sekunden. Wenn neue Zuordnungen übertragen werden,
wechselt Ihre IP-Adresse in den Zustand updating, während wir sie anwenden, und Anfragen in
diesem Zeitraum schlagen fehl. Zwei oder drei Fehlschläge, gefolgt von Erfolg, sind normal.
Testen Sie aus einem Netzwerk, das nicht Ihr eigenes ist. Am einfachsten geht das über mobile Daten:
curl http://{YOUR IP ADDRESS}
Verbindungsabbrüche
Der Tunnel baut sich nach einem Verbindungsabbruch, einem Neustart des Routers oder einer neuen Adresse von Ihrem Internetanbieter von selbst wieder auf, ohne dass Sie etwas neu starten oder konfigurieren müssen.
Meistens repariert er sich, ohne dass der Agent etwas tun muss. Der Tunnel ist eine ausgehende Verbindung, die alle 25 Sekunden durch einen Keepalive offen gehalten wird, und unser Server lernt Ihre Adresse aus jedem Paket neu, das der Agent sendet. Verwirft Ihr Router also die Zuordnung oder weist Ihnen einen neuen Port zu, stellt der nächste Keepalive sie wieder her.
Bei den selteneren Fehlern, die ein Keepalive nicht beheben kann, beendet sich der Agent, statt
den Tunnel an Ort und Stelle zu reparieren, und Docker startet ihn mit einer frischen
Verbindung neu. Im Log sehen Sie zuerst tunnel appears broken, sobald er das Problem bemerkt,
und dann exiting so the container is restarted, wenn es über mehrere Prüfungen hinweg
bestehen bleibt. Beide Zeilen gehören zur normalen Wiederherstellung.
Die Wiederherstellung hängt von Ihrer Restart-Policy ab, behalten Sie also
restart: unless-stopped für den Dienst bei. Ohne sie stoppt der Container und bleibt gestoppt.
Solange die Internetverbindung Ihres Hosts ausgefallen ist, sind auch Ihre Dienste nicht erreichbar. Der Tunnel baut sich wieder auf, sobald eine Verbindung verfügbar ist.
Die echte Client-IP-Adresse sehen
Standardmäßig sehen Ihre Container nicht die IP-Adresse des Besuchers. Der GetPublicIP-Container
schreibt beim Weiterleiten die Quelladresse des eingehenden Verkehrs um, und jeder Besucher
erscheint in Ihren Access-Logs daher mit derselben lokalen IP-Adresse. Geolokalisierung, Rate
Limiting pro Client, Missbrauchssperren und fail2ban sehen alle nur eine IP-Adresse.
GETPUBLICIP_PRESERVE_CLIENT_IP schaltet das Umschreiben ab, und Ihre Container sehen dann die
echte IP-Adresse des Clients.
Dafür muss jeder Dienst geändert werden, an den Sie weiterleiten. Lesen Sie deshalb diesen
Abschnitt, bevor Sie es aktivieren.
Solange die Quelladresse auf eine im Compose-Netzwerk umgeschrieben wird, antworten Ihre Dienste
automatisch über den GetPublicIP-Container. Ist GETPUBLICIP_PRESERVE_CLIENT_IP aktiv, muss die
Standardroute jedes Dienstes auf den GetPublicIP-Container zeigen, damit seine Antworten über
Ihre öffentliche IP-Adresse zum Client zurückgelangen. Ohne diese Route gehen die Antworten über
Ihren normalen Internetanschluss hinaus, und der Client verwirft sie.
Dafür ist das Image 1.1.0 oder neuer erforderlich.
Die Einstellung gilt für den ganzen Agenten und nicht für eine einzelne Zuordnung, sie wirkt sich also auf jeden Dienst aus, an den dieser Agent weiterleitet.
Warum sich die Standardroute ändern muss
Alles Weitere in diesem Abschnitt folgt daraus, was mit einer eingehenden Anfrage und ihrer ausgehenden Antwort geschieht:
Ablauf im Standardmodus
visitor 203.0.113.9 → your public IP → tunnel → agent
agent rewrites the source to its own address, 172.29.7.2
web replies to 172.29.7.2, which is on its own subnet
agent puts the real address back, reply leaves through the tunnel
Ablauf mit erhaltener Client-IP
visitor 203.0.113.9 → your public IP → tunnel → agent
web sees 203.0.113.9 and then send replies to 203.0.113.9
the web container reply will follow the default route
Ein Container entscheidet, wohin er eine Antwort schickt, indem er zuerst sein eigenes Subnetz und dann seine Standardroute betrachtet. Solange die Quelladresse umgeschrieben wird, ist jede Antwort an etwas im lokalen Subnetz adressiert, und die Standardroute kommt nie ins Spiel. Ist die Erhaltung der Client-IP aktiv, ist jede Antwort an ein Ziel irgendwo im Internet adressiert, also entscheidet die Standardroute über alle. Die Lösung ist daher eine Route, die in jedem Dienst gesetzt wird, und keine Einstellung am Agenten kann sie ersetzen.
Docker bietet dafür keine eingebaute Möglichkeit. Die Beispiele unten setzen die Standardroute jedes Dienst-Containers deshalb mit einem kleinen Sidecar-Container.
Beispielprojekt
Es gibt zwei Versionen desselben Projekts. Beginnen Sie mit der reinen IPv4-Variante, sofern Sie nicht auch Ihre öffentliche IPv6-Adresse weiterleiten. Jede IPv6-Zeile unten muss zusätzlich stimmen, und ein halb fertiges IPv6-Setup ergibt einen Dienst, der über IPv4 funktioniert und über IPv6 hängt.
Nur IPv4
services:
getpublicip:
image: ghcr.io/getpublicip/getpublicip:latest
restart: unless-stopped
environment:
GETPUBLICIP_API_KEY: "${GETPUBLICIP_API_KEY}"
GETPUBLICIP_MAPPINGS: "80/tcp->web:80"
GETPUBLICIP_PRESERVE_CLIENT_IP: "true"
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
sysctls:
net.ipv4.ip_forward: 1
net.ipv4.conf.all.src_valid_mark: 1
networks:
appnet:
ipv4_address: 172.29.7.2 # fixed, because the sidecar routes to it
web:
image: nginx:alpine
restart: unless-stopped
networks:
appnet:
ipv4_address: 172.29.7.3 # give every service a fixed address, not just the agent
# Points web's default route at the agent, from inside web's own network
# namespace. Runs once and exits.
web-route:
image: alpine:3.20
network_mode: "service:web"
cap_add:
- NET_ADMIN
restart: "no"
command: sh -c 'ip route replace default via 172.29.7.2'
depends_on:
web:
condition: service_started
restart: true # re-run this sidecar whenever web restarts
getpublicip:
condition: service_started
networks:
appnet:
driver: bridge
ipam:
config:
- subnet: 172.29.7.0/24
gateway: 172.29.7.1
IPv4 und IPv6
Dasselbe Projekt mit der IPv6-Hälfte. Vier Dinge ändern sich: Das Netzwerk erhält
enable_ipv6: true und ein IPv6-Subnetz, jeder Dienst erhält eine feste ipv6_address, der
Agent erhält den sysctl net.ipv6.conf.all.forwarding, und der Sidecar setzt eine zweite
Standardroute.
services:
getpublicip:
image: ghcr.io/getpublicip/getpublicip:latest
restart: unless-stopped
environment:
GETPUBLICIP_API_KEY: "${GETPUBLICIP_API_KEY}"
GETPUBLICIP_MAPPINGS: "80/tcp/ipv4,ipv6->web:80"
GETPUBLICIP_PRESERVE_CLIENT_IP: "true"
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
sysctls:
net.ipv4.ip_forward: 1
net.ipv4.conf.all.src_valid_mark: 1
net.ipv6.conf.all.forwarding: 1
networks:
appnet:
ipv4_address: 172.29.7.2 # fixed, because the sidecar routes to it
ipv6_address: fd00:c0de:7::2
web:
image: nginx:alpine
restart: unless-stopped
networks:
appnet:
ipv4_address: 172.29.7.3 # give every service a fixed address, not just the agent
ipv6_address: fd00:c0de:7::3
# Points web's default routes at the agent, from inside web's own network
# namespace. Runs once and exits. Both families need their own route.
web-route:
image: alpine:3.20
network_mode: "service:web"
cap_add:
- NET_ADMIN
restart: "no"
command: >
sh -c 'ip route replace default via 172.29.7.2;
ip -6 route replace default via fd00:c0de:7::2'
depends_on:
web:
condition: service_started
restart: true # re-run this sidecar whenever web restarts
getpublicip:
condition: service_started
networks:
appnet:
driver: bridge
enable_ipv6: true
ipam:
config:
- subnet: 172.29.7.0/24
gateway: 172.29.7.1
- subnet: fd00:c0de:7::/64
gateway: fd00:c0de:7::1
Egal, mit welcher Variante Sie beginnen: Wiederholen Sie den Sidecar für jeden Dienst, an den Sie weiterleiten, und prüfen Sie die vier folgenden Punkte. Ist einer davon falsch, hängt der Dienst, ohne einen Fehler zu melden.
Geben Sie jedem Dienst im Netzwerk eine feste Adresse, nicht nur dem Agenten. Ein Dienst
ohne feste Adresse nimmt die niedrigste freie Adresse, und das ist die, die Sie für den Agenten
reserviert haben. Wegen depends_on startet er oft zuerst und belegt sie. Der Agent startet
dann überhaupt nicht und meldet Address already in use.
Wenn Sie IPv6 weiterleiten, setzen Sie beide Routen. Die IPv6-Standardroute ist unabhängig
von der IPv4-Route. Ein Sidecar, der nur die IPv4-Route setzt, lässt IPv6-Antworten also über
die Bridge hinausgehen, und diese Verbindungen hängen, während IPv4 funktioniert. Die zweite
Zeile ip -6 route replace im Dual-Stack-Beispiel setzt sie. Fehlt sie, ist das der häufigste
Grund, warum diese Variante schiefgeht, denn alles, was Sie über IPv4 testen, funktioniert.
Die Route überlebt keinen Neustart Ihres Dienstes. Docker baut einen neuen
Netzwerk-Namespace mit leerer Routingtabelle auf. Die Route ist also weg, und eingehender
Verkehr stoppt, bis der Sidecar wieder läuft. Darum kümmert sich das depends_on oben:
restart: true weist Compose an, den Sidecar bei jedem Neustart von web erneut auszuführen.
docker compose restart web und docker compose up -d reparieren die Route also beide von
selbst.
Nicht abgedeckt ist ein Neustart Ihres Dienstes, den Docker ohne Sie auslöst. Stürzt web ab
oder wird es vom Out-of-Memory-Killer beendet, holt seine eigene restart:-Policy es zurück,
ohne dass Compose beteiligt ist, und niemand führt den Sidecar erneut aus. Die Route fehlt,
eingehender Verkehr stoppt, und kein Problem wird gemeldet. Stellen Sie sie wieder her mit:
docker compose up -d web-route
Wir empfehlen, die Standardroute im Dockerfile des Dienstes zu setzen, damit sie solche
Neustarts übersteht. Andernfalls prüfen Sie die Routen mit docker exec web ip route und setzen
die Standardroute erneut, sobald sie fehlt.
Ziele auf dem Host funktionieren in diesem Modus nicht. Die Weiterleitung an einen Dienst auf dem Docker-Host setzt ebenfalls voraus, dass die Antwort über den Agenten zurückkommt, und dafür müsste die Standardroute des Hosts selbst geändert werden.
Prüfen, ob es funktioniert
Senden Sie eine Anfrage an Ihre IP-Adresse:
curl http://{YOUR IP ADDRESS} # one request through your public IP
docker compose logs --tail 10 web # what your container recorded
Das Log sollte die echte IP-Adresse des Clients zeigen. Zeigt es 172.29.7.2, ist die
Erhaltung der Client-IP nicht aktiv, und Sie sehen das Standardverhalten.
Ein Test vom Docker-Host selbst ist in Ordnung. Die Anfrage geht trotzdem hinaus an Ihre öffentliche IP-Adresse, erreicht unser Netzwerk und kommt durch den Tunnel zurück. Ihr Container zeichnet also die öffentliche Adresse Ihres Internetanschlusses auf, die sich leicht von der Bridge-Adresse unterscheiden lässt, die das Umschreiben dort eingetragen hätte.
Wenn Sie IPv6 weiterleiten, prüfen Sie es separat mit curl -6. Die beiden Adressfamilien
haben getrennte Standardrouten, eine kann also funktionieren, während die andere defekt ist.
Wenn es nicht funktioniert
Eine falsche Standardroute erzeugt keine Fehlermeldung. Verbindungen hängen, der Tunnel bleibt
aktiv und schreibt weiterhin healthy=true ins Log, die Weiterleitungsregeln bleiben korrekt,
und nichts in docker compose logs getpublicip meldet ein Problem, denn aus Sicht des Agenten
gibt es keines. Die Antworten Ihres Containers gehen auf dem falschen Weg hinaus statt über Ihre
öffentliche IP-Adresse.
Prüfen Sie die Routingtabelle im Dienst:
docker exec web ip route # default must be via the agent's address
docker exec web ip -6 route # and this one too, if you forward IPv6
Ausgehenden Datenverkehr über Ihre IP-Adresse senden
Die Abschnitte oben behandeln eingehenden Verkehr. GETPUBLICIP_OUTBOUND betrifft die andere
Richtung: Ihre Container erreichen das Internet über Ihre öffentliche IP-Adresse statt über die
Adresse Ihres Internetanbieters. Das hilft, wenn ein Dienst, mit dem Sie sich verbinden, nur
bekannte Adressen zulässt, oder wenn Ihr ausgehender Verkehr von derselben Adresse kommen soll
wie Ihr eingehender.
Es erfordert dieselbe Änderung der Standardroute wie die Erhaltung der Client-IP, aus demselben Grund: Die Antwort muss über den Agenten zurückkommen. Haben Sie den Sidecar dafür bereits eingerichtet, müssen Sie nur noch die Einstellung hinzufügen.
services:
getpublicip:
image: ghcr.io/getpublicip/getpublicip:latest
restart: unless-stopped
environment:
GETPUBLICIP_API_KEY: "${GETPUBLICIP_API_KEY}"
GETPUBLICIP_MAPPINGS: "80/tcp->web:80"
GETPUBLICIP_OUTBOUND: "true"
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
sysctls:
net.ipv4.ip_forward: 1
net.ipv4.conf.all.src_valid_mark: 1
net.ipv6.conf.all.forwarding: 1
networks:
appnet:
ipv4_address: 172.29.7.2
Lassen Sie dann jeden Container, der das nutzen soll, auf den Agenten zeigen, genau wie im Beispielprojekt oben. Ein Container, dessen Route Sie unverändert lassen, nutzt weiterhin die normale Docker-Bridge. Sie können die Dienste also einzeln umstellen.
Prüfen Sie es aus einem Container heraus, den Sie umgeleitet haben:
docker exec web curl -s https://api.getpublicip.com/ip
Es sollte Ihre GetPublicIP-Adresse angezeigt werden, nicht die Ihres Zuhauses oder Büros.
Nur ausgehend, ohne Portfreigaben
Wenn Sie nur die ausgehende Richtung brauchen, ist GETPUBLICIP_MAPPINGS optional:
environment:
GETPUBLICIP_API_KEY: "${GETPUBLICIP_API_KEY}"
GETPUBLICIP_OUTBOUND: "true"
Ein so gestarteter Agent lässt die Portfreigaben Ihrer IP-Adresse, wie sie sind, auch die, die Sie im Dashboard eingerichtet haben.
Was Sie vor dem Aktivieren wissen sollten
Ihre Container teilen sich eine Adresse. Alles hinter dem Agenten verlässt das Netz mit derselben öffentlichen IPv4- und derselben öffentlichen IPv6-Adresse. Die Gegenseite kann Ihre Container also nicht voneinander unterscheiden.
Das Verhalten ist ausfallsicher. Ein über den Agenten geleiteter Container hat gar kein Internet, solange der Tunnel unterbrochen ist, während er vorher Ihren normalen Anschluss genutzt hätte. Das ist Absicht, damit Ihr Verkehr nie ohne Ihr Wissen auf die Adresse Ihres Internetanbieters ausweicht. Überlegen Sie aber gut, bevor Sie etwas, auf das Sie angewiesen sind, über den Agenten leiten.
Wenn ein Container das Internet nicht erreicht, liegt das Problem fast immer an seiner Route und nicht am Agenten. Prüfen Sie im Container selbst:
docker exec web ip route # default must be via the agent's address
docker exec web ip -6 route # and this one too, if you use IPv6
Container-Berechtigungen
| Einstellung | Wofür sie benötigt wird |
|---|---|
cap_add: NET_ADMIN | Konfiguration der WireGuard-Schnittstelle und der Weiterleitungsregeln |
devices: /dev/net/tun | Das Tunnelgerät selbst |
net.ipv4.ip_forward=1 | Weiterleitung des Verkehrs vom Tunnel an Ihren Ziel-Container |
net.ipv4.conf.all.src_valid_mark=1 | Erforderlich für das Routing-Setup von wg-quick |
net.ipv6.conf.all.forwarding=1 | Nur nötig, wenn Sie IPv6 weiterleiten |
macOS
Verwenden Sie Docker Desktop, dann funktioniert die Compose-Datei oben unverändert, auf Intel ebenso wie auf Apple Silicon.
Andere Docker-Laufzeitumgebungen für macOS (Colima, OrbStack, Rancher Desktop) verwenden andere Kernels und wurden nicht geprüft. Wir können daher nicht sagen, ob der Tunnel dort aufgebaut wird.
Windows
Die Compose-Datei oben braucht unter Windows mit Docker Desktop keine Änderungen.
Docker Desktop benötigt ein 64-Bit-Windows 10 oder 11 in einer Version, die Microsoft noch unterstützt, sowie das WSL-2-Backend, das standardmäßig verwendet wird. Vor dem Start sollten Sie dann zwei Dinge prüfen.
1. Docker Desktop muss im Modus für Linux-Container laufen. Die Engine für Windows-Container kann dieses Image nicht ausführen und steht mit dem WSL-2-Backend ohnehin nicht zur Verfügung.
2. Ihr WSL2-Kernel muss Version 6.6.x haben. Älteren Kernels, darunter 5.15, fehlt ein
Netfilter-Modul, das der Tunnel benötigt, und aus dem Container heraus lässt sich das nicht
umgehen. Der Tunnel kommt dann nicht zustande und meldet
unknown option '--save-mark'. Prüfen und aktualisieren Sie das in PowerShell:
wsl --version # need "Kernel version: 6.6.x"
wsl --update # if it reports anything older
6.6 wurde erst um WSL 2.4 bis 2.7 herum zum festen Standard. Ein Rechner, der länger nicht aktualisiert wurde, kann also noch auf 5.15 laufen. Dieselbe Voraussetzung gilt, wenn Sie statt Docker Desktop Docker CE in einer WSL2-Distribution betreiben, denn diese nutzt denselben Kernel.
Unter 6.6 ist tun ein Modul und nicht fest eingebaut. Prüfen Sie daher, ob der Geräteknoten
existiert, bevor Sie den Fehler beim Agenten suchen. Dieser Befehl schlägt schon beim Erstellen
des Containers fehl, wenn er fehlt:
docker run --rm --device /dev/net/tun alpine ls -l /dev/net/tun
Sie brauchen weder eine Regel in der Windows-Firewall noch eine Portweiterleitung. Eingehender Verkehr kommt über den Tunnel an, weder die Windows-Firewall noch das NAT von WSL liegen also auf dem Weg.
Laptops und Ruhezustand
Der Ruhezustand unterbricht den Tunnel. Unter macOS und Windows pausiert die Linux-VM, wenn Ihr Rechner in den Ruhezustand geht, und Ihre öffentliche IP-Adresse ist bis zum Aufwachen nicht erreichbar; danach baut sich der Tunnel automatisch wieder auf. Probieren Sie es gern auf Ihrem Laptop aus, betreiben Sie es aber auf einem Server: Ein Rechner, der schläft, ist ein schlechter Host für eine öffentliche IP-Adresse, die immer erreichbar sein soll.
Ein API-Schlüssel, ein Tunnel
Ein WireGuard-Schlüssel gehört zu genau einem Endpunkt. Laufen zwei Container mit demselben API-Schlüssel, werfen sie sich gegenseitig aus der Verbindung. Es gewinnt jeweils der, dessen Handshake am jüngsten ist, und der andere verwirft stillschweigend Verkehr bis zu seinem nächsten Keepalive. Das sieht nach zufälliger Unzuverlässigkeit aus statt nach einem klaren Fehler. Die übliche Ursache ist ein Test auf dem Laptop, während ein Server bereits mit demselben Schlüssel verbunden ist.
Dieses Problem diagnostiziert sich selbst: Beide Container starten immer wieder neu, weil jeder von ihnen zu dem Schluss kommt, er sei der defekte. Ein Container, der in einer Neustartschleife hängt, obwohl die Internetverbindung des Rechners in Ordnung ist, bedeutet fast immer, dass ein zweiter Agent denselben Schlüssel verwendet.
Verwenden Sie einen API-Schlüssel pro laufendem Tunnel.
Fehlerbehebung
Beginnen Sie mit docker compose logs -f getpublicip.
| Was Sie sehen | Was es bedeutet |
|---|---|
GETPUBLICIP_API_KEY is required | Die Variable ist nicht gesetzt, oder Ihre .env-Datei wird nicht eingelesen |
tunnel up: … 401 | Der API-Schlüssel ist ungültig |
waiting for destinations to resolve | Das Ziel läuft noch nicht, der Dienstname ist falsch, oder der Agent teilt kein Netzwerk mit ihm |
wg-quick oder Berechtigungsfehler | NET_ADMIN oder /dev/net/tun fehlt |
iptables-restore … unknown option '--save-mark' | Nur Windows: ein WSL2-Kernel älter als 6.6. Führen Sie wsl --update aus. Siehe Windows |
error gathering device information … /dev/net/tun | Der Geräteknoten existiert auf dem Host nicht. Prüfen Sie unter Docker Desktop die Version Ihres WSL2-Kernels |
| Verkehr kommt an, aber Antworten hängen | Die sysctls für die Weiterleitung sind nicht gesetzt |
| Eine Zuordnung zum Host wird abgelehnt | Der Dienst auf dem Host ist an 127.0.0.1 statt an 0.0.0.0 gebunden, oder eine Host-Firewall verwirft Verkehr aus dem Bridge-Subnetz |
tunnel appears broken | Die Verbindung ist abgebrochen. Der Agent kümmert sich bereits darum. Siehe Verbindungsabbrüche |
tunnel health cannot be determined | Der Agent konnte den Status des Tunnels diesmal nicht lesen, was nicht dasselbe ist wie ein ausgefallener Tunnel. Er bekommt mehr Zeit, sich von selbst zu erholen, bevor der Container neu gestartet wird |
exiting so the container is restarted | Normale Wiederherstellung, kein Fehler. Der Container kommt mit einer frischen Verbindung zurück. Wiederholt sich das über längere Zeit, hat der Rechner entweder kein Internet, oder zwei Agenten teilen sich einen API-Schlüssel |
Im Log sieht nichts falsch aus, aber eingehender Verkehr hängt, und GETPUBLICIP_PRESERVE_CLIENT_IP ist aktiv | Das Ziel schickt seine Antworten nicht über den Agenten zurück. Führen Sie docker exec <target> ip route aus: Die Standardroute muss auf den Agenten zeigen, und bei IPv6-Weiterleitung auch ip -6 route. Siehe Die echte Client-IP-Adresse sehen |
these destinations cannot work while preserving client IPs | Ein Ziel auf dem Host ist zugeordnet, während die Erhaltung der Client-IP aktiv ist, und das kann nicht funktionieren. Verlegen Sie diese Zuordnungen auf einen zweiten Agenten, bei dem die Einstellung aus bleibt |
a port range must forward to the same range | Eine Bereichszuordnung zeigt auf andere Ports am Ziel, oder auf einer Seite steht ein Bereich und auf der anderen ein einzelner Port. Lassen Sie den internen Port weg oder wiederholen Sie denselben Bereich. Siehe Portbereiche |
no destination resolved in the family its mapping asked for | Eine ipv6-Zuordnung zeigt auf einen Dienst ohne IPv6-Adresse, meist ein Compose-Netzwerk ohne enable_ipv6: true. Siehe IPv6 weiterleiten |
Ein Container, den Sie über den Agenten geleitet haben, hat kein Internet, und GETPUBLICIP_OUTBOUND ist aktiv | Entweder ist der Tunnel unterbrochen (dieser Modus ist absichtlich ausfallsicher), oder die Standardroute des Containers zeigt nicht auf den Agenten. Führen Sie docker exec <target> ip route aus und bei IPv6 auch ip -6 route. Siehe Ausgehenden Datenverkehr über Ihre IP-Adresse senden |
GETPUBLICIP_MAPPINGS is required (or set GETPUBLICIP_OUTBOUND=true for egress with no inbound ports) | Sie haben den Agenten ohne Portzuordnungen gestartet. Das ist nur bei einem rein ausgehenden Setup erlaubt, das GETPUBLICIP_OUTBOUND=true braucht |
skipping API push: no mappings configured (egress-only) | Kein Fehler. Ein rein ausgehender Agent lässt die Portfreigaben Ihrer IP-Adresse unberührt, statt sie zu löschen |
preserveClientIp and masqueradeOutbound are mutually exclusive | GETPUBLICIP_PRESERVE_CLIENT_IP und GETPUBLICIP_MASQUERADE waren beide aktiviert. Entfernen Sie GETPUBLICIP_MASQUERADE |
is not a boolean (use true or false) | Eine Einstellung wie GETPUBLICIP_PRESERVE_CLIENT_IP hat einen anderen Wert als true oder false erhalten. yes und on werden bewusst abgelehnt, damit ein Tippfehler die Einstellung nicht deaktiviert lässt, ohne dass Sie es merken |
Um eine Konfiguration zu prüfen, ohne etwas zu starten oder die API zu kontaktieren, führen Sie sie im Dry-Run-Modus aus. Er gibt die Regeln aus, die angewendet würden, und beendet sich dann:
docker run --rm \
-e GETPUBLICIP_API_KEY=x -e GETPUBLICIP_DRY_RUN=true \
-e GETPUBLICIP_ISOLATED_INTERFACE=eth0 \
-e GETPUBLICIP_MAPPINGS="8080/tcp->web:80" \
ghcr.io/getpublicip/getpublicip:latest
Häufig gestellte Fragen
Muss ich Ports an meinen Containern veröffentlichen, um GetPublicIP zu nutzen?
Nein. Der Datenverkehr kommt über den WireGuard-Tunnel an, nicht über einen veröffentlichten Host-Port. Die Dienste, die Sie erreichbar machen, brauchen daher keine ports:-Einträge und überhaupt keine Änderungen. Mit ports: wäre der Dienst auch in Ihrem LAN erreichbar, was meist nicht gewünscht ist.
Muss der GetPublicIP-Container privilegiert laufen?
Nein. Der Container braucht die Capability NET_ADMIN, das Gerät /dev/net/tun und die sysctls für die Weiterleitung, sonst nichts.
Muss das WireGuard-Kernelmodul auf dem Host installiert sein?
Nein. Das Image nutzt das Kernelmodul des Hosts, wenn es vorhanden ist, und greift andernfalls auf das mitgelieferte Userspace-wireguard-go zurück. Auf dem Host ist in keinem Fall etwas zu installieren, auf keiner Plattform.
Funktioniert das unter macOS und Windows?
Ja, und die Compose-Datei braucht auf keinem der beiden Systeme Änderungen. Der Host Ihres Containers ist eine Linux-VM und nicht das Desktop-Betriebssystem. Das Tunnelgerät stammt also aus dieser VM, und unter macOS oder Windows selbst ist nichts zu installieren. macOS funktioniert mit Docker Desktop unverändert auf Intel und Apple Silicon. Unter Windows muss Docker Desktop im Modus für Linux-Container laufen, und Ihr WSL2-Kernel muss Version 6.6.x haben. Prüfen Sie das mit wsl --version und führen Sie wsl --update aus, falls eine ältere Version angezeigt wird, denn Kernels vor 6.6 fehlt ein Netfilter-Modul, das der Tunnel benötigt.
Entschlüsselt GetPublicIP meinen HTTPS-Datenverkehr?
Nein. GetPublicIP leitet Pakete weiter und terminiert niemals TLS. Wir besitzen also keines Ihrer Zertifikate oder privaten Schlüssel und haben nichts, womit wir entschlüsseln könnten. Die TLS-Sitzung wird direkt zwischen dem Browser Ihres Besuchers und dem Ihrer Dienste ausgehandelt, der sie terminiert, und erst dort zum ersten Mal entschlüsselt. Dieser Dienst braucht ein eigenes gültiges Zertifikat, genau wie auf jedem anderen öffentlichen Host. Let's Encrypt ist kostenlos, automatisiert und dafür gut geeignet. Wenn Sie eine HTTP-01-Challenge verwenden, denken Sie daran, neben Port 443 auch Port 80 zuzuordnen.
Kann ich einen Port an einen Dienst auf dem Docker-Host statt an einen Container weiterleiten?
Ja. Lassen Sie die Zuordnung auf host.docker.internal zeigen und ergänzen Sie unter Linux extra_hosts: - "host.docker.internal:host-gateway". In Docker Desktop ist das bereits eingebaut. Eine feste IP-Adresse funktioniert ebenfalls. Der Dienst auf dem Host muss außerdem auf 0.0.0.0 statt auf 127.0.0.1 lauschen, und eine Host-Firewall muss eingehenden Verkehr aus dem Bridge-Subnetz erlauben. Ziele auf dem Host sind das Einzige, was sich nicht mit GETPUBLICIP_PRESERVE_CLIENT_IP kombinieren lässt.
Können meine Container die echte IP-Adresse des Besuchers sehen?
Ja, mit GETPUBLICIP_PRESERVE_CLIENT_IP=true. Standardmäßig ist das aus, weil es Arbeit auf Ihrer Seite erfordert. Normalerweise schreibt der Agent die Quelladresse des eingehenden Verkehrs auf seine eigene um, damit die Antworten über ihn zurückkommen. Deshalb zeigen Ihre Access-Logs für jeden Besucher dieselbe Adresse. Schalten Sie das ab, muss jeder Dienst, an den Sie weiterleiten, seine Antworten stattdessen selbst über den Agenten zurückschicken, und dafür muss die Standardroute dieses Dienstes geändert werden. Die Einstellung gilt für Ihre gesamte Compose-Datei und nicht für eine einzelne Zuordnung, und die Weiterleitung an einen Dienst auf dem Docker-Host funktioniert nicht, solange sie aktiv ist. Richten Sie sie immer zusammen mit der Route ein, nie allein: Die Variable allein hinterlässt einen Dienst, der hängt, während die Logs weiterhin gesund aussehen.
Kann ich X-Forwarded-For statt GETPUBLICIP_PRESERVE_CLIENT_IP verwenden?
Nicht allein. X-Forwarded-For hilft nur, wenn das, was den Header hinzufügt, die echte Client-Adresse überhaupt sehen kann. Die Quelladresse wird auf Paketebene umgeschrieben, bevor irgendetwas eine HTTP-Anfrage liest. Ein Reverse Proxy in Ihrer Compose-Datei erhält also Pakete, die bereits vorgeben, vom GetPublicIP-Container zu stammen, und hat nichts Wahres, was er in den Header schreiben könnte. Dort einen hinzuzufügen, hält die falsche Adresse nur an einer zweiten Stelle fest. In einem Fall funktioniert der Header jedoch, und Sie brauchen nichts davon: Wenn Ihr Datenverkehr ein CDN oder einen externen Proxy wie Cloudflare erreicht, bevor er bei Ihrer öffentlichen IP-Adresse ankommt, sieht dieser Dienst den echten Client und setzt den Header selbst. Ihre Container lesen ihn dann ganz normal aus.
Können meine Container meine öffentliche IP-Adresse auch für ausgehenden Datenverkehr nutzen?
Ja, mit GETPUBLICIP_OUTBOUND=true. Standardmäßig nutzt nur eingehender Verkehr den Tunnel, und Ihre Container erreichen das Internet weiterhin über Ihren normalen Anschluss. Wenn Sie diese Einstellung aktivieren, läuft auch ihr ausgehender Verkehr durch den Tunnel und verlässt ihn mit Ihrer GetPublicIP-Adresse. Dafür ist dieselbe Änderung nötig wie für die echte Client-IP (die Standardroute jedes Containers muss auf den GetPublicIP-Container zeigen). Haben Sie das bereits eingerichtet, müssen Sie nur noch die Einstellung hinzufügen. Alle Container dahinter teilen sich die eine Adresse. Außerdem ist das Verhalten bewusst ausfallsicher: Solange der Tunnel unterbrochen ist, haben diese Container gar kein Internet, statt auf die Adresse Ihres Internetanbieters auszuweichen.
Was passiert, wenn meine Internetverbindung abbricht?
Der Tunnel baut sich von selbst wieder auf. Es gibt nichts neu zu starten und nichts zu konfigurieren. Die meisten Abbrüche behebt der Keepalive, der die Verbindung offen hält, ohne dass der Agent eingreifen muss; bei einem echten Tunnel haben wir gemessen, dass der Verkehr etwa 17 Sekunden nach der Wiederherstellung der Verbindung wieder floss. Bei den selteneren Fehlern, die ein Keepalive nicht beheben kann, stoppt der Agent den Container, statt den Tunnel an Ort und Stelle zu reparieren, und Ihre Restart-Policy startet ihn sofort mit einer frischen Verbindung neu. Deshalb setzt das Compose-Beispiel restart: unless-stopped. Solange Ihr Internet ausgefallen ist, ist Ihr Dienst nicht erreichbar, und der Tunnel baut sich wieder auf, sobald eine Verbindung verfügbar ist.
Was passiert, wenn einer meiner Container mit einer neuen IP-Adresse neu startet?
Der Agent löst alle Dienstnamen der Ziele in regelmäßigen Abständen neu auf (GETPUBLICIP_RESOLVE_INTERVAL, standardmäßig 30 Sekunden) und wendet die Weiterleitungsregeln erneut an, wenn ein Container umgezogen ist. Sie müssen nichts neu starten. Eine einzelne verlorene Anfrage direkt nach einer Neusynchronisierung ist normal, solange sich das Connection Tracking einpendelt.
Kann ich denselben API-Schlüssel an zwei Orten gleichzeitig verwenden?
Nein. Ein WireGuard-Schlüssel gehört zu genau einem Endpunkt. Zwei Container mit demselben API-Schlüssel werfen sich daher gegenseitig aus der Verbindung. Es gewinnt jeweils der, dessen Handshake am jüngsten ist. Das äußert sich in zufälligen, sporadischen Ausfällen statt in einer klaren Fehlermeldung. Ein eindeutiges Signal gibt es aber: Beide Container starten immer wieder neu, weil jeder von ihnen zu dem Schluss kommt, er sei der defekte. Verwenden Sie einen API-Schlüssel pro laufendem Tunnel.
Erste Schritte erklärt, wie der Dienst funktioniert. Wenn Sie Ihre Dienste direkt auf einem Host statt in Containern betreiben, lesen Sie die Anleitungen für Linux und Windows.