WebSocket n'est pas une requête HTTP ordinaire. Après la première « poignée de main » (handshake), la connexion reste ouverte, et les données circulent dans les deux sens de manière continue. C'est pourquoi les proxies HTTP standard interrompent souvent les connexions WS ou ne savent pas comment les traiter. Dans cet article, nous allons examiner comment proxy correctement le trafic WebSocket : quels proxies conviennent, comment les configurer et quelles erreurs se rencontrent le plus souvent.
Comment fonctionne WebSocket et pourquoi il est difficile à proxy
Pour comprendre le problème, il faut examiner la mécanique. Une connexion WebSocket commence comme une requête HTTP ordinaire : le client envoie l'en-tête Upgrade: websocket et Connection: Upgrade. Le serveur répond par le code 101 Switching Protocols — et à partir de ce moment, la connexion cesse d'être HTTP. Elle se transforme en un canal bidirectionnel permanent, par lequel les données circulent dans des trames.
Un proxy HTTP/1.1 standard, qui ne sait que transmettre des requêtes et des réponses, se heurte à un problème : il ne sait pas quoi faire avec la connexion après la réponse 101. De nombreux serveurs proxy ferment simplement la connexion à ce moment-là ou renvoient une erreur 502 Bad Gateway. D'autres maintiennent la connexion, mais ne savent pas transmettre correctement les trames WebSocket, ce qui entraîne des interruptions ou des distorsions de données.
Voici les principales différences entre WebSocket et HTTP ordinaire du point de vue du proxy :
| Paramètre | HTTP | WebSocket |
|---|---|---|
| Type de connexion | Requête → Réponse → Fermeture | Permanent, bidirectionnel |
| Durée de vie | Secondes (une requête) | Minutes, heures, jours |
| Initiateur des données | Uniquement le client | Client et serveur |
| Protocole après handshake | HTTP | Propre (RFC 6455) |
| Ports | 80, 443 | 80 (WS), 443 (WSS) |
C'est à cause du changement de protocole après le handshake que la plupart des solutions proxy simples ne parviennent pas à gérer WebSocket. Il faut soit utiliser un proxy qui prend explicitement en charge le tunneling, soit utiliser SOCKS5 — un protocole qui fonctionne à un niveau plus bas et ne déchiffre pas le contenu du trafic.
Quels types de proxy prennent en charge WebSocket
Tous les proxies ne sont pas également utiles pour WebSocket. Examinons chaque type :
| Type de proxy | Support WS | Mécanisme | Complexité |
|---|---|---|---|
| Proxy HTTP | ⚠️ Partiellement | Via tunnel CONNECT | Moyenne |
| Proxy HTTPS | ✅ Oui | CONNECT + TLS | Moyenne |
| SOCKS4 | ⚠️ Limité | Tunnel TCP sans auth | Faible |
| SOCKS5 | ✅ Complet | TCP/UDP transparent | Faible |
| Proxy transparent | ❌ Non | Uniquement HTTP | — |
Conclusion : pour les tâches WebSocket, le choix optimal est SOCKS5. Ce protocole fonctionne au niveau de transport et tunnelise simplement la connexion TCP, sans se soucier du contenu du trafic. Peu importe s'il s'agit de HTTP, WebSocket, SSH ou autre chose. Les proxies HTTP peuvent également fonctionner avec WS, mais uniquement via la méthode CONNECT — et il y a des nuances que nous examinerons ci-dessous.
Méthode CONNECT : comment le proxy HTTP tunnelise WebSocket
La méthode HTTP CONNECT est un mécanisme spécial qui permet aux proxies HTTP de créer un tunnel « aveugle » vers le serveur cible. Le proxy n'analyse pas le trafic à l'intérieur du tunnel, mais redirige simplement les octets. C'est ainsi que fonctionne HTTPS via un proxy HTTP — et c'est ainsi que l'on peut proxy WebSocket.
Le processus est le suivant :
- Le client envoie une requête au proxy :
CONNECT example.com:443 HTTP/1.1 - Le proxy établit une connexion TCP avec
example.com:443 - Le proxy répond au client :
200 Connection Established - À partir de ce moment, le proxy transmet simplement les octets dans les deux sens — sans les analyser
- Le client effectue le handshake TLS directement avec le serveur via le tunnel
- Ensuite — le handshake WebSocket au-dessus de TLS
Limitation clé : la méthode CONNECT est généralement autorisée uniquement pour le port 443. Si votre serveur WebSocket fonctionne sur un port non standard (par exemple, 8080 ou 9000), le proxy peut refuser la connexion. Dans ce cas, SOCKS5 est préférable — il n'a pas de restrictions de port.
Il est également important de noter que certains proxies HTTP d'entreprise (comme Squid dans sa configuration standard) bloquent explicitement la méthode CONNECT pour certains ports ou exigent une authentification. Si vous travaillez avec des fournisseurs de proxy commerciaux, la plupart d'entre eux prennent en charge CONNECT sans restrictions.
# Exemple de requête CONNECT via curl (pour vérification)
curl -v -x http://proxy_host:proxy_port \
--proxytunnel \
https://echo.websocket.org
# Si le proxy prend en charge CONNECT — vous verrez :
# * CONNECT tunnel established, response 200
SOCKS5 et WebSocket : pourquoi c'est la meilleure option
SOCKS5 est un protocole de proxy au niveau des connexions TCP/UDP. Contrairement aux proxies HTTP, SOCKS5 ne sait rien du protocole applicatif qui circule à l'intérieur. Il crée simplement un tunnel entre le client et le serveur cible, et c'est tout. Cela le rend idéal pour WebSocket pour plusieurs raisons :
- Pas de restrictions de protocole : SOCKS5 tunnelise tout le trafic TCP, y compris WS, WSS, SSH, FTP, etc.
- Pas de restrictions de port : fonctionne avec n'importe quel port, pas seulement 443 ou 80
- Pas d'interruption lors du changement de protocole : le proxy ne « voit » pas le passage de HTTP à WebSocket
- Support de l'authentification : SOCKS5 prend en charge le login/mot de passe, ce qui est pratique pour les proxies commerciaux
- Support de l'UDP : si votre application utilise WebRTC ou UDP avec WS — SOCKS5 s'en sortira
Pratiquement toutes les bibliothèques modernes pour travailler avec WebSocket prennent en charge SOCKS5 soit directement, soit via des paquets supplémentaires. Nous allons examiner ci-dessous des exemples concrets pour Python et Node.js.
💡 Quand choisir SOCKS5, et quand HTTP CONNECT ?
Utilisez SOCKS5 si : port non standard, besoin de support UDP, vous voulez un minimum de configurations.
Utilisez HTTP CONNECT si : le fournisseur de proxy ne prend pas en charge SOCKS5, ou si vous travaillez via un proxy d'entreprise.
Exemples de code : WebSocket via proxy en Python
Examinons quelques scénarios pour Python. Les bibliothèques les plus populaires pour WebSocket en Python sont websockets et websocket-client.
Option 1 : websocket-client via proxy HTTP
import websocket
# Paramètres du proxy HTTP
proxy_host = "proxy.example.com"
proxy_port = 8080
proxy_user = "username"
proxy_pass = "password"
ws = websocket.WebSocket()
ws.connect(
"wss://echo.websocket.org",
http_proxy_host=proxy_host,
http_proxy_port=proxy_port,
http_proxy_auth=(proxy_user, proxy_pass),
proxy_type="http" # ou "socks5"
)
ws.send("Hello, WebSocket!")
result = ws.recv()
print(f"Reçu : {result}")
ws.close()
Option 2 : websocket-client via SOCKS5
import websocket
# Pour SOCKS5, vous avez besoin du paquet : pip install PySocks
ws = websocket.WebSocket()
ws.connect(
"wss://echo.websocket.org",
http_proxy_host="socks5_proxy.example.com",
http_proxy_port=1080,
http_proxy_auth=("username", "password"),
proxy_type="socks5"
)
ws.send("Message de test")
print(ws.recv())
ws.close()
Option 3 : bibliothèque websockets (asyncio) via SOCKS5
La bibliothèque websockets (asyncio) n'a pas de support intégré pour le proxy, donc nous utilisons python-socks pour créer un tunnel :
# pip install websockets python-socks[asyncio]
import asyncio
import websockets
from python_socks.async_.asyncio import Proxy
async def connect_via_socks5():
proxy = Proxy.from_url("socks5://username:[email protected]:1080")
# Créer une connexion TCP via le proxy
sock = await proxy.connect(
dest_host="echo.websocket.org",
dest_port=443
)
# Passer le socket à websockets
async with websockets.connect(
"wss://echo.websocket.org",
sock=sock
) as ws:
await ws.send("Hello via SOCKS5!")
response = await ws.recv()
print(f"Réponse : {response}")
asyncio.run(connect_via_socks5())
Option 4 : patch global via PySocks
Si vous souhaitez diriger tout le trafic de l'application Python via SOCKS5 sans modifier chaque appel — utilisez socks.setdefaultproxy() :
# pip install PySocks
import socks
import socket
import websocket
# Patch globalement le socket
socks.set_default_proxy(
socks.SOCKS5,
"proxy.example.com",
1080,
username="user",
password="pass"
)
socket.socket = socks.socksocket
# Maintenant toutes les connexions passent par SOCKS5
ws = websocket.WebSocket()
ws.connect("wss://echo.websocket.org")
ws.send("Proxy SOCKS5 global!")
print(ws.recv())
ws.close()
Exemples de code : WebSocket via proxy en Node.js
Dans l'écosystème Node.js, la bibliothèque la plus populaire pour WebSocket est ws. Pour le proxy via HTTP/SOCKS5, on utilise le paquet https-proxy-agent ou socks-proxy-agent.
Option 1 : WSS via proxy HTTP CONNECT
// npm install ws https-proxy-agent
const WebSocket = require('ws');
const { HttpsProxyAgent } = require('https-proxy-agent');
const proxyUrl = 'http://username:[email protected]:8080';
const agent = new HttpsProxyAgent(proxyUrl);
const ws = new WebSocket('wss://echo.websocket.org', { agent });
ws.on('open', () => {
console.log('Connexion établie via le proxy HTTP');
ws.send('Hello from Node.js!');
});
ws.on('message', (data) => {
console.log(`Reçu : ${data}`);
ws.close();
});
ws.on('error', (err) => {
console.error('Erreur :', err.message);
});
Option 2 : WSS via SOCKS5
// npm install ws socks-proxy-agent
const WebSocket = require('ws');
const { SocksProxyAgent } = require('socks-proxy-agent');
const proxyUrl = 'socks5://username:[email protected]:1080';
const agent = new SocksProxyAgent(proxyUrl);
const ws = new WebSocket('wss://echo.websocket.org', { agent });
ws.on('open', () => {
console.log('Connexion établie via SOCKS5');
ws.send(JSON.stringify({ type: 'ping', data: 'test' }));
});
ws.on('message', (data) => {
console.log('Réponse :', data.toString());
});
ws.on('close', (code, reason) => {
console.log(`Fermé : ${code} - ${reason}`);
});
Option 3 : WS (sans TLS) via proxy HTTP manuellement
Pour WS non chiffré (port 80) via un proxy HTTP, il faut envoyer manuellement la requête CONNECT, car les agents standard fonctionnent souvent uniquement avec HTTPS :
const net = require('net');
const WebSocket = require('ws');
function createTunnel(proxyHost, proxyPort, targetHost, targetPort) {
return new Promise((resolve, reject) => {
const socket = net.connect(proxyPort, proxyHost, () => {
const connectReq =
`CONNECT ${targetHost}:${targetPort} HTTP/1.1\r\n` +
`Host: ${targetHost}:${targetPort}\r\n` +
`Proxy-Authorization: Basic ${Buffer.from('user:pass').toString('base64')}\r\n` +
`\r\n`;
socket.write(connectReq);
});
socket.once('data', (data) => {
if (data.toString().includes('200')) {
resolve(socket);
} else {
reject(new Error(`Le proxy a rejeté CONNECT : ${data.toString()}`));
}
});
socket.on('error', reject);
});
}
async function main() {
const socket = await createTunnel(
'proxy.example.com', 8080,
'echo.websocket.org', 80
);
const ws = new WebSocket('ws://echo.websocket.org', { socket });
ws.on('open', () => {
ws.send('Tunnel CONNECT manuel !');
});
ws.on('message', (data) => {
console.log('Reçu :', data.toString());
ws.close();
});
}
main().catch(console.error);
WSS (WebSocket Secure) : caractéristiques du proxy avec TLS
WSS est WebSocket sur TLS (similaire à HTTPS pour HTTP). Lors du proxy de WSS via SOCKS5 ou HTTP CONNECT, il y a un point important : le chiffrement TLS est établi entre le client et le serveur final, et non entre le client et le proxy. Cela signifie :
- Le serveur proxy ne voit pas le contenu du trafic WSS — uniquement l'adresse IP et le port de destination
- Le certificat du serveur est vérifié directement par le client
- Le proxy ne peut pas « remplacer » ou « intercepter » les données sans installer son propre certificat CA
C'est une bonne nouvelle du point de vue de la sécurité. Mais il y a aussi des nuances pratiques lors de la configuration :
Vérification du certificat via le proxy
Parfois, lors de l'utilisation de proxies d'entreprise (qui effectuent une inspection SSL), vous pouvez obtenir une erreur de vérification du certificat. Dans ce cas, le proxy remplace le certificat du serveur par le sien. Pour fonctionner dans un tel environnement, il faut ajouter le certificat CA du proxy aux certificats de confiance :
# Python : passer le certificat CA du proxy d'entreprise
import ssl
import websocket
ssl_context = ssl.create_default_context()
ssl_context.load_verify_locations("/path/to/corporate-ca.crt")
ws = websocket.WebSocket(sslopt={"context": ssl_context})
ws.connect(
"wss://internal.example.com",
http_proxy_host="corp-proxy.company.com",
http_proxy_port=8080,
proxy_type="http"
)
# Dans les environnements de test (PAS pour la production !) vous pouvez désactiver la vérification :
ws_test = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
ws_test.connect("wss://test.example.com", http_proxy_host="proxy", http_proxy_port=8080)
⚠️ Important
Désactiver la vérification du certificat TLS (CERT_NONE) est acceptable uniquement dans un environnement de test. En production, cela crée une vulnérabilité aux attaques de type MITM (man-in-the-middle).
SNI (Server Name Indication) via proxy
Lors de l'utilisation de SOCKS5, le client peut résoudre lui-même le DNS ou déléguer cela au proxy. Le mode socks5h (SOCKS5 avec résolution de nom d'hôte) signifie que la requête DNS est effectuée du côté du serveur proxy. Cela est important pour WSS, car l'en-tête SNI dans le handshake TLS doit correspondre au nom d'hôte :
# socks5 — DNS résolu localement (par le client)
# socks5h — DNS résolu par le serveur proxy (recommandé pour l'anonymat)
from python_socks.async_.asyncio import Proxy
# DNS via proxy (recommandé) :
proxy = Proxy.from_url("socks5h://user:[email protected]:1080")
# DNS localement :
proxy = Proxy.from_url("socks5://user:[email protected]:1080")
Erreurs courantes et comment les corriger
Nous avons rassemblé les problèmes les plus fréquents lors du proxy de WebSocket avec des solutions :
Erreur 1 : 407 Proxy Authentication Required
Le proxy nécessite une authentification, mais vous n'avez pas transmis les identifiants ou vous les avez transmis incorrectement.
# ❌ Incorrect — pas d'autorisation
ws.connect("wss://example.com", http_proxy_host="proxy.example.com", http_proxy_port=8080)
# ✅ Correct — nous transmettons le login et le mot de passe
ws.connect(
"wss://example.com",
http_proxy_host="proxy.example.com",
http_proxy_port=8080,
http_proxy_auth=("username", "password")
)
Erreur 2 : Connection reset by peer / 502 Bad Gateway
Le proxy ne prend pas en charge WebSocket ou la méthode CONNECT. Solution : passez à SOCKS5 ou vérifiez si votre fournisseur prend en charge le trafic WebSocket.
Erreur 3 : La connexion se coupe après 30-60 secondes
De nombreux serveurs proxy ferment les connexions TCP « inactives » après un certain temps. Une connexion WebSocket peut sembler inactive s'il n'y a pas d'échange de données. La solution consiste à activer le ping/pong :
# Python — activer le ping keepalive toutes les 20 secondes
import websocket
import threading
def run():
ws = websocket.WebSocketApp(
"wss://echo.websocket.org",
on_message=lambda ws, msg: print(msg),
on_error=lambda ws, err: print(f"Erreur : {err}"),
on_close=lambda ws, c, m: print("Fermé")
)
ws.run_forever(
ping_interval=20, # envoyer ping toutes les 20 sec
ping_timeout=10, # attendre pong pas plus de 10 sec
http_proxy_host="proxy.example.com",
http_proxy_port=8080,
proxy_type="socks5"
)
thread = threading.Thread(target=run)
thread.start()
Erreur 4 : SSL: CERTIFICATE_VERIFY_FAILED
Cela se produit le plus souvent lors de l'utilisation d'un proxy d'entreprise avec inspection SSL. Solution : ajoutez le certificat CA du proxy aux certificats de confiance (voir section ci-dessus) ou utilisez SOCKS5 au lieu d'un proxy HTTP — SOCKS5 ne fait pas d'inspection SSL.
Erreur 5 : Handshake status 403 Forbidden
Le serveur cible bloque la connexion. Raisons : l'IP du proxy est sur liste noire, les en-têtes requis (Origin, User-Agent) sont absents, ou le serveur bloque le trafic provenant de centres de données. Solution : utilisez des proxies résidentiels avec de vraies IP d'utilisateurs domestiques — ils sont beaucoup plus difficiles à bloquer.
Erreur 6 : [Errno 111] Connection refused
Le serveur proxy est inaccessible : hôte/port incorrect, ou le proxy n'est pas en cours d'exécution. Vérifiez les données de connexion et la disponibilité du proxy via une simple requête HTTP avant de tester WebSocket.
Quel type de proxy choisir pour les tâches WebSocket
Le choix du type de proxy dépend de la tâche spécifique. Voici un guide pratique :
| Tâche | Type recommandé | Pourquoi |
|---|---|---|
| Parsing via WS (bourses, données financières) | Proxies de centre de données | Haute vitesse, faible latence, connexion stable |
| Contourner les blocages des services WebSocket | Proxies résidentiels | Vraies IP, risque minimal de blocage |
| Applications mobiles avec WS (travail avec des API mobiles) | Proxies mobiles | IP des opérateurs mobiles — haute confiance de la part des services |
| Tests de charge du serveur WS | Proxies de centre de données | Pas cher, rapide, beaucoup de connexions simultanées |
| Tests de géolocalisation WS | Proxies résidentiels | Large choix de pays et de villes |
Paramètres importants des proxies pour WebSocket
Lors du choix d'un fournisseur de proxy pour les tâches WebSocket, faites attention aux paramètres suivants :
- Support SOCKS5 : assurez-vous que le fournisseur propose SOCKS5, et pas seulement HTTP
- Durée de session : pour WebSocket, les sessions « sticky » sont importantes — une IP pendant longtemps. Les proxies rotatifs interrompront la connexion
- Délai d'attente de connexion : le proxy doit prendre en charge des connexions TCP à long terme (de quelques minutes à des heures)
- Débit : pour le WebSocket en streaming (vidéo, données boursières), un débit élevé sans restrictions est important
- Latence : pour les applications financières et les bots de trading, une latence minimale est cruciale — choisissez un proxy avec des serveurs plus proches du service cible
💡 Vérification de la prise en charge de WebSocket par le fournisseur de proxy
Avant d'acheter un proxy pour les tâches WebSocket, testez-les via un serveur écho gratuit :
wss://echo.websocket.org ou
wss://ws.postman-echo.com/raw.
Si la connexion est établie et que les messages sont renvoyés — le proxy fonctionne correctement avec WebSocket.
Configuration de la session sticky pour WebSocket
La plupart des fournisseurs de proxies résidentiels utilisent la rotation des IP par défaut. Pour WebSocket, cela est inacceptable — chaque changement d'IP signifie une rupture de connexion. Assurez-vous d'utiliser le mode sticky session (IP fixe). Cela se fait généralement via un format d'URL spécial pour le proxy :
# Exemple de format de session sticky (dépend du fournisseur) :
# Rotatif (NE convient pas pour WebSocket) :
socks5://user:[email protected]:1080
# Session sticky (convient pour WebSocket) :
socks5://user-session-abc123:[email protected]:1080
# Ou via le paramètre de pays et de session :
socks5://user-country-us-session-12345:[email protected]:1080
Conclusion
WebSocket n'est pas simplement « HTTP avec une connexion longue ». C'est un protocole distinct qui nécessite une approche particulière lors du proxy. Les principales conclusions de cet article :
- SOCKS5 — le choix optimal pour WebSocket : fonctionne au niveau de transport, ne déchiffre pas le protocole, prend en charge tous les ports
- Proxy HTTP via CONNECT fonctionne également, mais avec des restrictions de port et des problèmes potentiels d'inspection SSL
- Les sessions sticky sont obligatoires : les proxies rotatifs interrompront la connexion WebSocket à chaque changement d'IP
- Ping/pong keepalive est nécessaire pour éviter la rupture de connexion par timeout du proxy
- WSS via proxy est sécurisé : le chiffrement TLS est établi directement entre le client et le serveur, le proxy ne voit pas le contenu
Si vous développez une application qui fonctionne avec WebSocket via un proxy — commencez par SOCKS5 et les sessions sticky. Cela vous fera économiser des heures de débogage. Pour les tâches où la vitesse et la stabilité de la connexion sont importantes (bots de trading, streaming de données), les proxies de centre de données avec faible latence conviennent parfaitement. Si le service cible bloque activement les IP des centres de données — envisagez des proxies résidentiels : ils disposent de vraies IP d'utilisateurs domestiques et sont beaucoup moins susceptibles d'être bloqués même lors de longues sessions WebSocket.
```