10 KiB
Installation
Schritt-für-Schritt-Einrichtung von Server (Raspberry Pi) und Client (Windows).
Alle Befehle sind zum Kopieren gedacht. Platzhalter in GROSSBUCHSTABEN
ersetzen.
Dauer: etwa 20 Minuten.
Voraussetzungen
Server
- Raspberry Pi oder anderer Linux-Rechner mit Docker und Docker Compose
(
docker compose versionfunktioniert) - Nginx Proxy Manager läuft dort in Docker
- Eine Domain zeigt auf deinen Internetanschluss. Im Router ist Port 443 an den Pi weitergeleitet.
- Im Nginx Proxy Manager gibt es für diese Domain einen Proxy Host mit gültigem SSL-Zertifikat. Ein neues Zertifikat bekommst du im Proxy Host über den Tab SSL → Request a new SSL Certificate.
- SSH-Zugang zum Pi mit einem Benutzer, der
sudodarf
Client
- Windows 10 oder 11 mit Google Chrome
- Dieses Projekt als Ordner auf dem PC
Teil 1 — Server
1.1 Dateien auf den Pi kopieren
In PowerShell im Projektordner (dort, wo README.md liegt):
$Pi = 'BENUTZER@PI-ADRESSE'
ssh $Pi 'mkdir -p ~/wstunnel && chmod 700 ~/wstunnel'
scp server\docker-compose.yml server\restrictions.example.yaml server\firewall\tunnler-firewall.sh server\firewall\tunnler-firewall.service "${Pi}:wstunnel/"
Danach am Pi anmelden. Alle folgenden Befehle in Teil 1 laufen dort:
ssh $Pi
1.2 Netz des Proxy Managers ermitteln
Der Tunnel-Container kommt in dasselbe Docker-Netz wie der Nginx Proxy Manager und bekommt dort eine feste IP-Adresse.
cd ~/wstunnel
NPM_CONTAINER=$(docker ps --format '{{.Names}} {{.Image}}' | awk '/nginx-proxy-manager/ {print $1; exit}')
NPM_NETWORK=$(docker inspect "$NPM_CONTAINER" --format '{{range $k, $v := .NetworkSettings.Networks}}{{$k}}{{"\n"}}{{end}}' | head -n 1)
SUBNET=$(docker network inspect "$NPM_NETWORK" --format '{{(index .IPAM.Config 0).Subnet}}')
TUNNEL_IP=$(python3 -c 'import ipaddress, sys; print(ipaddress.ip_network(sys.argv[1])[-6])' "$SUBNET")
printf 'NPM_NETWORK=%s\nTUNNEL_IP=%s\n' "$NPM_NETWORK" "$TUNNEL_IP" > .env
echo "Proxy Manager: $NPM_CONTAINER | Netz: $NPM_NETWORK ($SUBNET) | Tunnel-IP: $TUNNEL_IP"
Die letzte Zeile muss einen Container, ein Netz und eine IP nennen, zum Beispiel:
Proxy Manager: nginx-app-1 | Netz: nginx_default (172.20.0.0/16) | Tunnel-IP: 172.20.255.250
Ist ein Feld leer oder heißt das Netz bridge, siehe
Fehlerbehebung.
1.3 Secret erzeugen
Das Secret ist das Passwort des Tunnels. Es wird Teil des URL-Pfads.
cd ~/wstunnel
SECRET=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 32)
sed "s/__SECRET__/$SECRET/" restrictions.example.yaml > restrictions.yaml
chmod 644 restrictions.yaml
echo "Secret: $SECRET"
Das Secret in einem Passwort-Manager speichern. Es wird in Schritt 1.6 und 2.2 gebraucht.
1.4 Tunnel-Server starten
cd ~/wstunnel
docker compose up -d
docker logs wstunnel --tail 5
Docker lädt das Image ghcr.io/erebe/wstunnel beim ersten Start selbst
herunter. Die Version steht in docker-compose.yml. In der Log-Ausgabe muss
folgende Zeile stehen:
Starting wstunnel server listening on 0.0.0.0:8090
1.5 Firewall einrichten
Die Regeln sperren für den Tunnel-Container alle privaten Netze. Über den Tunnel ist damit weder das Heimnetz noch der Pi selbst erreichbar.
cd ~/wstunnel
. ./.env
echo "TUNNEL_IP=$TUNNEL_IP" | sudo tee /etc/default/tunnler-firewall
sudo install -m 755 tunnler-firewall.sh /usr/local/sbin/
sudo install -m 644 tunnler-firewall.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now tunnler-firewall
sudo iptables -S TUNNLER | head -n 3
Die Ausgabe beginnt mit -N TUNNLER. Die Regeln werden bei jedem Neustart
automatisch wieder gesetzt.
1.6 Nginx Proxy Manager konfigurieren
Die Werte für die Oberfläche anzeigen:
cd ~/wstunnel
. ./.env
SECRET=$(sed -n 's/.*PathPrefix "^\([A-Za-z0-9]*\)\$".*/\1/p' restrictions.yaml)
echo "Location: /$SECRET/"
echo "Forward: http $TUNNEL_IP 8090"
Im Nginx Proxy Manager Hosts → Proxy Hosts öffnen und beim Proxy Host der Domain auf Edit klicken:
-
Tab Details: Websockets Support einschalten.
-
Tab Custom Locations → Add location:
Feld Wert Location /SECRET/aus der Ausgabe oben, mit beiden SchrägstrichenScheme httpForward Hostname / IP Tunnel-IP aus der Ausgabe oben, ohne Schrägstrich Forward Port 8090 -
Beim Zahnrad der Location dieses Feld füllen:
proxy_read_timeout 3600s; proxy_send_timeout 3600s; proxy_buffering off; -
Save. Der Proxy Host muss danach als Online angezeigt werden.
Die bestehende Website unter / bleibt unverändert.
Teil 2 — Client
2.1 Ordner ablegen
In PowerShell im Projektordner:
New-Item -ItemType Directory -Force C:\Tools | Out-Null
Copy-Item -Recurse client C:\Tools\tunnler
Ein anderer Zielordner geht genauso. Admin-Rechte sind nicht nötig.
wstunnel.exe lädt der erste Start von GitHub nach bin\ und prüft dabei die
SHA-256-Prüfsumme.
2.2 Konfiguration anlegen
cd C:\Tools\tunnler
Copy-Item config.example.ps1 config.ps1
notepad config.ps1
In config.ps1 zwei Werte eintragen und speichern:
$TunnelSecret = 'SECRET'
$TunnelServer = 'wss://DOMAIN:443'
2.3 Server-Weg prüfen
curl.exe -s -o NUL -w "%{http_code}`n" https://DOMAIN/SECRET/events
| Ergebnis | Bedeutung |
|---|---|
400 |
Richtig: Die Anfrage erreicht den Tunnel-Server |
404 |
Die Custom Location fehlt oder ist falsch geschrieben (1.6) |
502 |
Der Container läuft nicht, oder die Forward-IP ist falsch (1.4, 1.6) |
2.4 Tunnel testen
Chrome-Tunnel.cmd doppelklicken. Es öffnet sich ein eigenes Chrome-Fenster.
Danach in PowerShell:
cd C:\Tools\tunnler
.\Tunnel-Status.cmd
Die angezeigte IP muss die IP des Internetanschlusses zu Hause sein. Für einen echten Test den PC mit einem Handy-Hotspot verbinden: Die IP darf dann nicht die des Hotspots sein.
2.5 codexx einrichten
PATH-eintragen.cmd doppelklicken. Der Client-Ordner landet im Benutzer-PATH,
Admin-Rechte sind nicht nötig. Danach VS Code und alle Terminals komplett neu
starten. In jedem Projektordner startet codexx statt codex Codex über den
Tunnel.
Nach dem Verschieben des Client-Ordners den alten Eintrag unter
Umgebungsvariablen für dieses Konto bearbeiten → Path löschen und
PATH-eintragen.cmd erneut ausführen.
Teil 3 — Einsatz hinter einem Firmen-Proxy
Netze mit erzwungenem Proxy lassen keine direkte Verbindung zu. Der Tunnel muss dort durch den Proxy.
3.1 Proxy-Adresse herausfinden
(Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings").AutoConfigURL
Die angezeigte URL im Browser öffnen. In der PAC-Datei nach einer Zeile wie
PROXY proxy.firma.de:8080 suchen.
3.2 Proxy eintragen
In config.ps1:
$UpstreamProxy = 'http://PROXY-HOST:PROXY-PORT'
Verlangt der Proxy eine Anmeldung, zusätzlich $UpstreamProxyUser und
$UpstreamProxyPassword setzen. Danach Tunnel-Stop.cmd ausführen und
Chrome-Tunnel.cmd neu starten.
3.3 Wenn der Proxy TLS aufbricht
In Edge https://DOMAIN öffnen, auf das Schloss klicken und das Zertifikat
ansehen. Ist der Aussteller nicht Let's Encrypt, bricht der Proxy die
Verschlüsselung auf. Der Tunnel scheitert dann an der Zertifikatsprüfung. Nur
in diesem Fall in config.ps1 setzen:
$SkipTlsVerify = $true
Der Proxy sieht dann das Secret. Nach dem Einsatz das Secret tauschen.
Secret tauschen
Auf dem Pi:
cd ~/wstunnel
OLD=$(sed -n 's/.*PathPrefix "^\([A-Za-z0-9]*\)\$".*/\1/p' restrictions.yaml)
NEW=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 32)
sed -i "s/$OLD/$NEW/" restrictions.yaml
echo "Neues Secret: $NEW"
Der Server lädt die Datei automatisch neu. Danach:
- Im Nginx Proxy Manager die Custom Location auf
/NEUES-SECRET/ändern und speichern. - Auf jedem PC in
config.ps1$TunnelSecretersetzen, dannTunnel-Stop.cmdausführen.
Aktualisieren
In ~/wstunnel/docker-compose.yml die Image-Version erhöhen
(Releases), dann:
cd ~/wstunnel
docker compose pull
docker compose up -d
Den Client auf dieselbe Version bringen: In client\scripts\common.ps1
$WstunnelVersion anpassen, Tunnel-Stop.cmd ausführen und
client\bin\wstunnel.exe löschen. Der nächste Start lädt die neue Version.
Deinstallieren
-
Im Nginx Proxy Manager die Custom Location entfernen.
-
Auf dem Pi:
cd ~/wstunnel && docker compose down sudo systemctl disable --now tunnler-firewall sudo rm /etc/systemd/system/tunnler-firewall.service /usr/local/sbin/tunnler-firewall.sh /etc/default/tunnler-firewall sudo systemctl daemon-reload rm -r ~/wstunnel -
Auf dem PC den Client-Ordner löschen. Es wurde nichts installiert.
Fehlerbehebung
| Symptom | Lösung |
|---|---|
1.2: Proxy Manager: ist leer |
Der Container heißt anders. docker ps ausführen und den Namen von Hand setzen: NPM_CONTAINER=NAME, dann ab der zweiten Zeile wiederholen. |
1.2: Netz heißt bridge |
Im Standardnetz sind keine festen IPs möglich. Den Proxy Manager in ein eigenes Netz verschieben, zum Beispiel per Docker Compose. |
1.4: Address already in use / invalid address |
Die Tunnel-IP ist belegt oder liegt außerhalb des Subnetzes. In ~/wstunnel/.env eine andere freie IP aus dem Subnetz eintragen und 1.4 bis 1.6 wiederholen. |
| 1.6: Proxy Host Offline | Die Location in NPM löschen und Schreibweise prüfen. Im Feld Forward Hostname darf kein Pfad stehen. |
Client: Tunnel-Client lauscht nicht |
logs\wstunnel.err.log im Client-Ordner lesen. Ein anderes Programm nutzt eventuell Port 1080; dann $LocalProxy in config.ps1 ändern. |
| Client verbindet nicht, Timeout | Im Firmennetz fehlt $UpstreamProxy (3.2). Sonst Portweiterleitung und DNS der Domain prüfen. |
Seite lädt nicht, Client-Log zeigt 400 |
Das Ziel ist gesperrt (nur Ports 80/443, keine privaten Adressen). Den Grund zeigt docker logs wstunnel auf dem Pi in der Zeile Rejecting …. |
| Codex nutzt den Tunnel nicht | Codex mit codexx starten, nicht direkt mit codex. Fehlt der Befehl, PATH-eintragen.cmd ausführen (2.5). |