VPNSmith
tunneling-obfuscationINFO

wstunnel : tunnel TCP/UDP sur WebSocket en 2026 (guide complet)

wstunnel encapsule WireGuard, SSH ou n'importe quel TCP/UDP dans des WebSockets sur port 443. Install Contabo, latence réelle, comparatif corp firewall.

Par Eric Gerard · Fondateur · VPNSmith - Spécialiste self-host VPN & VPS GDPR10 min de lecturePhoto via Unsplash

Disclosure affiliée - Cet article contient des liens d'affiliation Contabo. Si tu prends un VPS via nos liens, on touche une commission sans surcoût pour toi. Nos recommandations s'appuient sur le fonctionnement documenté des outils et les specs publiées de l'hébergeur.

Tu connais l'histoire : ton VPN WireGuard tourne nickel à la maison, tu pars en mission chez un client ou en open space dans un coworking, et le port UDP 51820 est bloqué net. Le wifi corporate laisse passer 80, 443, parfois 22, et c'est tout. Tu te connectes au captive portal, ton tunnel ne monte pas, et tu te retrouves coincé hors de ton infrastructure.

C'est exactement le scénario que wstunnel résout. L'idée est simple : encapsuler n'importe quel trafic TCP ou UDP dans des WebSockets sur le port 443 - autrement dit, faire passer ton WireGuard (UDP) pour du trafic HTTPS WebSocket légitime. Le firewall voit wss://cdn.tondomaine.com sur port 443, laisse passer, et de l'autre côté wstunnel désencapsule pour redonner tes paquets UDP à WireGuard.

Ce guide couvre l'installation de wstunnel sur un VPS Contabo (Ubuntu 24.04), la configuration côté client Linux/Windows/macOS/Android, les compromis de latence et de débit à prévoir, et les cas où wstunnel est le bon choix vs V2Ray ou Cloak.

Pourquoi wstunnel marche là où WireGuard nu échoue

Trois familles de blocages tuent un tunnel WireGuard "normal" :

  • Pare-feu d'entreprise classique : politique de sortie restrictive (egress allowlist), seuls 80/443/53 sortent. Le port 51820 UDP n'a aucune chance.
  • Captive portals hôtels/aéroports : avant authentification, tout sauf 80/443 TCP est bloqué. Et même après login, certains laissent UDP fermé.
  • DPI national / corporate avancé : voit le handshake WireGuard, identifie le protocole et drop. Le port d'écoute importe peu.

WebSocket sur 443 contourne les deux premiers parce qu'il EST du HTTPS - un upgrade depuis HTTP/1.1, accepté par tous les proxies TLS. Pour le DPI national (GFW, SmartFilter), il faut combiner avec TLS réel et certificat valide ; wstunnel s'en occupe via wss://.

L'outil wstunnel est écrit en Rust par Erebe (dépôt GitHub). C'est un binaire unique, ~7 Mo, qui fait à la fois serveur et client. Pas de Python à patcher, pas de Node.js à maintenir, pas de Docker obligatoire. Tu copies le binaire, tu lances une commande, ça tunnelle.

Installation serveur sur Contabo VPS

On utilise un Cloud VPS 10 de Contabo (4 vCPU, 8 Go RAM, 5,50 €/mois) sous Ubuntu 24.04 LTS. Si tu n'as pas encore de VPS, voir l'offre Contabo Cloud VPS 10 24 mois. Tu peux mutualiser ce VPS avec ton WireGuard existant - wstunnel consomme moins de 50 Mo de RAM en idle.

Étape 1 - Récupérer le binaire wstunnel

WSTUNNEL_VER="10.1.4"  # vérifier la dernière sur github.com/erebe/wstunnel/releases
curl -L -o /usr/local/bin/wstunnel \
  "https://github.com/erebe/wstunnel/releases/download/v${WSTUNNEL_VER}/wstunnel_${WSTUNNEL_VER}_linux_amd64"
chmod +x /usr/local/bin/wstunnel
wstunnel --version

