Wireguard
WireGuard ist eine freie Software zum Aufbau eines virtuellen privaten Netzwerkes über eine verschlüsselte Verbindung. Als Besonderheit ist diese VPN-Technik direkt im Linux-Kernel ab Version 5.6 integriert und erlaubt so eine höhere Verarbeitungsgeschwindigkeit als vergleichbare Lösungen wie IPsec oder OpenVPN
- Wireguard Public IP weiterleiten
- Einrichtung Loadbalancer
- Erstellung Wireguard Server und Client Configs
- Einrichtung Client unter OPNSense
- Wireguard UI Server einrichten
- Wireguard Reconnect bei IP Wechsel
- Wireguard Clients
- Fehlerbehebungen
- Wireguard Site2Site Tunnel
- Wireguard Proxy
Wireguard Public IP weiterleiten
Einrichtung Loadbalancer
Einrichtung Loadbalancer
Auf Loadbalancer 1 einloggen und folgende Pakete installieren
apt install lvs
Nun eine neue Datei mit folgender Config anlegen
nano /etc/keepalived/keepalived.conf
Inhalt einfügen
global_defs {
notification_email {
info@hacker-net.de
}
notification_email_from lb001@strange-hosting.com
smtp_server hacker-net.de
smtp_connect_timeout 60
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 101
unicast_src_ip 159.69.13.9
unicast_peer { 49.12.74.225 }
priority 101
notify /root/failover.sh
advert_int 1
authentication {
auth_type PASS
auth_pass 775567567ghBysA!asHjk99gf!
}
virtual_ipaddress {
116.202.189.172
}
virtual_ipaddress_excluded {
2a01:4f8:1c0c:8218::1
}
}
Nun die failover.sh im root Verzeichnis anlegen
nano /root/failover.sh
Nun Inhalt einfügen
#!/bin/bash
#lb0001 ID : 5605626
#lb0002 ID : 5605974
#floating ip LBS 116.202.189.172 =: 245713
#floating id KC 78.46.239.42 =: 617007
#floatingip6 id 2a01:4f8:1c17:8106::/64 =: 246612
#floating ip GBL 16126703 =: 78.47.118.115
TYPE=$1
NAME=$2
STATE=$3
case $STATE in
"MASTER") curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer 5BEoQe1HDjITxzhCPmnp8cJq1Ybv6ehNIgdvrfkiECG0fyASSOQbIlFMj9GF0lsV" -d '{"server": 5605626}' 'https://api.hetzner.cloud/v1/floating_ips/245713/actions/assign'
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer 5BEoQe1HDjITxzhCPmnp8cJq1Ybv6ehNIgdvrfkiECG0fyASSOQbIlFMj9GF0lsV" -d '{"server": 5605626}' 'https://api.hetzner.cloud/v1/floating_ips/246612/actions/assign'
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer 5BEoQe1HDjITxzhCPmnp8cJq1Ybv6ehNIgdvrfkiECG0fyASSOQbIlFMj9GF0lsV" -d '{"server": 5605626}' 'https://api.hetzner.cloud/v1/floating_ips/16126703/actions/assign'
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer 5BEoQe1HDjITxzhCPmnp8cJq1Ybv6ehNIgdvrfkiECG0fyASSOQbIlFMj9GF0lsV" -d '{"server": 5605626}' 'https://api.hetzner.cloud/v1/floating_ips/617007/actions/assign'
echo "Master"
exit 0
;;
"BACKUP") echo "backup"
exit 0
;;
"FAULT") echo "fault"
exit 0
;;
*) echo "unknown state"
exit 1
;;
esac
Nun auf Loadblancer zwei einloggen
Folgene pakete installieren
apt install lvs
Nun eine neue Datei mit folgender Config anlegen
nano /etc/keepalived/keepalived.conf
Inhalt einfügen
nano /root/failover.sh
Erstellung Wireguard Server und Client Configs
Auf dem Server:
Erstellung der Server Config, Muss nur einmal gemacht werden.
Schlüsselpaar erstellen.
Sollen mehre IPs erstellt werden empfehle ich für jeden Server + client ein Verzeichnis zu erstellen
Beispiel:
Dazu ein Verzeichnis keys anlegen mit folgenden Unterverzeichnissen je IP (Diese IP Adressen ahbe ich nicht, Beispiel
Nun in das Verzeichnis Server der ersten IP gehen.
wg genkey | tee privatekey | wg pubkey > publickey
Nun haben wir zwei Schlüsseldateien.
Einmal private Key und publickey
Jetzt sieht das ganze so aus
Nun die Config Datei erstellen mit den Schlüsseldateien.
Eine Wireguard Config ist in zwei Teile geteilt.
Einmal Interface das der Lokale Teil für den Computer
(Auch ein Client hat einen lokalen Teil, der Dient dazu das Interface bereitzustellen.
Der zweite Teil sind die Peers, es können auch mehrere Peers eingetragen sein. Aber wir erstellen hier für jede IP einene eigene config. Den Publickey für den Peer haben wir noch nicht.
nano ~/keys/ip_27.44.34.21/server/ip27443421server.conf
[Interface]
Address = 172.16.0.1 # oder irgenein anderes privates Netz from RFC1918 (privates Netz) 10.10.0.x oder 192.168.0.100 oder oder egal. Wichtig, auf einem Computer dürfen die entze nicht gleich sein
PrivateKey = <private_key_vom_server>
ListenPort = 51820 # or jeder andere port der beliebt
[Peer]
PublicKey = <public_key_vom_client_also_der_derdie_ip_bekommen_soll>
AllowedIPs = publicip_v4/32,ipv6 mit subnet # Here tragen wir unsere PUBLIC IPS ein, die auf der PEER Seite zur Verfügung stehen sollen
Ein Beispiel, diese Keys wurden NIE verwendet, also viel Spaß damit
Inhalt Privatekey Server
mJn1lWnRFTze3wojk3a+d5TsPSOolRqt3dfN7ekgukU=
Inhalt Publickey Server
/amP0UXRsKhzW1QsLvQ/7UjchU1oFfkWYZbZj/mWtxA=
[Interface]
Address = 192.168.100.1
PrivateKey = mJn1lWnRFTze3wojk3a+d5TsPSOolRqt3dfN7ekgukU=
ListenPort = 51820
[Peer]
PublicKey = <haben_wir_noch_nicht_leer_lassen>
AllowedIPs = 27.44.34.21/32, 3a01:4d8:xxxx:8106::/64
Nun die Client Schlüssel erstellen konfig erstellen
Dazu ins client Verzeichnis gehen und wieder
wg genkey | tee privatekey | wg pubkey > publickey
Nun haben wir auch dort im Verzeichnis Client auch zwei Schlüssel
Unserer Privatekey
0Is0rjpsSpzBPDoT+Quv/3GWGe1nPKrNfXJa80wUY0E=
Unserer Public Key
2gWEqeQxoGa9hI94UvV4trVVdiG1G7sq0iLr6W5ymUE=
Nun in der Serverconfig den Public key nachtragen unter Peers
nano ~/keys/ip_27.44.34.21/server/ip27443421server.conf
Nun im peer bereich public key "haben wir noch nicht erstezen" Platzhalter mit dem öffentlichem Schlüssel vom Client ersetzten
....
[Peer]
PublicKey = 2gWEqeQxoGa9hI94UvV4trVVdiG1G7sq0iLr6W5ymUE=
AllowedIPs = 27.44.34.21/32, 3a01:4d8:xxxx:8106::/64
Nun die Client Config erstellen
nano ~/keys/ip_27.44.34.21/client/ip27443421client.conf
[Interface]
Address = publicip_v4/32,ipv6 OHNE subnet
PrivateKey = <private_key_vom_client>
ListenPort = 51820 # irgendeiner darf nur auf dem client nicht doppelt sein. Denn dieser Port wird ja nie benutzt. Denn wir verbinden uns ja zum Server und nicht umgekehrt
[Peer]
PublicKey = <public_key_vom_server_also_der_derdie_ip_bekommen_soll>
Endpoint: ip_adresse_vom_server(Die die der Server fest hat) und den Listen Port aus der Server conf
AllowedIPs = 0.0.0.0/0,::/0 Der erste Wert heißt als standard Gateway für ipv4, der zweite standard gateway für ipv6. Spricht route alles
Beispiel:
[Interface]
Address = 27.44.34.21
PrivateKey = 0Is0rjpsSpzBPDoT+Quv/3GWGe1nPKrNfXJa80wUY0E=
ListenPort = 51820
[Peer]
PublicKey = /amP0UXRsKhzW1QsLvQ/7UjchU1oFfkWYZbZj/mWtxA=
Endpoint: 27.44.34.20:51820
AllowedIPs = 0.0.0.0/0,::/0
Nun sind die Configs fertig und können ausgerollt werden.
Dazu die Server config nach /etc/wireguard kopieren
cp ~/keys/ip_27.44.34.21/server/ip27443421server.conf /etc/wireguard
Nun den Tunnel beim start aktiv schalten
systemctl enable wg-quick@ip27443421server
systemctl start wg-quick@ip27443421server
Wenn ein Loadbalancer im einsatz ist, die Schlüssel und configs auch auf dem Slaveloadbalancer kopieren.
Dort im /etc/wireguard die config auch reinkopieren und auch dort mit systemctl enable den Dienst in die Autostart packen und danach starten
Nun die Client config auf den Client kopieren, entweder den text per Copy und paste übermitteln in eine neue Datei auf den client oder per scp.
Diese muss dann auch in
/etc/wireguard/ip27443421client.conf
Nun diese auch beim starten ausführen
systemctl enable wg-quick@ip27443421client
systemctl start wg-quick@ip27443421client
Fertig.
Einrichtung Client unter OPNSense
In OPNSense einloggen dann unter -> System -> Firmware -> Packages ->
Wireguard auswählen und installieren
Dann F5 drücken damit die Seite aktualisert.
Nun unter VPN Wireguard gehen.
Dort den Haken bei Wireguard rein.
Nun auf den Registerreiter Local und dort auf das kleine + drücken
Nun folgendes Ausfüllen:
Die Daten können per Copy and paste aus der vorher herstellten conf Datei gezogen werden.
Leider unterstützt OPNSense kein import von Conf Dateien
Name : ipadressse ohne punkte dient zur besseren Übersicht
Private Key : den Privaten Key vom Client
Listen Port : irgeneiner hauptsache auf dem Client nicht schon vergeben : 5555
Tunnel Address : die ipdresse mit 32 Netz
alles andere so lassen
Dann Save
Nun auf den Registerreiter Endpoints und dort auf das kleine Plus klicken
Nun folgendes ausfüllen
Name PUBIP : PUPIP und dahinter die IP ohne punkte
Den Public Key vom Server nicht Client
Allowed IP alle
Endpoint Adresse : Die Adresse wo der VPN Server Erreichbar ist.
dann auf Save.
Nun wieder zurück auf den Registerreiter Local da den Eintrag editieren.
Nun im Dropdownmenü peers, den Endpunkt auswählen und Speichern.
Danach im Im Registerreiter General,
den Haken wieder raus. Apply klicken,
Dann haken wieder rein. Apply klicken.
Nun Unterinterfaces -> Assignments -> In der Beschreibung WG1 IP_eintragen. Und dann auf + drücken
Danach auf Save klicken
Nun in Interfaces , dann auf neu erstelle Interface
Nun folgende Einstellungen vornehmen
Wireguard UI Server einrichten
Installation des Servers unter Debian
Teil 1. Installation im Terminal
Abbhängikeiten installieren.
apt update && apt install -y wireguard curl tar iptables resolvconf
Bei Debian 12/13 wird die resolv.conf nicht angelegt. Das heißt nach installtaion von resolvconf funktioniert die Namensauflösung nicht. Daher rersolv.conf anlegen mit Inhalt des google dns Servers als Beispiel
nameserver 8.8.8.8
Denn Sonst funktioniert das Update/Installationsskript nicht
Falls die ufw Firewall aktiv ist, bei dieser folgenden UDP Port öffnen 51820, wenn nicht überspringen
ufw allow 51820/udp
!!Sollte der Wireguard Server hinter einem Router stehen das NAT Portforwarding UDP 51820 nicht vergessen einzurichten!!
Nun in der Systemctl Portforwarding aktivieren
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
sysctl -p
Nun das Startscript für den Wireguard WEBGUI erstellen.
In dem Systemstart wird das Programm so eingestellt das es die Datenbank zum Wireguard Server in/etc/wireguard/db/ abgelegt
cat <<EOF > /etc/wireguard/start-wgui.sh
#!/bin/bash
cd /etc/wireguard
./wireguard-ui -bind-address 0.0.0.0:5000
EOF
ACHTUNG: Die -bind-address 0.0.0.0:5000 sollte aus Sicherheitsgründen, sobald der erste Tunnel steht, gegen die WireGuard Server IP-Adresse 10.252.1.0 ausgetauscht werden!
Nun das Script ausführbar machen.
chmod +x /etc/wireguard/start-wgui.sh
Nun die Systemdienste anlegen
cat <<EOF > /etc/systemd/system/wgui-web.service
[Unit]
Description=WireGuard UI
[Service]
Type=simple
ExecStart=/etc/wireguard/start-wgui.sh
[Install]
WantedBy=multi-user.target
EOF
Nun das Install / Update script erstellen, damit können wir immer die aktuellste Version downloaden.
cat <<EOF > /etc/wireguard/update.sh
#!/bin/bash
VER=\$(curl -sI https://github.com/ngoduykhanh/wireguard-ui/releases/latest | grep "location:" | cut -d "/" -f8 | tr -d '\r')
echo "downloading wireguard-ui \$VER"
curl -sL "https://github.com/ngoduykhanh/wireguard-ui/releases/download/\$VER/wireguard-ui-\$VER-linux-amd64.tar.gz" -o wireguard-ui-\$VER-linux-amd64.tar.gz
echo -n "extracting "; tar xvf wireguard-ui-\$VER-linux-amd64.tar.gz
echo "restarting wgui-web.service"
systemctl restart wgui-web.service
EOF
Das Script ausführbar machen und starten
chmod +x /etc/wireguard/update.sh
cd /etc/wireguard; ./update.sh
Es erscheinen folgende fehler in der Ausgabe, aber es wird trotzdem korrekt installiert
Ausgabe
/update.sh: Zeile 2: : Kommando nicht gefunden.
./update.sh: Zeile 4: : Kommando nicht gefunden.
downloading wireguard-ui v0.3.7
./update.sh: Zeile 7: : Kommando nicht gefunden.
extracting wireguard-ui
./update.sh: Zeile 9: : Kommando nicht gefunden.
restarting wgui-web.service
Wireguard conf von Systemd überwachen lassen und bei Änderung wiregaurd neustarten.
Dienst 1
cat <<EOF > /etc/systemd/system/wgui.service
[Unit]
Description=Restart WireGuard
After=network.target
[Service]
Type=oneshot
ExecStart=/bin/systemctl restart wg-quick@wg0.service
[Install]
RequiredBy=wgui.path
EOF
Dienst 2
cat <<EOF > /etc/systemd/system/wgui.path
[Unit]
Description=Watch /etc/wireguard/wg0.conf for changes
[Path]
PathModified=/etc/wireguard/wg0.conf
[Install]
WantedBy=multi-user.target
EOF
Nun alle 3 Dienste aktivieren und starten
touch /etc/wireguard/wg0.conf
systemctl enable wgui.{path,service} wg-quick@wg0.service wgui-web.service
systemctl start wgui.{path,service}
Nun können wir auf den Wireguard Server über die Weboberfläche zugreifen.
Standard Anmeldedaten :
Benutzername : admin
Kennwort : admin
In der alten version über die Datei!!!!
Diese ändern wir ab in der Datei /etc/wireguard/db/server/users.json
nano /etc/wireguard/db/server/users.json
Inhalt, einfach neues Passwort setzten
{
"username": "admin",
"password": "<neues passwort>"
}
In der neuen Version endlich über GUI.
Auf User Setting und dann Edit.
Endlich können auch mehrere Benutzer erstellt werden ;-)
Über den Button new user oben rechts
Nun neues Passwort vergeben und auf save klicken
Teil 2. Email sender Einrichten (Optional)
Wenn man gerne die Files per Email versendet möchte müssen in der Service Datei folgende Environment Variablen angelegt werden
Die Service datei editieren
nano /etc/systemd/system/wgui-web.service
Das SMTP PASSWORT muss leer gesetzt werden.
und in die Passwort Datei muss das Passwort
| Variable |
Möcgliche optionen |
SMTP_AUTH_TYPE |
Die SMTP authentication Typen. : PLAIN, LOGIN, NONE |
SMTP_ENCRYPTION |
Dieencryption Methode. : NONE, SSL, SSLTLS, TLS, STARTTLSjenachdem was für ein Port gesetzt wurde |
Inhalt hinzufügen
[Unit]
Description=WireGuard UI
[Service]
Type=simple
ExecStart=/etc/wireguard/start-wgui.sh
Environment="SMTP_HOSTNAME=<smtpserver>"
Environment="SMTP_PORT=465"
Environment="SMTP_USERNAME=<benutzername>"
Environment="SMTP_PASSWORD="
Environment="SMTP_PASSWORD_FILE=/etc/wireguard/smtppass"
Environment="SMTP_AUTH_TYPE=LOGIN"
Environment="SMTP_ENCRYPTION=SSL"
Environment="EMAIL_FROM_ADDRESS=<emailadresse>"
Environment="EMAIL_FROM_NAME="Anzeigename"
[Install]
WantedBy=multi-user.target
Danach den Systemd daemon neustarten
systemctl daemon-reload
Nun die Passwortfile erstellen
nano /etc/wireguard/smtppass
Inhalt
absolutgeheimesmtppasswort
Nun den Dienst neustarten
service wgui-web restart
Nun kann man über die GUI die Datei wegsenden.
Dazu bei dem Client auf den Button Email klicken
Nun entweder hinterleget Adresse nutzen, oder andere eingeben dann auf send
Die Email wurde erfolgreich gesendet
Teil 3. Weiter in der Webgui
Nach dem Einloggen links auf den Menüpunkt Global Settings.
Die Endpoint Address mit dem DNS namen oder Public ip tauschen.
um die Public IP rauszubekommen, im Terminal.
curl ifconfig.me
DNS Server auf 8.8.8.8 setzen und MTU rauslöschen.und auf save klicken
und dann apply Config klicken
Dann sehe das ganze so aus als Beispiel
Nun auf den Menüpunkt links Wireguard Server.
Nun mittels terminal und ip a herausfinden welche Netzwerkkarte für lan es gibt.
Ausgabe
ip a
ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 2a:xx:xxx:xx:85 brd ff:ff:ff:ff:ff:ff
altname enp0s18
Nun bei Postup folgendes eintragen (die ens18 durch eure Netzwerkkarte erstezen)
iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j
ACCEPT; iptables -t nat -A POSTROUTING -o ens18 -j MASQUERADE
Nun bei Postdown folgendes eintragen (die ens18 durch eure Netzwerkkarte erstezen)
iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o
%i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens18 -j MASQUERADE
Nun auf save
und apply config klicken
Dann sieht das ganze so aus.
Damit ist die Installation abgeschlossen
Clients einrichten
In der Weboberfläche einloggen dann im Menü links auf Wireguard Clients gehen
Nun oben rechts auf New Client klicken.
Nun folgendes Ausfüllen:
Name : Name des Clients
Email : Email des Clients
IP-Allocations (so lassen nichts ändern)
Allowed IPs. Alles rauslöschen und 10.252.1.0/24 eintragen und als zweiten werd euer netzt was Ihr erreichen wollt in diesem Fall 192.168.178./24
Use server DNS : haken raus
Dann sehe das ganze so aus:
Nun wieder auf apply Config oben rechts
Nun steht in der liste unser Client in der Liste.
Über Download wird die wiregaurd conf downgeloaded und über QR Code der Code angezeigt
Damit ist unser Client eingerichtet und einsatzbereit.
Wer einen Postfix konfiguerieren möchte, kann auch die Email senden funktion nutzen.
Wireguard Reconnect bei IP Wechsel
Windows Powershell script
Beschreibung:
Ist der Server unter einer DYN Adresse errreichbar, bekommt wireguard nicht mit, das sich die IP geändert hat.
Dazu müssen wir den Dienst neustarten. Dazu nehmen wir ein Powershell Script, das immer die aktuelle mit der alten IP alle 5 Minuten vergleicht.
Das alle 5 Minuten rufen wir mit bdem Taskplaner auf
Los gehts:
Tunnelname herausbekommen.
Unter Windows Dienste den Tunnel raussuchen
In unserem Beispiel heißt der Tunnel "WireGuardTunnel$tk-anlage"
Das Script:
Hier muss noch der Pfad zur TXT Datei, zur Log Datei und der Tunnelname angeben werden.
Das WireGuardTunnel steht schon da, es muss nur noch der Name mit dem Dollar angegben werden.
Das Dollar muss mit ` escaped werden. : Beispiel : $TunnelName = "`$tk-anlage"
$FilePath = 'path\to\ip.txt'
$LogPath = 'path\to\ip.log'
$TunnelName = "`$meintunnelnamenachdemdollar"
function Write-Log {
param (
[string]$Message
)
Add-Content -Path $Global:LogPath -Value "[$(Get-Date)] $Message"
}
try {
$CurrentIP = (Invoke-RestMethod -Uri 'http://ifconfig.me/ip').Trim()
Write-Log "Aktuelle IP: $CurrentIP"
$StoredIP = Get-Content $FilePath -ErrorAction SilentlyContinue
Write-Log "Gespeicherte IP: $StoredIP"
if ($CurrentIP -ne $StoredIP) {
Write-Log "IP-Adresse hat sich geändert. Neustart des Dienstes..."
# Neustart des WireGuard-Dienstes und Erfassung der Ausgabe
$ServiceRestartOutput = Restart-Service -Name "WireGuardTunnel$TunnelName" -PassThru
Write-Log "Dienstneustart-Ausgabe: $ServiceRestartOutput"
# Aktualisierung der gespeicherten IP-Adresse
Set-Content -Path $FilePath -Value $CurrentIP
Write-Log "Die gespeicherte IP-Adresse wurde aktualisiert."
}
}
catch {
# Logging von Fehlern
Write-Log "Es gab einen Fehler beim Abrufen der aktuellen IP-Adresse oder beim Neustart des Dienstes: $_"
}
Beispiel:
$FilePath = 'c:\tunnel\ip.txt'
$LogPath = 'c:\unnel\log.txt'
$TunnelName = "`$tk-anlage"
function Write-Log {
param (
[string]$Message
)
Add-Content -Path $Global:LogPath -Value "[$(Get-Date)] $Message"
}
try {
$CurrentIP = (Invoke-RestMethod -Uri 'http://ifconfig.me/ip').Trim()
Write-Log "Aktuelle IP: $CurrentIP"
$StoredIP = Get-Content $FilePath -ErrorAction SilentlyContinue
Write-Log "Gespeicherte IP: $StoredIP"
if ($CurrentIP -ne $StoredIP) {
Write-Log "IP-Adresse hat sich geändert. Neustart des Dienstes..."
# Neustart des WireGuard-Dienstes und Erfassung der Ausgabe
$ServiceRestartOutput = Restart-Service -Name "WireGuardTunnel$TunnelName" -PassThru
Write-Log "Dienstneustart-Ausgabe: $ServiceRestartOutput"
# Aktualisierung der gespeicherten IP-Adresse
Set-Content -Path $FilePath -Value $CurrentIP
Write-Log "Die gespeicherte IP-Adresse wurde aktualisiert."
}
}
catch {
# Logging von Fehlern
Write-Log "Es gab einen Fehler beim Abrufen der aktuellen IP-Adresse oder beim Neustart des Dienstes: $_"
}
Task Planen
Programm zum starten wählen:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Als Parameter
-ExecutionPolicy Bypass -File "C:\Pfad\zu\Ihrem\Skript.ps1"
In unserem Beispiel
-ExecutionPolicy Bypass -File "c:\tunnel\reconnect.ps1"
Nun in den erweitertet Eigenschaften jeden Tag um 00:00 UHR und Ausführung alle 5 Minuten auswählen und Ausführung alle 1 Tag!
Den Haken bei Aktiviert nicht vergessen!
Nun noch mit Windows 10 auswählen und unabhängig von der Benutzeranmeldung ausführen auswählen.
Dann noch mit höchsten Privilegien ausführen.
Fertig.
Wireguard Clients
Linux Wireguard UI Client
Beschreibung:
Einen Wireguard Tunnel kann man natürlich mit wg-quick up / down starten und stoppen.
Aber angenehmer ist es ja über die GUI eine Tunnelverwaltung zu haben.
leider gibt es von Wireguard nur Offical einen Windows client mit UI.
Aber Gott sei dank, hat sich ein Freiwilliger, die mühe gemacht und einen Client designed.
Vielleicht design ich ja auch noch mal einen.
Dieser client listet die confs aus /etc/wireguard auf oder fügt welche hinzu.
Das UI ist fast identisch mit dem vom Windows
Vorraussetzungen:
GLIBC_2.32 oder GLIBC_2.34
sudo apt install libc6
Bei Debian 13
sudo apt install pkexec
Installation:
Einfach die deb Datei runterladen und installieren.
Gibt es zur Zeit als Release nur für amd64.
Wer andere Platformen braucht, den Quelltext kompilieren.
Hier downloaden
https://github.com/UnnoTed/wireguird/releases/tag/v1.1.0
So sieht das ganze dann aus
Fehler:
sudo wireguird
/opt/wireguird/wireguird: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /opt/wireguird/wireguird)
/opt/wireguird/wireguird: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /opt/wireguird/wireguird)
Wie wir sehen haben wir gblib c 2.31, diese Version ist zu klein.
Betriebssystem updaten, wenn in den Paketquellen keine neuere Version ist.
sudo apt install libc6
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut.
Statusinformationen werden eingelesen.... Fertig
libc6 ist schon die neueste Version (2.31-0ubuntu9.14).
Fehlerbehebungen
/usr/bin/wg-quick: line 31: resolvconf: command not found
Beschreibung:
Sollte dieser Fehler beim wg-quick up <verbindungsname> auftauchen
/usr/bin/wg-quick: line 31: resolvconf: command not found
Dann fehlt resolvconf Paket.
Dieses einfach installieren, mit oder ohne sudo je nach dem:
sudo apt install resolvconf
Fertig
Wireguard Site2Site Tunnel
Site2Site Tunnel mit nur einer Öffentlichen statischen ip auf einer Seite
Beschreibung:
Es gibt Situationen da möchte man zwei Netzwerke miteinander verbinden.
hier zu ein kleines Script das zwei Wireguard configs erstellt.
Das Script:
nano make_wg_s2s.py
Inhalt
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import base64
import ipaddress
import os
import shutil
import subprocess
import sys
from typing import List, Optional, Tuple
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
# ---------- Key generation ----------
def have_cmd(cmd: str) -> bool:
return shutil.which(cmd) is not None
def gen_keys_with_wg() -> Tuple[str, str]:
priv = subprocess.check_output(["wg", "genkey"], text=True).strip()
pub = subprocess.check_output(["wg", "pubkey"], input=priv, text=True).strip()
if not priv or not pub:
raise RuntimeError("wg returned empty key(s)")
return priv, pub
def gen_keys_with_pynacl_or_crypto() -> Tuple[str, str]:
try:
from nacl.public import PrivateKey
sk = PrivateKey.generate()
priv_b = bytes(sk._private_key)
pub_b = bytes(sk.public_key._public_key)
return base64.b64encode(priv_b).decode(), base64.b64encode(pub_b).decode()
except Exception:
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
from cryptography.hazmat.primitives import serialization
sk = X25519PrivateKey.generate()
priv_b = sk.private_bytes(
encoding=serialization.Encoding.Raw,
format=serialization.PrivateFormat.Raw,
encryption_algorithm=serialization.NoEncryption(),
)
pub_b = sk.public_key().public_bytes(
encoding=serialization.Encoding.Raw,
format=serialization.PublicFormat.Raw
)
return base64.b64encode(priv_b).decode(), base64.b64encode(pub_b).decode()
def gen_keypair() -> Tuple[str, str]:
if have_cmd("wg"):
try:
return gen_keys_with_wg()
except Exception as e:
eprint(f"Warnung: wg keygen fehlgeschlagen: {e}")
# Fallback
try:
return gen_keys_with_pynacl_or_crypto()
except Exception as e:
eprint("Fehler: Konnte keinen Schlüssel erzeugen. Installiere 'wireguard-tools' ODER 'pynacl' ODER 'cryptography'.")
eprint(f"Details: {e}")
sys.exit(3)
# ---------- Helpers ----------
def parse_ip(addr: str, allow_v6: bool) -> ipaddress._BaseAddress:
ip = ipaddress.ip_address(addr)
if ip.version == 6 and not allow_v6:
raise ValueError("IPv6 angegeben, aber --ipv6 nicht gesetzt.")
return ip
def parse_cidr_list(text: str, allow_v6: bool) -> List[str]:
nets = []
for token in [t.strip() for t in text.split(",") if t.strip()]:
net = ipaddress.ip_network(token, strict=False)
if net.version == 6 and not allow_v6:
raise ValueError("IPv6-Netz angegeben, aber --ipv6 nicht gesetzt.")
nets.append(str(net))
return nets
def ensure_single_host_cidr(ip: str) -> str:
ipobj = ipaddress.ip_address(ip)
return f"{ip}/{32 if ipobj.version == 4 else 128}"
def prompt(msg: str, default: Optional[str]=None, required: bool=True) -> str:
suffix = f" [{default}]" if default else ""
while True:
val = input(f"{msg}{suffix}: ").strip()
if not val and default is not None:
return default
if val or not required:
return val
print("Bitte Wert eingeben.")
def uniq(seq: List[str]) -> List[str]:
seen = set()
out = []
for x in seq:
if x not in seen:
seen.add(x)
out.append(x)
return out
# ---------- CLI ----------
def build_args() -> argparse.Namespace:
p = argparse.ArgumentParser(
description="Erstellt WireGuard Site-to-Site Configs (nur eine Seite öffentlich erreichbar).",
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
p.add_argument("--name", help="Projektname (Verzeichnis wird angelegt)")
p.add_argument("--public-endpoint", help="Domain oder IP der öffentlichen Seite (z.B. vpn.example.com)")
#p.add_argument("--public-port", type=int, default=51820, help="UDP-Port der öffentlichen Seite")
p.add_argument("--public-port", type=int, default=None, help="UDP-Port der öffentlichen Seite (Standard: 51820)")
p.add_argument("--public-wg-ip4", help="WG-IPv4 der öffentlichen Seite (z.B. 10.10.0.1)")
p.add_argument("--private-wg-ip4", help="WG-IPv4 der privaten Seite (leer lassen um keine Address zu setzen)")
p.add_argument("--public-lans", help="Komma-Liste LAN-Netze hinter öffentlicher Seite (z.B. 192.168.10.0/24,192.168.11.0/24)")
p.add_argument("--private-lans", help="Komma-Liste LAN-Netze hinter privater Seite")
p.add_argument("--ipv6", action="store_true", help="IPv6 zusätzlich konfigurieren")
p.add_argument("--public-wg-ip6", help="WG-IPv6 der öffentlichen Seite (z.B. fd00:10:10::1)")
p.add_argument("--private-wg-ip6", help="WG-IPv6 der privaten Seite (leer lassen erlaubt)")
p.add_argument("-v", "--verbose", action="store_true", help="Mehr Ausgaben")
return p.parse_args()
# ---------- Main ----------
def main():
print("Start…")
args = build_args()
if args.verbose:
print("Argumente empfangen:", args)
# Eingaben einsammeln
proj = args.name or prompt("Projektname")
base_dir = os.path.abspath(proj)
if os.path.exists(base_dir):
eprint(f"Projekt '{proj}' gibt’s schon – nichts überschrieben.")
sys.exit(1)
public_endpoint = args.public_endpoint or prompt("Public Endpoint (Domain oder IP)")
# NEU:
if args.public_port is None:
port_str = prompt("Public UDP-Port", default="51820", required=False)
public_port = int(port_str or "51820")
else:
public_port = args.public_port
public_wg_ip4 = args.public_wg_ip4 or prompt("WG-IPv4 der öffentlichen Seite (z.B. 10.10.0.1)")
private_wg_ip4 = args.private_wg_ip4
if private_wg_ip4 is None:
private_wg_ip4 = prompt("WG-IPv4 der privaten Seite (leer = keine Address)", required=False)
public_lans = parse_cidr_list(args.public_lans, allow_v6=args.ipv6) if args.public_lans else []
if not args.public_lans:
val = prompt("LAN-Netze öff. Seite (Komma, leer für keine)", required=False)
if val:
public_lans = parse_cidr_list(val, allow_v6=args.ipv6)
private_lans = parse_cidr_list(args.private_lans, allow_v6=args.ipv6) if args.private_lans else []
if not args.private_lans:
val = prompt("LAN-Netze private Seite (Komma, leer für keine)", required=False)
if val:
private_lans = parse_cidr_list(val, allow_v6=args.ipv6)
v6_enabled = bool(args.ipv6)
public_wg_ip6 = args.public_wg_ip6
private_wg_ip6 = args.private_wg_ip6
if v6_enabled:
public_wg_ip6 = public_wg_ip6 or prompt("WG-IPv6 öff. Seite (z.B. fd00:10:10::1)")
if private_wg_ip6 is None:
private_wg_ip6 = prompt("WG-IPv6 private Seite (leer = keine Address)", required=False)
# Validierung
try:
parse_ip(public_wg_ip4, allow_v6=False)
if private_wg_ip4:
parse_ip(private_wg_ip4, allow_v6=False)
if v6_enabled:
parse_ip(public_wg_ip6, allow_v6=True)
if private_wg_ip6:
parse_ip(private_wg_ip6, allow_v6=True)
except Exception as e:
eprint(f"IP-Fehler: {e}")
sys.exit(2)
# Dirs
pub_dir = os.path.join(base_dir, "public")
prv_dir = os.path.join(base_dir, "private")
os.makedirs(pub_dir, exist_ok=False)
os.makedirs(prv_dir, exist_ok=False)
if args.verbose:
print("Projektverzeichnis:", base_dir)
# Keys
print("Erzeuge Schlüsselpaare…")
server_priv, server_pub = gen_keypair() # öffentliche Seite
client_priv, client_pub = gen_keypair() # private Seite
# Interface-Adressen
iface_addrs_public = [f"{public_wg_ip4}/32"]
iface_addrs_private: List[str] = []
if private_wg_ip4:
iface_addrs_private.append(f"{private_wg_ip4}/32")
peer_allowed_from_client = [ensure_single_host_cidr(public_wg_ip4)]
peer_allowed_from_server = []
if private_wg_ip4:
peer_allowed_from_server.append(ensure_single_host_cidr(private_wg_ip4))
if v6_enabled:
iface_addrs_public.append(f"{public_wg_ip6}/128")
if private_wg_ip6:
iface_addrs_private.append(f"{private_wg_ip6}/128")
peer_allowed_from_client.append(ensure_single_host_cidr(public_wg_ip6))
if private_wg_ip6:
peer_allowed_from_server.append(ensure_single_host_cidr(private_wg_ip6))
# LANs ergänzen
if private_lans:
peer_allowed_from_server.extend(private_lans)
if public_lans:
peer_allowed_from_client.extend(public_lans)
peer_allowed_from_client = uniq(peer_allowed_from_client)
peer_allowed_from_server = uniq(peer_allowed_from_server)
# Config rendern
public_conf = "[Interface]\n"
public_conf += f"Address = {', '.join(iface_addrs_public)}\n"
public_conf += f"ListenPort = {public_port}\n"
public_conf += f"PrivateKey = {server_priv}\n"
public_conf += "# SaveConfig = false\n\n"
public_conf += "[Peer]\n"
public_conf += f"PublicKey = {client_pub}\n"
if peer_allowed_from_server:
public_conf += f"AllowedIPs = {', '.join(peer_allowed_from_server)}\n"
public_conf += "PersistentKeepalive = 25\n"
private_conf = "[Interface]\n"
if iface_addrs_private:
private_conf += f"Address = {', '.join(iface_addrs_private)}\n"
private_conf += f"PrivateKey = {client_priv}\n"
private_conf += "# SaveConfig = false\n\n"
private_conf += "[Peer]\n"
private_conf += f"PublicKey = {server_pub}\n"
private_conf += f"Endpoint = {public_endpoint}:{public_port}\n"
private_conf += f"AllowedIPs = {', '.join(peer_allowed_from_client)}\n"
private_conf += "PersistentKeepalive = 25\n"
# Schreiben
with open(os.path.join(pub_dir, "wg0.conf"), "w") as f:
f.write(public_conf)
with open(os.path.join(prv_dir, "wg0.conf"), "w") as f:
f.write(private_conf)
readme = (
f"# {proj} – WireGuard Site-to-Site\n\n"
"Dieses Projekt erzeugt zwei Konfigurationen:\n\n"
f"- public/wg0.conf → Öffentliche Seite (ListenPort: {public_port}, Endpoint: {public_endpoint})\n"
"- private/wg0.conf → Private Seite (hinter NAT; verbindet aktiv zum Endpoint)\n\n"
"Start (Beispiel):\n"
" wg-quick up wg0\n\n"
"Tipps:\n"
" IPv4 Forwarding: sysctl -w net.ipv4.ip_forward=1\n"
" IPv6 Forwarding: sysctl -w net.ipv6.conf.all.forwarding=1\n"
" Routen/Firewall: LANs erlauben/setzen.\n"
)
with open(os.path.join(base_dir, "README.md"), "w") as f:
f.write(readme)
print("Fertig!")
print(" -", os.path.join(pub_dir, "wg0.conf"))
print(" -", os.path.join(prv_dir, "wg0.conf"))
print("Nichts wurde überschrieben.")
if __name__ == "__main__":
try:
main()
except SystemExit as se:
# argparse nutzt SystemExit – durchreichen
raise
except Exception as ex:
eprint("Unerwarteter Fehler:", ex)
import traceback
traceback.print_exc()
sys.exit(99)
Verwendung:
1) **Interaktiv** (alles wird abgefragt)
python3 make_wg_s2s.py
2) **Parameter gesteuert für ipv4**
python3 make_wg_s2s.py \
--name firma-tunnel \
--public-endpoint vpn.example.com \
--public-port 51820 \
--public-wg-ip4 10.10.0.1 \
--private-wg-ip4 10.10.0.2 \
--public-lans 192.168.10.0/24 \
--private-lans 192.168.20.0/24
3) **Parameter gesteuert für ipv6**
python3 make_wg_s2s.py \
--name firma-v6 \
--public-endpoint v6.example.com \
--public-port 51820 \
--public-wg-ip4 10.10.0.1 \
--private-wg-ip4 10.10.0.2 \
--ipv6 \
--public-wg-ip6 fd00:10:10::1 \
--private-wg-ip6 fd00:10:10::2 \
--public-lans 192.168.10.0/24,fd00:aaaa::/64 \
--private-lans 192.168.20.0/24,fd00:bbbb::/64
Wireguard Proxy
Einrichtung
Beschreibung:
Wireguardproxy, dient dazu einen wirguardclient über http zu tunnel.
Das bedueted auf dem Client Rechner läuft ein bridge Client (Der braucht keine Admin rechte) der den wireguard traffic in den http tunnel jagt. und der Server nimm den traffic an und leitet ihn an den wireguard Server weiter.
Der eigetliche wireguard client hat dann als IP Adresse nicht mehr den wireguard Server sondern 127.0.0.1 nämlich den Client rechner weil auf dem gleichen port der http proxy client lauscht
Verbindungsschema
Echte Wireguard Client (127.0.0.1:51820) -> HTTP PROXY_CLIENT_LOKAL -> Internet -> HTTP_PROXY_SERVER -> echter wireguard Server (127.0.0.1:51820)
Installtion Docker container:
Dieser braucht keinerlei Konfiguration.
Einfach auf dem wirgeuard Server starten fertig.
Download docker-compose Datei : docker-compose.yml
und Dockerfile : Dockerfile
Docker compose
services:
wstunnel:
build: .
image: wstunnel-custom
container_name: wstunnel
restart: unless-stopped
network_mode: host
# Laeuft als root -> darf Port 443 binden
# Kein Gefummel mit Entrypoint oder Capabilities noetig
# network_mode: host wird benötigt damit wstunnel
# den WireGuard Port auf localhost erreichen kann (127.0.0.1:51820)
Dockerfile:
FROM debian:bookworm-slim
ARG TARGETARCH
ENV DEBIAN_FRONTEND=noninteractive
# curl fuer den Download, ca-certificates fuer HTTPS
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates tar && \
rm -rf /var/lib/apt/lists/*
# Aktuelle Version von GitHub API ermitteln und Binary herunterladen
RUN set -eux; \
VERSION=$(curl -fsSL https://api.github.com/repos/erebe/wstunnel/releases/latest \
| grep '"tag_name"' | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/'); \
VERNUM="${VERSION#v}"; \
case "$(uname -m)" in \
x86_64) ARCH="amd64" ;; \
aarch64) ARCH="arm64" ;; \
armv7*) ARCH="armv7" ;; \
*) echo "Unsupported arch: $(uname -m)"; exit 1 ;; \
esac; \
echo "Downloading wstunnel ${VERSION} for ${ARCH}..."; \
curl -fsSL "https://github.com/erebe/wstunnel/releases/download/${VERSION}/wstunnel_${VERNUM}_linux_${ARCH}.tar.gz" \
| tar -xz -C /usr/local/bin wstunnel; \
chmod +x /usr/local/bin/wstunnel; \
wstunnel --version
EXPOSE 443
ENTRYPOINT ["/usr/local/bin/wstunnel"]
CMD ["server", "--restrict-to", "127.0.0.1:51820", "wss://0.0.0.0:443"]
Proxy Client installtion:
Windows:
Hier den Servernamen und die IPs anpassen
Download bat : start_wstunnel.bat
@echo off
setlocal enabledelayedexpansion
:: ============================================================
:: wstunnel Client - WireGuard over WebSocket
:: Anpassen: PROXY_SERVER = Domainname eures wstunnel-Servers
:: ============================================================
set PROXY_SERVER=vpn.example.com
:: Lokaler UDP Port fuer WireGuard (muss mit WG Endpoint uebereinstimmen)
set LOCAL_WG_PORT=51820
:: Remote WireGuard Port auf dem Server
set REMOTE_WG_PORT=51820
:: wstunnel Binary
set WSTUNNEL=%~dp0wstunnel.exe
:: GitHub Download URL (latest release, Windows x64)
set DOWNLOAD_URL=https://github.com/erebe/wstunnel/releases/latest/download/wstunnel_x86_64-pc-windows-msvc.exe
:: ============================================================
echo.
echo ############################################
echo wstunnel WireGuard Proxy
echo ############################################
echo.
echo Server : %PROXY_SERVER%
echo Tunnel : UDP localhost:%LOCAL_WG_PORT% --^> %PROXY_SERVER%:%REMOTE_WG_PORT%
echo.
:: --- Pruefen ob wstunnel.exe vorhanden ---
if exist "%WSTUNNEL%" goto :start
echo [!] wstunnel.exe nicht gefunden.
echo [*] Versuche automatischen Download via wget...
echo.
:: wget verfuegbar?
where wget >nul 2>&1
if %errorlevel% neq 0 (
echo [!] wget nicht gefunden. Versuche PowerShell...
goto :download_ps
)
wget --no-check-certificate -q --show-progress -O "%WSTUNNEL%" "%DOWNLOAD_URL%"
if %errorlevel% neq 0 (
echo [!] wget Download fehlgeschlagen. Versuche PowerShell...
goto :download_ps
)
goto :download_ok
:download_ps
echo [*] Lade via PowerShell (Invoke-WebRequest)...
powershell -NoProfile -Command ^
"Invoke-WebRequest -Uri '%DOWNLOAD_URL%' -OutFile '%WSTUNNEL%' -UseBasicParsing"
if %errorlevel% neq 0 (
echo.
echo [FEHLER] Download fehlgeschlagen!
echo Bitte manuell herunterladen:
echo %DOWNLOAD_URL%
echo und als wstunnel.exe in diesen Ordner legen.
echo.
pause
exit /b 1
)
:download_ok
if not exist "%WSTUNNEL%" (
echo [FEHLER] wstunnel.exe nach Download nicht gefunden!
pause
exit /b 1
)
echo [OK] wstunnel.exe erfolgreich heruntergeladen.
echo.
:start
echo Bitte WireGuard Endpoint auf 127.0.0.1:%LOCAL_WG_PORT% setzen!
echo Fenster offen lassen solange VPN aktiv ist.
echo.
pause
"%WSTUNNEL%" client ^
-L "udp://%LOCAL_WG_PORT%:127.0.0.1:%REMOTE_WG_PORT%?timeout_sec=0" ^
"wss://%PROXY_SERVER%:443"
echo.
echo wstunnel beendet.
pause
Linux:
Hier den Servernamen und die IPs anpassen
Download bat : start_wstunnel.sh
#!/bin/bash
# ============================================================
# wstunnel Client - WireGuard over WebSocket
# Anpassen: PROXY_SERVER = Domainname eures wstunnel-Servers
# ============================================================
PROXY_SERVER="vpn.example.com"
# Lokaler UDP Port fuer WireGuard (muss mit WG Endpoint uebereinstimmen)
LOCAL_WG_PORT=51820
# Remote WireGuard Port auf dem Server
REMOTE_WG_PORT=51820
# wstunnel Binary (im selben Ordner oder im PATH)
WSTUNNEL="wstunnel"
# ============================================================
# Farben
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo ""
echo -e "${GREEN} *** wstunnel WireGuard Proxy ***${NC}"
echo -e " Server : ${YELLOW}${PROXY_SERVER}${NC}"
echo -e " Tunnel : UDP localhost:${LOCAL_WG_PORT} --> ${PROXY_SERVER}:${REMOTE_WG_PORT}"
echo ""
echo -e "${YELLOW} Bitte WireGuard Endpoint auf 127.0.0.1:${LOCAL_WG_PORT} setzen!${NC}"
echo " Skript laufen lassen solange VPN aktiv ist."
echo ""
# Pruefen ob wstunnel vorhanden
if ! command -v "$WSTUNNEL" &>/dev/null && [ ! -f "./$WSTUNNEL" ]; then
echo -e "${RED} FEHLER: wstunnel nicht gefunden!${NC}"
echo " Download: https://github.com/erebe/wstunnel/releases"
echo " Binary nach /usr/local/bin/wstunnel kopieren oder in diesen Ordner legen."
exit 1
fi
# Lokales wstunnel bevorzugen falls vorhanden
if [ -f "./wstunnel" ]; then
WSTUNNEL="./wstunnel"
chmod +x "$WSTUNNEL"
fi
echo -e "${GREEN} Starte Tunnel...${NC}"
echo ""
# Sauber beenden bei Strg+C
trap 'echo -e "\n${YELLOW} Tunnel beendet.${NC}"; exit 0' SIGINT SIGTERM
"$WSTUNNEL" client \
-L "udp://${LOCAL_WG_PORT}:127.0.0.1:${REMOTE_WG_PORT}?timeout_sec=0" \
"wss://${PROXY_SERVER}:443"
echo ""
echo -e "${YELLOW} wstunnel beendet.${NC}"
Der echte Wireguard Client:
Jetzt muss nur nur noch im Echten wireguard client der endpunkt auf 127.0.0.1 geändert werden
Endpoint = 127.0.0.1:51820