From 5912e2892a97a0a3ca31232493476f7dc2dbdd5d Mon Sep 17 00:00:00 2001 From: theodorsm Date: Sun, 15 Dec 2024 23:02:49 +0100 Subject: [PATCH] Add CovertWebRTC API --- client/lib/rendezvous.go | 27 +++++++++++++++++++++++--- client/lib/snowflake.go | 8 +++++++- client/lib/webrtc.go | 41 +++++++++++++++++++++++++++++++++++++--- proxy/lib/snowflake.go | 1 - 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go index d40e93e..e7245e2 100644 --- a/client/lib/rendezvous.go +++ b/client/lib/rendezvous.go @@ -185,17 +185,35 @@ type WebRTCDialer struct { // Deprecated: Use NewWebRTCDialerWithEventsAndProxy instead func NewWebRTCDialer(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int) *WebRTCDialer { - return NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, nil, nil, false, false) + return NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, nil, nil) } // Deprecated: Use NewWebRTCDialerWithEventsAndProxy instead func NewWebRTCDialerWithEvents(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int, eventLogger event.SnowflakeEventReceiver) *WebRTCDialer { - return NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventLogger, nil, false, false) + return NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventLogger, nil) } // NewWebRTCDialerWithEventsAndProxy constructs a new WebRTCDialer. func NewWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int, eventLogger event.SnowflakeEventReceiver, proxy *url.URL, +) *WebRTCDialer { + config := webrtc.Configuration{ + ICEServers: iceServers, + } + + return &WebRTCDialer{ + BrokerChannel: broker, + webrtcConfig: &config, + max: max, + + eventLogger: eventLogger, + proxy: proxy, + } +} + +// NewWebRTCDialerWithEventsAndProxy constructs a new WebRTCDialer setting DTLS mimicking and randomization. +func NewCovertWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int, + eventLogger event.SnowflakeEventReceiver, proxy *url.URL, dtlsRandomize bool, dtlsMimic bool, ) *WebRTCDialer { config := webrtc.Configuration{ @@ -218,7 +236,10 @@ func NewWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrt func (w WebRTCDialer) Catch() (*WebRTCPeer, error) { // TODO: [#25591] Fetch ICE server information from Broker. // TODO: [#25596] Consider TURN servers here too. - return NewWebRTCPeerWithEventsAndProxy(w.webrtcConfig, w.BrokerChannel, w.eventLogger, w.proxy, w.dtlsRandomize, w.dtlsMimic) + if w.dtlsRandomize || w.dtlsMimic { + return NewCovertWebRTCPeerWithEventsAndProxy(w.webrtcConfig, w.BrokerChannel, w.eventLogger, w.proxy, w.dtlsRandomize, w.dtlsMimic) + } + return NewWebRTCPeerWithEventsAndProxy(w.webrtcConfig, w.BrokerChannel, w.eventLogger, w.proxy) } // GetMax returns the maximum number of snowflakes to collect. diff --git a/client/lib/snowflake.go b/client/lib/snowflake.go index 8982e22..0ab09e4 100644 --- a/client/lib/snowflake.go +++ b/client/lib/snowflake.go @@ -162,8 +162,14 @@ func NewSnowflakeClient(config ClientConfig) (*Transport, error) { if config.Max > max { max = config.Max } + eventsLogger := event.NewSnowflakeEventDispatcher() - transport := &Transport{dialer: NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventsLogger, config.CommunicationProxy, config.DTLSRandomize, config.DTLSMimic), eventDispatcher: eventsLogger} + var transport *Transport + if config.DTLSRandomize || config.DTLSMimic { + transport = &Transport{dialer: NewCovertWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventsLogger, config.CommunicationProxy, config.DTLSRandomize, config.DTLSMimic), eventDispatcher: eventsLogger} + } else { + transport = &Transport{dialer: NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventsLogger, config.CommunicationProxy), eventDispatcher: eventsLogger} + } return transport, nil } diff --git a/client/lib/webrtc.go b/client/lib/webrtc.go index fbe4fbf..5754b59 100644 --- a/client/lib/webrtc.go +++ b/client/lib/webrtc.go @@ -11,7 +11,6 @@ import ( "sync" "time" - "github.com/pion/dtls/v3" "github.com/pion/ice/v4" "github.com/pion/transport/v3" "github.com/pion/transport/v3/stdnet" @@ -53,7 +52,7 @@ type WebRTCPeer struct { func NewWebRTCPeer( config *webrtc.Configuration, broker *BrokerChannel, ) (*WebRTCPeer, error) { - return NewWebRTCPeerWithEventsAndProxy(config, broker, nil, nil, false, false) + return NewWebRTCPeerWithEventsAndProxy(config, broker, nil, nil) } // Deprecated: Use NewWebRTCPeerWithEventsAndProxy Instead. @@ -61,7 +60,7 @@ func NewWebRTCPeerWithEvents( config *webrtc.Configuration, broker *BrokerChannel, eventsLogger event.SnowflakeEventReceiver, ) (*WebRTCPeer, error) { - return NewWebRTCPeerWithEventsAndProxy(config, broker, eventsLogger, nil, false, false) + return NewWebRTCPeerWithEventsAndProxy(config, broker, eventsLogger, nil) } // NewWebRTCPeerWithEventsAndProxy constructs a WebRTC PeerConnection to a snowflake proxy. @@ -72,6 +71,42 @@ func NewWebRTCPeerWithEvents( func NewWebRTCPeerWithEventsAndProxy( config *webrtc.Configuration, broker *BrokerChannel, eventsLogger event.SnowflakeEventReceiver, proxy *url.URL, +) (*WebRTCPeer, error) { + if eventsLogger == nil { + eventsLogger = event.NewSnowflakeEventDispatcher() + } + + connection := new(WebRTCPeer) + { + var buf [8]byte + if _, err := rand.Read(buf[:]); err != nil { + panic(err) + } + connection.id = "snowflake-" + hex.EncodeToString(buf[:]) + } + connection.closed = make(chan struct{}) + + // Override with something that's not NullLogger to have real logging. + connection.bytesLogger = &bytesNullLogger{} + + // Pipes remain the same even when DataChannel gets switched. + connection.recvPipe, connection.writePipe = io.Pipe() + + connection.eventsLogger = eventsLogger + connection.proxy = proxy + + err := connection.connect(config, broker, false, false) + if err != nil { + connection.Close() + return nil, err + } + return connection, nil +} + +// NewCovertWebRTCPeerWithEventsAndProxy constructs a WebRTC PeerConnection to a snowflake proxy using DTLS mimicking or randomization. +func NewCovertWebRTCPeerWithEventsAndProxy( + config *webrtc.Configuration, broker *BrokerChannel, + eventsLogger event.SnowflakeEventReceiver, proxy *url.URL, dtlsRandomize bool, dtlsMimic bool, ) (*WebRTCPeer, error) { if eventsLogger == nil { diff --git a/proxy/lib/snowflake.go b/proxy/lib/snowflake.go index 396acb5..b91fa83 100644 --- a/proxy/lib/snowflake.go +++ b/proxy/lib/snowflake.go @@ -42,7 +42,6 @@ import ( "github.com/pion/ice/v4" "github.com/gorilla/websocket" - "github.com/pion/dtls/v3" "github.com/pion/transport/v3/stdnet" "github.com/pion/webrtc/v4" "github.com/theodorsm/covert-dtls/pkg/mimicry"