홈으로 돌아가기

WebRTC TURN을 통한 SOCKS5: Go 구현

SOCKS5 트래픽을 WB Stream WebRTC 화상 회의로 위장하는 도구. Reverse API, 최소 protobuf parser, yamux과 함께 TURN-relay를 통한 KCP. 순수 Go 완전 자동화.

화상 회의에서의 SOCKS5 터널: 전체 분석
Advertisement 728x90

WebRTC TURN을 통한 SOCKS5 터널링: Go로 구현하기

WB Stream 플랫폼에서 WebRTC TURN 세션 내에 SOCKS5 트래픽을 숨기는 도구가 개발되었습니다. 트래픽은 LiveKit SFU를 사용해 화상 회의로 위장합니다. 전체 사이클: 역방향 HTTP API, protobuf 파싱, TURN 릴레이를 통한 KCP, yamux 멀티플렉싱. 브라우저 없이 단일 실행 명령으로 작동합니다.

stream.wb.ru API 역공학

puppeteer를 통한 트래픽 수집으로 네 번의 HTTP 요청과 WebSocket 연결 순서가 밝혀졌습니다. 메인 페이지는 브라우저 없이 요청을 차단하지만(코드 498), API 엔드포인트는 접근 가능합니다.

순서:

Google AdInline article slot
  • POST /auth/api/v1/auth/user/guest-register — displayName이 포함된 게스트 JWT 토큰.
  • POST /api-room/api/v2/roomroomType: ROOM_TYPE_ALL_ON_SCREEN, roomPrivacy: ROOM_PRIVACY_FREE로 방 생성.
  • POST /api-room/api/v1/room/{id}/join — 참가 (GET은 501 반환).
  • GET /api-room-manager/api/v1/room/{id}/token — LiveKit 토큰 (Accept-Encoding에서 gzip 고려).

WebSocket: wss://wbstream01-el.wb.ru:7880/rtc?access_token=...&sdk=js&version=2.15.3&protocol=16. ICE 서버: turn:wb-stream-turn-1.wb.ru:3478.

쿠키/CSRF 없이 net/http로 구현.

rr, _ := wb(cl, "POST", "/auth/api/v1/auth/user/guest-register",
    []byte(`{"displayName":"lh_42"}`), "")

LiveKit SignalResponse를 위한 Protobuf 파서

LiveKit는 ICE 서버를 SignalResponse > JoinResponse > ICEServer(필드 1>5/9)로 전송합니다. 전체 google.golang.org/protobuf는 과도하므로 최소 40줄 파서를 작성했습니다.

Google AdInline article slot

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
}

길이 구분 필드 추출:

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
}

파서는 필드 5(WB 포크)와 9(표준)에서 ICE 서버를 검색해 urls, username, credential을 추출합니다.

Google AdInline article slot

터널 아키텍처: KCP + TURN + yamux

SOCKS5의 TCP → yamux 스트림 → KCP(AES-256) → TURN 릴레이 → VPS → 인터넷.

주요 구성 요소:

  • TURN 할당 via pion/turn: tc.Allocate()net.PacketConn 반환.
  • 릴레이를 통한 KCP: kcp.NewConn(peerVPS, blk, 10, 3, relay).
  • 스트림 멀티플렉싱을 위한 Yamux.
  • VPS의 SOCKS5 서버.
uc, _ := net.ListenUDP("udp", nil)
tc, _ := turn.NewClient(&turn.ClientConfig{...})
relay, _ := tc.Allocate()
kc, _ := kcp.NewConn(peerVPS, blk, 10, 3, relay)

서버: KCP 리스너 + yamux 서버 + SOCKS5.

자동화 및 내결함성

  • 스마트 키: base64(IP|SHA256(password)).
  • 재연결: yamux ping/15s, 백오프 2-60s, TURN 자격 증명 캐시 5분.
  • 자체 정리: pgrep + 이전 인스턴스 종료, systemd 덮어쓰기.
  • 우아한 종료: Ctrl+C → 2초 정리.

실행 및 제한 사항

go build -o lionheart .
# 서버
./lionheart  # 키 복사
# 클라이언트
./lionheart  # 키 붙여넣기 → 127.0.0.1:1080

제한 사항: WB Stream API 의존성, 하드코딩된 wbstream01-el.wb.ru. 계획: Android/iOS용 gomobile(VpnService/NEPacketTunnelProvider).

핵심 포인트

  • DPI/방화벽을 위한 WebRTC 트래픽 위장, 기가비트 속도 지원.
  • 의존성 없는 최소 protobuf 파서.
  • KCP를 위한 net.PacketConn으로서의 TURN 릴레이.
  • 브라우저/API 키 없이 완전 자동화.
  • 순수 Go, gomobile 준비 완료.

— Editorial Team

Advertisement 728x90

다음 읽기