aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCecylia Bocovich <cohosh@torproject.org>2020-08-11 13:22:16 -0400
committerCecylia Bocovich <cohosh@torproject.org>2020-08-27 16:43:55 -0400
commit1364d7d45bbec9de605a266a84ea60cdfa6676db (patch)
tree5f44d90f0963f98fda2927261dab92ee2d9fa386
parentd5ae7562ac65f07d1c2e4137534217644f391612 (diff)
downloadsnowflake-1364d7d45bbec9de605a266a84ea60cdfa6676db.tar.gz
snowflake-1364d7d45bbec9de605a266a84ea60cdfa6676db.zip
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.
-rw-r--r--client/lib/lib_test.go6
-rw-r--r--client/lib/snowflake.go34
-rw-r--r--client/snowflake.go38
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.")
}