commit 1364d7d45bbec9de605a266a84ea60cdfa6676db Author: Cecylia Bocovich cohosh@torproject.org Date: Tue Aug 11 13:22:16 2020 -0400
Move snowflake ConnectLoop inside SOCKS Handler
Bug #21314: maintains a separate snowflake connect loop per SOCKS connection. This way, if Tor decides to stop using Snowflake, Snowflake will stop using the client's network. --- client/lib/lib_test.go | 6 +++--- client/lib/snowflake.go | 34 +++++++++++++++++++++++++++++++++- client/snowflake.go | 38 +++++--------------------------------- 3 files changed, 41 insertions(+), 37 deletions(-)
diff --git a/client/lib/lib_test.go b/client/lib/lib_test.go index ebcf284..a93943f 100644 --- a/client/lib/lib_test.go +++ b/client/lib/lib_test.go @@ -157,11 +157,11 @@ func TestSnowflakeClient(t *testing.T) {
SkipConvey("Handler Grants correctly", func() { socks := &FakeSocksConn{} - snowflakes := &FakePeers{} + broker := &BrokerChannel{Host: "test"} + d := NewWebRTCDialer(broker, nil)
So(socks.rejected, ShouldEqual, false) - snowflakes.toRelease = nil - Handler(socks, snowflakes) + Handler(socks, d) So(socks.rejected, ShouldEqual, true) }) }) diff --git a/client/lib/snowflake.go b/client/lib/snowflake.go index b355c3e..d08a7bc 100644 --- a/client/lib/snowflake.go +++ b/client/lib/snowflake.go @@ -142,7 +142,17 @@ var sessionManager = sessionManager_{}
// Given an accepted SOCKS connection, establish a WebRTC connection to the // remote peer and exchange traffic. -func Handler(socks net.Conn, snowflakes SnowflakeCollector) error { +func Handler(socks net.Conn, tongue Tongue) error { + // Prepare to collect remote WebRTC peers. + snowflakes := NewPeers(1) + snowflakes.Tongue = tongue + + // Use a real logger to periodically output how much traffic is happening. + snowflakes.BytesLogger = NewBytesSyncLogger() + + log.Printf("---- Handler: begin collecting snowflakes ---") + go connectLoop(snowflakes) + // Return the global smux.Session. sess, err := sessionManager.Get(snowflakes) if err != nil { @@ -160,9 +170,31 @@ func Handler(socks net.Conn, snowflakes SnowflakeCollector) error { log.Printf("---- Handler: begin stream %v ---", stream.ID()) copyLoop(socks, stream) log.Printf("---- Handler: closed stream %v ---", stream.ID()) + snowflakes.End() + log.Printf("---- Handler: end collecting snowflakes ---") return nil }
+// Maintain |SnowflakeCapacity| number of available WebRTC connections, to +// transfer to the Tor SOCKS handler when needed. +func connectLoop(snowflakes SnowflakeCollector) { + for { + // Check if ending is necessary. + _, err := snowflakes.Collect() + if err != nil { + log.Printf("WebRTC: %v Retrying in %v...", + err, ReconnectTimeout) + } + select { + case <-time.After(ReconnectTimeout): + continue + case <-snowflakes.Melted(): + log.Println("ConnectLoop: stopped.") + return + } + } +} + // Exchanges bytes between two ReadWriters. // (In this case, between a SOCKS connection and smux stream.) func copyLoop(socks, stream io.ReadWriter) { diff --git a/client/snowflake.go b/client/snowflake.go index 55bc48e..a7f5208 100644 --- a/client/snowflake.go +++ b/client/snowflake.go @@ -26,28 +26,8 @@ const ( DefaultSnowflakeCapacity = 1 )
-// Maintain |SnowflakeCapacity| number of available WebRTC connections, to -// transfer to the Tor SOCKS handler when needed. -func ConnectLoop(snowflakes sf.SnowflakeCollector) { - for { - // Check if ending is necessary. - _, err := snowflakes.Collect() - if err != nil { - log.Printf("WebRTC: %v Retrying in %v...", - err, sf.ReconnectTimeout) - } - select { - case <-time.After(sf.ReconnectTimeout): - continue - case <-snowflakes.Melted(): - log.Println("ConnectLoop: stopped.") - return - } - } -} - // Accept local SOCKS connections and pass them to the handler. -func socksAcceptLoop(ln *pt.SocksListener, snowflakes sf.SnowflakeCollector) { +func socksAcceptLoop(ln *pt.SocksListener, tongue sf.Tongue) { defer ln.Close() for { conn, err := ln.AcceptSocks() @@ -68,7 +48,7 @@ func socksAcceptLoop(ln *pt.SocksListener, snowflakes sf.SnowflakeCollector) { return }
- err = sf.Handler(conn, snowflakes) + err = sf.Handler(conn, tongue) if err != nil { log.Printf("handler error: %s", err) return @@ -158,9 +138,6 @@ func main() { log.Printf("url: %v", strings.Join(server.URLs, " ")) }
- // Prepare to collect remote WebRTC peers. - snowflakes := sf.NewPeers(*max) - // Use potentially domain-fronting broker to rendezvous. broker, err := sf.NewBrokerChannel( *brokerURL, *frontDomain, sf.CreateBrokerTransport(), @@ -170,12 +147,8 @@ func main() { } go updateNATType(iceServers, broker)
- snowflakes.Tongue = sf.NewWebRTCDialer(broker, iceServers) - - // Use a real logger to periodically output how much traffic is happening. - snowflakes.BytesLogger = sf.NewBytesSyncLogger() - - go ConnectLoop(snowflakes) + // Create a new WebRTCDialer to use as the |Tongue| to catch snowflakes + dialer := sf.NewWebRTCDialer(broker, iceServers)
// Begin goptlib client process. ptInfo, err := pt.ClientSetup(nil) @@ -197,7 +170,7 @@ func main() { break } log.Printf("Started SOCKS listener at %v.", ln.Addr()) - go socksAcceptLoop(ln, snowflakes) + go socksAcceptLoop(ln, dialer) pt.Cmethod(methodName, ln.Version(), ln.Addr()) listeners = append(listeners, ln) default: @@ -228,7 +201,6 @@ func main() { for _, ln := range listeners { ln.Close() } - snowflakes.End() log.Println("snowflake is done.") }
tor-commits@lists.torproject.org