Commit 41c70f63 authored by David Fifield's avatar David Fifield
Browse files

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
	}
parent db243b91
......@@ -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)
})
......
......@@ -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 {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment