diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go index bf1a48c..bb344ec 100644 --- a/client/lib/rendezvous.go +++ b/client/lib/rendezvous.go @@ -13,6 +13,8 @@ import ( "sync" "time" + "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/turbotunnel" + "github.com/pion/webrtc/v4" utls "github.com/refraction-networking/utls" @@ -249,8 +251,9 @@ type WebRTCDialer struct { webrtcConfig *webrtc.Configuration max int - eventLogger event.SnowflakeEventReceiver - proxy *url.URL + eventLogger event.SnowflakeEventReceiver + proxy *url.URL + connectionID turbotunnel.ClientID } // Deprecated: Use NewWebRTCDialerWithNatPolicyAndEventsAndProxy instead @@ -281,7 +284,6 @@ func NewWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrt ) } -// NewWebRTCDialerWithNatPolicyAndEventsAndProxy constructs a new WebRTCDialer. func NewWebRTCDialerWithNatPolicyAndEventsAndProxy( broker *BrokerChannel, natPolicy *NATPolicy, @@ -289,6 +291,27 @@ func NewWebRTCDialerWithNatPolicyAndEventsAndProxy( max int, eventLogger event.SnowflakeEventReceiver, proxy *url.URL, +) *WebRTCDialer { + return NewWebRTCDialerWithNatPolicyAndEventsAndProxyAndClientID( + broker, + natPolicy, + iceServers, + max, + eventLogger, + proxy, + turbotunnel.NewClientID(), + ) +} + +// NewWebRTCDialerWithNatPolicyAndEventsAndProxy constructs a new WebRTCDialer. +func NewWebRTCDialerWithNatPolicyAndEventsAndProxyAndClientID( + broker *BrokerChannel, + natPolicy *NATPolicy, + iceServers []webrtc.ICEServer, + max int, + eventLogger event.SnowflakeEventReceiver, + proxy *url.URL, + clientID turbotunnel.ClientID, ) *WebRTCDialer { config := webrtc.Configuration{ ICEServers: iceServers, @@ -300,8 +323,9 @@ func NewWebRTCDialerWithNatPolicyAndEventsAndProxy( webrtcConfig: &config, max: max, - eventLogger: eventLogger, - proxy: proxy, + eventLogger: eventLogger, + proxy: proxy, + connectionID: clientID, } } @@ -309,9 +333,7 @@ func NewWebRTCDialerWithNatPolicyAndEventsAndProxy( func (w WebRTCDialer) Catch() (*WebRTCPeer, error) { // TODO: [#25591] Fetch ICE server information from Broker. // TODO: [#25596] Consider TURN servers here too. - return NewWebRTCPeerWithNatPolicyAndEventsAndProxy( - w.webrtcConfig, w.BrokerChannel, w.natPolicy, w.eventLogger, w.proxy, - ) + 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 77c784e..af00bc9 100644 --- a/client/lib/snowflake.go +++ b/client/lib/snowflake.go @@ -78,6 +78,8 @@ type Transport struct { // EventDispatcher is the event bus for snowflake events. // When an important event happens, it will be distributed here. eventDispatcher event.SnowflakeEventDispatcher + + clientID turbotunnel.ClientID } // ClientConfig defines how the SnowflakeClient will connect to the broker and Snowflake proxies. @@ -164,7 +166,11 @@ func NewSnowflakeClient(config ClientConfig) (*Transport, error) { max = config.Max } eventsLogger := event.NewSnowflakeEventDispatcher() - transport := &Transport{dialer: NewWebRTCDialerWithNatPolicyAndEventsAndProxy(broker, natPolicy, iceServers, max, eventsLogger, config.CommunicationProxy), eventDispatcher: eventsLogger} + clientID := turbotunnel.NewClientID() + transport := &Transport{ + dialer: NewWebRTCDialerWithNatPolicyAndEventsAndProxy(broker, natPolicy, iceServers, max, eventsLogger, config.CommunicationProxy), + eventDispatcher: eventsLogger, clientID: clientID, + } return transport, nil } @@ -198,7 +204,7 @@ func (t *Transport) Dial() (net.Conn, error) { // Create a new smux session log.Printf("---- SnowflakeConn: starting a new session ---") - pconn, sess, err := newSession(snowflakes) + pconn, sess, err := newSession(snowflakes, t.clientID) if err != nil { return nil, err } @@ -324,8 +330,11 @@ func parseIceServers(addresses []string) []webrtc.ICEServer { // newSession returns a new smux.Session and the net.PacketConn it is running // over. The net.PacketConn successively connects through Snowflake proxies // pulled from snowflakes. -func newSession(snowflakes SnowflakeCollector) (net.PacketConn, *smux.Session, error) { +func newSession(snowflakes SnowflakeCollector, clientIDCandid turbotunnel.ClientID) (net.PacketConn, *smux.Session, error) { clientID := turbotunnel.NewClientID() + if clientIDCandid != (turbotunnel.ClientID{}) { + clientID = clientIDCandid + } // We build a persistent KCP session on a sequence of ephemeral WebRTC // connections. This dialContext tells RedialPacketConn how to get a new @@ -342,9 +351,8 @@ func newSession(snowflakes SnowflakeCollector) (net.PacketConn, *smux.Session, e log.Println("---- Handler: snowflake assigned ----") log.Printf("activeTransportMode = %c \n", conn.activeTransportMode) if conn.activeTransportMode == 'u' { - packetIDConn := newPacketClientIDConn(clientID, conn) packetConnWrapper := &packetConnWrapper{ - ReadWriter: packetIDConn, + ReadWriter: conn, remoteAddr: dummyAddr{}, localAddr: dummyAddr{}, } diff --git a/client/lib/webrtc.go b/client/lib/webrtc.go index 85b18c9..a78c264 100644 --- a/client/lib/webrtc.go +++ b/client/lib/webrtc.go @@ -19,6 +19,7 @@ import ( "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event" "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/proxy" + "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/turbotunnel" "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/util" ) @@ -46,6 +47,7 @@ type WebRTCPeer struct { proxy *url.URL activeTransportMode byte + connectionID turbotunnel.ClientID } // Deprecated: Use NewWebRTCPeerWithNatPolicyAndEventsAndProxy Instead. @@ -77,15 +79,30 @@ func NewWebRTCPeerWithEventsAndProxy( ) } +func NewWebRTCPeerWithNatPolicyAndEventsAndProxy( + config *webrtc.Configuration, + broker *BrokerChannel, natPolicy *NATPolicy, eventsLogger event.SnowflakeEventReceiver, proxy *url.URL, +) (*WebRTCPeer, error) { + return NewWebRTCPeerWithNatPolicyAndEventsProxyAndClientID( + config, + broker, + natPolicy, + eventsLogger, + proxy, + turbotunnel.ClientID{}, + ) +} + // NewWebRTCPeerWithNatPolicyAndEventsAndProxy constructs // a WebRTC PeerConnection to a snowflake proxy. // // The creation of the peer handles the signaling to the Snowflake broker, including // the exchange of SDP information, the creation of a PeerConnection, and the establishment // of a DataChannel to the Snowflake proxy. -func NewWebRTCPeerWithNatPolicyAndEventsAndProxy( - config *webrtc.Configuration, broker *BrokerChannel, natPolicy *NATPolicy, - eventsLogger event.SnowflakeEventReceiver, proxy *url.URL, +// connectionID is the hinted ID for the connection. +func NewWebRTCPeerWithNatPolicyAndEventsProxyAndClientID(config *webrtc.Configuration, + broker *BrokerChannel, natPolicy *NATPolicy, eventsLogger event.SnowflakeEventReceiver, proxy *url.URL, + clientID turbotunnel.ClientID, ) (*WebRTCPeer, error) { if eventsLogger == nil { eventsLogger = event.NewSnowflakeEventDispatcher() @@ -109,6 +126,7 @@ func NewWebRTCPeerWithNatPolicyAndEventsAndProxy( connection.eventsLogger = eventsLogger connection.proxy = proxy + connection.connectionID = clientID err := connection.connect(config, broker, natPolicy) if err != nil { @@ -307,7 +325,7 @@ func (c *WebRTCPeer) preparePeerConnection( maxRetransmissionVal := uint16(0) maxRetransmission = &maxRetransmissionVal } - protocol := fmt.Sprintf("%c", c.activeTransportMode) + protocol := fmt.Sprintf("%c %s", c.activeTransportMode, c.connectionID.String()) dataChannelOptions := &webrtc.DataChannelInit{ Ordered: &ordered, Protocol: &protocol,