Túnel SOCKS5 a través de WebRTC TURN Wildberries: Implementación en Go
Se ha desarrollado una herramienta para ocultar el tráfico SOCKS5 dentro de sesiones WebRTC TURN en la plataforma WB Stream. El tráfico se disfraza como una videoconferencia utilizando LiveKit SFU. Ciclo completo: API HTTP inversa, análisis de protobuf, KCP sobre relé TURN, multiplexación yamux. Funciona sin navegador, con un solo comando de lanzamiento.
Ingeniería inversa de la API de stream.wb.ru
La recopilación de tráfico mediante puppeteer reveló una secuencia de cuatro solicitudes HTTP y una conexión WebSocket. La página principal bloquea solicitudes sin navegador (código 498), pero los endpoints de la API son accesibles.
Secuencia:
- POST /auth/api/v1/auth/user/guest-register — Token JWT de invitado con displayName.
- POST /api-room/api/v2/room — Crear una sala con
roomType: ROOM_TYPE_ALL_ON_SCREEN,roomPrivacy: ROOM_PRIVACY_FREE. - POST /api-room/api/v1/room/{id}/join — Unirse (GET devuelve 501).
- GET /api-room-manager/api/v1/room/{id}/token — Token de LiveKit (tener en cuenta gzip en Accept-Encoding).
WebSocket: wss://wbstream01-el.wb.ru:7880/rtc?access_token=...&sdk=js&version=2.15.3&protocol=16. Servidores ICE: turn:wb-stream-turn-1.wb.ru:3478.
Implementado con net/http sin cookies/CSRF.
rr, _ := wb(cl, "POST", "/auth/api/v1/auth/user/guest-register",
[]byte(`{"displayName":"lh_42"}`), "")
Analizador Protobuf para LiveKit SignalResponse
LiveKit transmite servidores ICE en SignalResponse > JoinResponse > ICEServer (campos 1>5/9). google.golang.org/protobuf completo es excesivo — se escribió un analizador mínimo de 40 líneas.
Decodificación Varint:
func pbVar(d []byte, o int) (uint64, int) {
var v uint64
for s := 0; o < len(d) && s < 64; s += 7 {
b := d[o]; o++
v |= uint64(b&0x7f) << s
if b < 0x80 { return v, o }
}
return 0, o
}
Extracción de campos de longitud delimitada:
func pbAll(d []byte, f uint64) (r [][]byte) {
for o := 0; o < len(d); {
t, n := pbVar(d, o)
if n == o { break }
o = n
switch t & 7 {
case 2:
l, n := pbVar(d, o); o = n
e := o + int(l)
if e > len(d) || e < o { return }
if t>>3 == f { r = append(r, d[o:e]) }
o = e
// ...
}
}
return
}
El analizador busca servidores ICE en el campo 5 (fork de WB) y 9 (estándar), extrayendo urls, nombre de usuario, credencial.
Arquitectura del túnel: KCP + TURN + yamux
TCP desde SOCKS5 → flujo yamux → KCP (AES-256) → relé TURN → VPS → internet.
Componentes clave:
- Asignación TURN mediante
pion/turn:tc.Allocate()devuelvenet.PacketConn. - KCP sobre relé:
kcp.NewConn(peerVPS, blk, 10, 3, relay). - Yamux para multiplexación de flujos.
- Servidor SOCKS5 en VPS.
uc, _ := net.ListenUDP("udp", nil)
tc, _ := turn.NewClient(&turn.ClientConfig{...})
relay, _ := tc.Allocate()
kc, _ := kcp.NewConn(peerVPS, blk, 10, 3, relay)
Servidor: Oyente KCP + servidor yamux + SOCKS5.
Automatización y tolerancia a fallos
- Clave inteligente: base64(
IP|SHA256(contraseña)). - Reconexión: ping yamux/15s, retroceso 2-60s, caché de credenciales TURN 5min.
- Autolimpieza:
pgrep+ matar instancias anteriores, sobrescritura systemd. - Apagado elegante: Ctrl+C → limpieza de 2s.
Lanzamiento y limitaciones
go build -o lionheart .
# Servidor
./lionheart # copiar clave
# Cliente
./lionheart # pegar clave → 127.0.0.1:1080
Limitaciones: dependencia de la API de WB Stream, wbstream01-el.wb.ru codificado. Planes: gomobile para Android/iOS (VpnService/NEPacketTunnelProvider).
Puntos clave
- Enmascaramiento como tráfico WebRTC para DPI/cortafuegos a velocidades de gigabit.
- Analizador protobuf mínimo sin dependencias.
- Relé TURN como
net.PacketConnpara KCP. - Automatización completa sin navegador/claves API.
- Puro Go, listo para gomobile.
— Editorial Team
Aún no hay comentarios.