mirror of
https://github.com/Andre-Bzk/tunnler.git
synced 2026-11-15 06:23:04 +01:00
341 lines
10 KiB
Markdown
341 lines
10 KiB
Markdown
# 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 version` funktioniert)
|
|
- [Nginx Proxy Manager](https://nginxproxymanager.com/) 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 `sudo` darf
|
|
|
|
**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):
|
|
|
|
```powershell
|
|
$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:
|
|
|
|
```powershell
|
|
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.
|
|
|
|
```bash
|
|
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](#fehlerbehebung).
|
|
|
|
### 1.3 Secret erzeugen
|
|
|
|
Das Secret ist das Passwort des Tunnels. Es wird Teil des URL-Pfads.
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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.
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
1. Tab **Details**: **Websockets Support** einschalten.
|
|
2. Tab **Custom Locations** → **Add location**:
|
|
|
|
| Feld | Wert |
|
|
|---|---|
|
|
| Location | `/SECRET/` aus der Ausgabe oben, mit beiden Schrägstrichen |
|
|
| Scheme | `http` |
|
|
| Forward Hostname / IP | Tunnel-IP aus der Ausgabe oben, ohne Schrägstrich |
|
|
| Forward Port | `8090` |
|
|
|
|
3. Beim Zahnrad der Location dieses Feld füllen:
|
|
|
|
```nginx
|
|
proxy_read_timeout 3600s;
|
|
proxy_send_timeout 3600s;
|
|
proxy_buffering off;
|
|
```
|
|
|
|
4. **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:
|
|
|
|
```powershell
|
|
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
|
|
|
|
```powershell
|
|
cd C:\Tools\tunnler
|
|
Copy-Item config.example.ps1 config.ps1
|
|
notepad config.ps1
|
|
```
|
|
|
|
In `config.ps1` zwei Werte eintragen und speichern:
|
|
|
|
```powershell
|
|
$TunnelSecret = 'SECRET'
|
|
$TunnelServer = 'wss://DOMAIN:443'
|
|
```
|
|
|
|
### 2.3 Server-Weg prüfen
|
|
|
|
```powershell
|
|
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:
|
|
|
|
```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
|
|
|
|
```powershell
|
|
(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`:
|
|
|
|
```powershell
|
|
$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:
|
|
|
|
```powershell
|
|
$SkipTlsVerify = $true
|
|
```
|
|
|
|
Der Proxy sieht dann das Secret. Nach dem Einsatz das Secret tauschen.
|
|
|
|
---
|
|
|
|
## Secret tauschen
|
|
|
|
Auf dem Pi:
|
|
|
|
```bash
|
|
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:
|
|
|
|
1. Im Nginx Proxy Manager die Custom Location auf `/NEUES-SECRET/` ändern und
|
|
speichern.
|
|
2. Auf jedem PC in `config.ps1` `$TunnelSecret` ersetzen, dann `Tunnel-Stop.cmd`
|
|
ausführen.
|
|
|
|
---
|
|
|
|
## Aktualisieren
|
|
|
|
In `~/wstunnel/docker-compose.yml` die Image-Version erhöhen
|
|
([Releases](https://github.com/erebe/wstunnel/releases)), dann:
|
|
|
|
```bash
|
|
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
|
|
|
|
1. Im Nginx Proxy Manager die Custom Location entfernen.
|
|
2. Auf dem Pi:
|
|
|
|
```bash
|
|
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
|
|
```
|
|
|
|
3. 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). |
|