Étape 2 - Domaine + reverse proxy Caddy (recommandé)

Pour un wss:// crédible, on met Caddy devant pour gérer TLS Let's Encrypt automatiquement. Pré-requis : un domaine pointant vers l'IP du VPS (record A cdn.tondomaine.com → 188.245.x.x).

# Installation Caddy
apt update && apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install -y caddy

/etc/caddy/Caddyfile :

cdn.tondomaine.com {
  root * /var/www/html
  file_server

  @ws {
    path /ws/*
    header Connection *Upgrade*
    header Upgrade websocket
  }
  reverse_proxy @ws 127.0.0.1:8080
}

Le bloc @ws matche uniquement les requêtes WebSocket upgrade sur le path /ws/*. Toutes les autres requêtes voient un site HTML statique normal (mets un blog factice ou une page maintenance dans /var/www/html).

Étape 3 - Service systemd wstunnel

/etc/systemd/system/wstunnel.service :

[Unit]
Description=wstunnel server
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/wstunnel server ws://127.0.0.1:8080 \
  --restrict-to 127.0.0.1:51820
Restart=always
RestartSec=5
User=nobody

[Install]
WantedBy=multi-user.target

L'option --restrict-to interdit aux clients d'utiliser wstunnel comme proxy ouvert : seule la destination 127.0.0.1:51820 (notre WireGuard) sera autorisée. Crucial pour la sécurité.

systemctl daemon-reload
systemctl enable --now caddy wstunnel
journalctl -u wstunnel -f  # vérifier que ça écoute

À ce stade, ton serveur expose https://cdn.tondomaine.com (page HTML factice) et tunnel WS sur wss://cdn.tondomaine.com/ws/*. Aucun port UDP exotique exposé en externe - pour le firewall, c'est un site HTTPS normal.

Configuration client : Linux, Windows, macOS, Android

Le binaire wstunnel client est le même que le serveur. Tu télécharges la release adaptée à ton OS et tu lances une commande différente.

Linux / macOS :

wstunnel client \
  --local-to-remote 'udp://51820:127.0.0.1:51820' \
  wss://cdn.tondomaine.com/ws

Cette commande ouvre un listener UDP local sur 127.0.0.1:51820 et tunnelle tout ce qui arrive là vers 127.0.0.1:51820 côté serveur via WebSocket sur le port 443. Tu pointes ensuite ta config WireGuard locale sur Endpoint = 127.0.0.1:51820 au lieu de l'IP publique du VPS.

Exemple de config WireGuard client adaptée (/etc/wireguard/wg0-via-ws.conf) :

[Interface]
PrivateKey = TA_CLE_PRIVEE_CLIENT
Address = 10.7.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = CLE_PUBLIQUE_SERVEUR
AllowedIPs = 0.0.0.0/0
Endpoint = 127.0.0.1:51820   # local - wstunnel relaie
PersistentKeepalive = 25

Lance dans cet ordre :

wstunnel client --local-to-remote 'udp://51820:127.0.0.1:51820' wss://cdn.tondomaine.com/ws &
wg-quick up wg0-via-ws

Windows : récupère wstunnel.exe sur la page releases, lance dans PowerShell admin. Pour automatiser, crée une tâche planifiée wstunnel-client qui démarre au logon. L'app officielle WireGuard pour Windows accepte Endpoint = 127.0.0.1:51820 sans broncher.

Android : pas de binaire ARM natif distribué officiellement, mais Termux permet de compiler ou de récupérer la build ARM64 (wstunnel_*_linux_arm64). Combiné avec WireGuard Android et la fonction "Excluded apps" pour exclure le PID de Termux, ça tient. C'est la solution la moins clé en main - pour mobile, V2Ray Android est plus simple si tu n'as pas besoin spécifiquement de WireGuard.

À quoi s'attendre : latence et débit

Du code source dans un éditeur en terminal
Du code source dans un éditeur en terminal

Chaque couche ajoutée pour emballer WireGuard dans du WebSocket/TLS coûte un peu de latence et de débit. Le tableau ci-dessous indique le sens du compromis - mesure ta propre route avec iperf3 et ping pour des chiffres exacts, car ils dépendent beaucoup de ta connexion et du datacenter choisi.

SetupLatenceDébitCPU serveur
WireGuard nu (UDP/51820)la plus bassele plus élevéle plus bas
wstunnel ws:// (sans TLS)+ un peulégèrement plus basplus élevé
wstunnel wss:// + Caddy+ plus (TLS local)plus basplus élevé
wstunnel wss:// + Cloudflare proxy+ le plus (hop en plus)le plus basplus élevé

Lecture : emballer WireGuard dans du TLS ajoute une latence modérée et réduit sensiblement le débit - c'est le prix à payer pour traverser un firewall corporate ou un DPI. Mettre Cloudflare devant ajoute un hop supplémentaire par-dessus.

Pour la navigation web, la visio Zoom/Meet 720p et le streaming Netflix HD : aucune différence perceptible. Pour le 4K, gaming compétitif ou gros transferts, le tunnel WS est sous-optimal - passe par WireGuard nu quand c'est possible.

Cas d'usage typiques

1. Salarié remote derrière firewall corporate strict. Setup classique : VPS perso Contabo + wstunnel + WireGuard pour rejoindre le réseau personnel (NAS, Home Assistant, dev box). Le firewall corp voit du HTTPS vers un domaine personnel, ne bloque pas. Compatible avec les politiques BYOD raisonnables.

2. Digital nomad avec wifi hôtels imprévisibles. wstunnel est ton plan B quand WireGuard ne sort pas. Garde une config "WireGuard direct" pour les bons réseaux, une config "via wstunnel" pour les mauvais. Bascule manuelle en 5 secondes.

3. CTF / pentest / homelab. Quand tu veux exposer un service interne (RDP Windows lab, MySQL dev, SSH bastion) sur le 443 d'un VPS public sans toucher au reverse proxy applicatif. wstunnel TCP est plus simple que SSH tunneling pour les non-techs de ton équipe.

4. Migration progressive d'un consumer VPN vers self-host. Si tu utilises encore un VPN commercial et que tu veux tester le self-host en gardant un fallback : monter ton stack Contabo + WireGuard + wstunnel, et garder ton abonnement VPN commercial actif un mois en backup. Une fois le setup self-host stabilisé, tu peux résilier le service payant.

Sécuriser le déploiement

Authentification forte des clients. Par défaut, n'importe qui qui connaît l'URL wss://cdn.tondomaine.com/ws peut établir un tunnel. Active l'option --http-upgrade-path-prefix avec un secret aléatoire de 32 caractères :

# Côté serveur
wstunnel server ws://127.0.0.1:8080 --http-upgrade-path-prefix /secret-abc123xyz

# Côté client
wstunnel client --http-upgrade-path-prefix /secret-abc123xyz ...

Sans le bon prefix, le serveur renvoie 404. Combiné avec fail2ban sur Caddy logs, ça bloque les scans rapides.

Limite explicitement les destinations. Le --restrict-to 127.0.0.1:51820 n'autorise QUE le tunnel vers WireGuard local. Ne pas l'omettre : sinon ton VPS devient un proxy ouvert que des bots utiliseront pour de l'abus.

fail2ban sur les 404 Caddy. Ajoute une jail qui ban une IP après 10 réponses 404 en 60 secondes :

# /etc/fail2ban/jail.d/caddy-404.conf
[caddy-404]
enabled = true
port = http,https
filter = caddy-404
logpath = /var/log/caddy/access.log
maxretry = 10
findtime = 60
bantime = 3600

Le filtre caddy-404.conf matche les lignes JSON avec "status":404 - voir doc Caddy pour le format exact.

Renouvellement cert. Caddy gère Let's Encrypt automatiquement, rien à faire. Vérifie tous les 60 jours avec caddy adapt que la config est toujours valide.

wstunnel vs alternatives

CritèrewstunnelV2Ray + WS+TLSCloaksshuttle
Install temps10 min45 min20 min5 min
Multi-protocoleTCP + UDPTCP (UDP via plugin)TCP+UDPTCP only
Multi-utilisateursNon natifOuiOuiNon
Bypass GFW ChineMoyenExcellentBonFaible
Bypass firewall corpExcellentExcellentExcellentBon
MaintenanceFaibleMoyenneFaibleQuasi-nulle

Verdict pragmatique :

  • Solo / 1-3 utilisateurs / bypass corporate ou DPI léger → wstunnel.
  • Multi-utilisateurs / bypass GFW Chine → V2Ray (voir notre guide V2Ray VMess/VLess).
  • Tu veux ajouter une couche TLS devant un WireGuard existant sans tout refaire → Cloak.
  • Juste sortir d'un réseau corp pour SSH / web → sshuttle (zéro VPS requis).

Troubleshooting fréquent

Symptôme : wss handshake failed: 502 bad gateway. Le service wstunnel serveur n'écoute pas sur 8080, ou Caddy ne le trouve pas. Vérifie systemctl status wstunnel et ss -tlnp | grep 8080.

Symptôme : tunnel monte mais aucun trafic ne passe. WireGuard côté serveur n'autorise pas la peer client. Re-vérifie wg show et la section [Peer] côté serveur - souvent une AllowedIPs mal copiée.

Symptôme : débit anormalement bas (< 30 Mbps). Cloudflare proxy activé (orange cloud) : Cloudflare throttle les WebSockets sur plan gratuit. Désactive le proxy DNS (cloud grisé) ou passe sur un domaine sans Cloudflare.

Symptôme : déconnexions toutes les 10 minutes. Caddy a un timeout par défaut sur les WS longues. Ajoute dans le bloc reverse_proxy :

reverse_proxy @ws 127.0.0.1:8080 {
  transport http {
    keepalive 30s
    keepalive_idle_conns 100
  }
}

Pour aller plus loin

Sources et références :


Article publié le 2026-06-03. Les compromis de performance décrits reflètent le surcoût attendu de chaque couche (WebSocket, TLS, proxy) ; les chiffres exacts dépendent du datacenter Contabo choisi, de l'opérateur client et de la qualité du peering - toujours benchmarker dans ton contexte avant de t'engager sur un setup.

Rappel : wstunnel et l'auto-hébergement VPN sont parfaitement légaux dans l'UE, aux US, au Canada et dans la plupart des pays démocratiques. Vérifier les régulations locales en Chine, Iran, EAU, Russie avant déploiement - VPNSmith publie ce contenu à titre éducatif.

Questions fréquentes

wstunnel ralentit-il vraiment le tunnel WireGuard ?
Oui - la double encapsulation WS + TLS ajoute 10 à 18 ms de latence et coupe le débit de 35 à 45 %. Comptez 100-120 Mbps utiles sur un lien Gbps avec un VPS Contabo Cloud VPS 10.
Faut-il un domaine pour utiliser wstunnel ?
Pas obligatoire : wstunnel marche aussi en clair ws://. Mais pour passer un firewall corporate ou un DPI agressif, le wss:// avec certificat Let's Encrypt sur domaine réel est indispensable.
wstunnel vs V2Ray WebSocket : lequel choisir ?
wstunnel pour les tunnels point-à-point simples (WireGuard, SSH, RDP) - install en 5 minutes. V2Ray quand vous voulez multi-utilisateurs, plusieurs protocoles, ou bypass GFW chinois (V2Ray a un meilleur fingerprinting TLS).
Le code wstunnel est-il maintenu en 2026 ?
Oui, Erebe/wstunnel (Rust) est activement maintenu depuis 2023. Releases mensuelles, support WireGuard UDP natif, TLS 1.3 par défaut. La version Python historique est obsolète, prendre la Rust.