[tor-commits] [snowflake/main] Change the representation of domain fronting in HTTP rendezvous.

dcf at torproject.org dcf at torproject.org
Thu Aug 5 22:18:28 UTC 2021


commit 55f4814dfb5c196bb66416d4f3ba367498602489
Author: David Fifield <david at bamsoftware.com>
Date:   Sun Jul 18 10:39:51 2021 -0600

    Change the representation of domain fronting in HTTP rendezvous.
    
    Formerly, BrokerChannel represented the broker URL and possible domain
    fronting as
            bc.url  *url.URL
            bc.Host string
    That is, bc.url is the URL of the server which we contact directly, and
    bc.Host is the Host header to use in the request. With no domain
    fronting, bc.url points directly at the broker itself, and bc.Host is
    blank. With domain fronting, we do the following reshuffling:
            if front != "" {
                    bc.Host = bc.url.Host
                    bc.url.Host = front
            }
    That is, we alter bc.url to reflect that the server to which we send
    requests directly is the CDN, not the broker, and store the broker's own
    URL in the HTTP Host header.
    
    The above representation was always confusing to me, because in my
    mental model, we are always conceptually communicating with the broker;
    but we may optionally be using a CDN proxy in the middle. The new
    representation is
            bc.url   *url.URL
            bc.front string
    bc.url is the URL of the broker itself, and never changes. bc.front is
    the optional CDN front domain, and likewise never changes after
    initialization. When domain fronting is in use, we do the swap in the
    http.Request struct, not in BrokerChannel itself:
            if bc.front != "" {
                    request.Host = request.URL.Host
                    request.URL.Host = bc.front
            }
    
    Compare to the representation in meek-client:
    
    https://gitweb.torproject.org/pluggable-transports/meek.git/tree/meek-client/meek-client.go?h=v0.35.0#n94
            var options struct {
                    URL       string
                    Front     string
            }
    https://gitweb.torproject.org/pluggable-transports/meek.git/tree/meek-client/meek-client.go?h=v0.35.0#n308
            if ok { // if front is set
                    info.Host = info.URL.Host
                    info.URL.Host = front
            }
---
 client/lib/lib_test.go   | 12 ++++++------
 client/lib/rendezvous.go | 23 +++++++++++------------
 2 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/client/lib/lib_test.go b/client/lib/lib_test.go
index 03c53dd..9087eed 100644
--- a/client/lib/lib_test.go
+++ b/client/lib/lib_test.go
@@ -172,14 +172,14 @@ func TestSnowflakeClient(t *testing.T) {
 
 	Convey("Dialers", t, func() {
 		Convey("Can construct WebRTCDialer.", func() {
-			broker := &BrokerChannel{Host: "test"}
+			broker := &BrokerChannel{front: "test"}
 			d := NewWebRTCDialer(broker, nil, 1)
 			So(d, ShouldNotBeNil)
 			So(d.BrokerChannel, ShouldNotBeNil)
-			So(d.BrokerChannel.Host, ShouldEqual, "test")
+			So(d.BrokerChannel.front, ShouldEqual, "test")
 		})
 		SkipConvey("WebRTCDialer can Catch a snowflake.", func() {
-			broker := &BrokerChannel{Host: "test"}
+			broker := &BrokerChannel{}
 			d := NewWebRTCDialer(broker, nil, 1)
 			conn, err := d.Catch()
 			So(conn, ShouldBeNil)
@@ -201,8 +201,8 @@ func TestSnowflakeClient(t *testing.T) {
 			b, err := NewBrokerChannel("http://test.broker", "", transport, false)
 			So(b.url, ShouldNotBeNil)
 			So(err, ShouldBeNil)
-			So(b.Host, ShouldResemble, "")
 			So(b.url.Host, ShouldResemble, "test.broker")
+			So(b.front, ShouldResemble, "")
 			So(b.transport, ShouldNotBeNil)
 		})
 
@@ -210,8 +210,8 @@ func TestSnowflakeClient(t *testing.T) {
 			b, err := NewBrokerChannel("http://test.broker", "front", transport, false)
 			So(b.url, ShouldNotBeNil)
 			So(err, ShouldBeNil)
-			So(b.Host, ShouldResemble, "test.broker")
-			So(b.url.Host, ShouldResemble, "front")
+			So(b.url.Host, ShouldResemble, "test.broker")
+			So(b.front, ShouldResemble, "front")
 			So(b.transport, ShouldNotBeNil)
 		})
 
diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go
index b89f432..caa4ae4 100644
--- a/client/lib/rendezvous.go
+++ b/client/lib/rendezvous.go
@@ -32,10 +32,8 @@ const (
 
 // Signalling Channel to the Broker.
 type BrokerChannel struct {
-	// The Host header to put in the HTTP request (optional and may be
-	// different from the host name in URL).
-	Host               string
 	url                *url.URL
+	front              string            // Optional front domain to replace url.Host in requests.
 	transport          http.RoundTripper // Used to make all requests.
 	keepLocalAddresses bool
 	NATType            string
@@ -61,14 +59,12 @@ func NewBrokerChannel(broker string, front string, transport http.RoundTripper,
 		return nil, err
 	}
 	log.Println("Rendezvous using Broker at:", broker)
-	bc := new(BrokerChannel)
-	bc.url = targetURL
-	if front != "" { // Optional front domain.
+	if front != "" {
 		log.Println("Domain fronting using:", front)
-		bc.Host = bc.url.Host
-		bc.url.Host = front
 	}
-
+	bc := new(BrokerChannel)
+	bc.url = targetURL
+	bc.front = front
 	bc.transport = transport
 	bc.keepLocalAddresses = keepLocalAddresses
 	bc.NATType = nat.NATUnknown
@@ -92,7 +88,7 @@ func limitedRead(r io.Reader, limit int64) ([]byte, error) {
 func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) (
 	*webrtc.SessionDescription, error) {
 	log.Println("Negotiating via BrokerChannel...\nTarget URL: ",
-		bc.Host, "\nFront URL:  ", bc.url.Host)
+		bc.url.Host, "\nFront URL:  ", bc.front)
 	// Ideally, we could specify an `RTCIceTransportPolicy` that would handle
 	// this for us.  However, "public" was removed from the draft spec.
 	// See https://developer.mozilla.org/en-US/docs/Web/API/RTCConfiguration#RTCIceTransportPolicy_enum
@@ -126,8 +122,11 @@ func (bc *BrokerChannel) Negotiate(offer *webrtc.SessionDescription) (
 	if nil != err {
 		return nil, err
 	}
-	if "" != bc.Host { // Set true host if necessary.
-		request.Host = bc.Host
+	if bc.front != "" {
+		// Do domain fronting. Replace the domain in the URL's with the
+		// front, and store the original domain the HTTP Host header.
+		request.Host = request.URL.Host
+		request.URL.Host = bc.front
 	}
 	resp, err := bc.transport.RoundTrip(request)
 	if nil != err {





More information about the tor-commits mailing list