commit c13810192d243690dab4c0e890a1f50273a22ca1 Author: David Fifield david@bamsoftware.com Date: Sun Jul 18 14:18:32 2021 -0600
Skeleton of ampCacheRendezvous.
Currently the same as httpRendezvous, but activated using the -ampcache command-line option. --- client/lib/rendezvous.go | 13 ++++++- client/lib/rendezvous_ampcache.go | 78 +++++++++++++++++++++++++++++++++++++++ client/lib/snowflake.go | 7 ++-- client/snowflake.go | 3 +- 4 files changed, 95 insertions(+), 6 deletions(-)
diff --git a/client/lib/rendezvous.go b/client/lib/rendezvous.go index 8568120..8af638f 100644 --- a/client/lib/rendezvous.go +++ b/client/lib/rendezvous.go @@ -59,13 +59,22 @@ func CreateBrokerTransport() http.RoundTripper { // Construct a new BrokerChannel, where: // |broker| is the full URL of the facilitating program which assigns proxies // to clients, and |front| is the option fronting domain. -func NewBrokerChannel(broker string, front string, transport http.RoundTripper, keepLocalAddresses bool) (*BrokerChannel, error) { +func NewBrokerChannel(broker, ampCache, front string, transport http.RoundTripper, keepLocalAddresses bool) (*BrokerChannel, error) { log.Println("Rendezvous using Broker at:", broker) + if ampCache != "" { + log.Println("Through AMP cache at:", ampCache) + } if front != "" { log.Println("Domain fronting using:", front) }
- rendezvous, err := newHTTPRendezvous(broker, front, transport) + var rendezvous rendezvousMethod + var err error + if ampCache != "" { + rendezvous, err = newAMPCacheRendezvous(broker, ampCache, front, transport) + } else { + rendezvous, err = newHTTPRendezvous(broker, front, transport) + } if err != nil { return nil, err } diff --git a/client/lib/rendezvous_ampcache.go b/client/lib/rendezvous_ampcache.go new file mode 100644 index 0000000..89745f4 --- /dev/null +++ b/client/lib/rendezvous_ampcache.go @@ -0,0 +1,78 @@ +package lib + +import ( + "bytes" + "errors" + "log" + "net/http" + "net/url" +) + +// ampCacheRendezvous is a rendezvousMethod that communicates with the +// .../amp/client route of the broker, optionally over an AMP cache proxy, and +// with optional domain fronting. +type ampCacheRendezvous struct { + brokerURL *url.URL + cacheURL *url.URL // Optional AMP cache URL. + front string // Optional front domain to replace url.Host in requests. + transport http.RoundTripper // Used to make all requests. +} + +// newAMPCacheRendezvous creates a new ampCacheRendezvous that contacts the +// broker at the given URL, optionally proxying through an AMP cache, and with +// an optional front domain. transport is the http.RoundTripper used to make all +// requests. +func newAMPCacheRendezvous(broker, cache, front string, transport http.RoundTripper) (*ampCacheRendezvous, error) { + brokerURL, err := url.Parse(broker) + if err != nil { + return nil, err + } + var cacheURL *url.URL + if cache != "" { + var err error + cacheURL, err = url.Parse(cache) + if err != nil { + return nil, err + } + } + return &CacheRendezvous{ + brokerURL: brokerURL, + cacheURL: cacheURL, + front: front, + transport: transport, + }, nil +} + +func (r *ampCacheRendezvous) Exchange(encPollReq []byte) ([]byte, error) { + log.Println("Negotiating via AMP cache rendezvous...") + log.Println("Broker URL:", r.brokerURL) + log.Println("AMP cache URL:", r.cacheURL) + log.Println("Front domain:", r.front) + + // Suffix the path with the broker's client registration handler. + reqURL := r.brokerURL.ResolveReference(&url.URL{Path: "client"}) + req, err := http.NewRequest("POST", reqURL.String(), bytes.NewReader(encPollReq)) + if err != nil { + return nil, err + } + + if r.front != "" { + // Do domain fronting. Replace the domain in the URL's with the + // front, and store the original domain the HTTP Host header. + req.Host = req.URL.Host + req.URL.Host = r.front + } + + resp, err := r.transport.RoundTrip(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + log.Printf("AMP cache rendezvous response: %s", resp.Status) + if resp.StatusCode != http.StatusOK { + return nil, errors.New(BrokerErrorUnexpected) + } + + return limitedRead(resp.Body, readLimit) +} diff --git a/client/lib/snowflake.go b/client/lib/snowflake.go index f643c0a..0fc7671 100644 --- a/client/lib/snowflake.go +++ b/client/lib/snowflake.go @@ -39,7 +39,8 @@ type Transport struct { // iceAddresses are the STUN/TURN urls needed for WebRTC negotiation // keepLocalAddresses is a flag to enable sending local network addresses (for testing purposes) // max is the maximum number of snowflakes the client should gather for each SOCKS connection -func NewSnowflakeClient(brokerURL, frontDomain string, iceAddresses []string, keepLocalAddresses bool, max int) (*Transport, error) { +func NewSnowflakeClient(brokerURL, ampCacheURL, frontDomain string, + iceAddresses []string, keepLocalAddresses bool, max int) (*Transport, error) {
log.Println("\n\n\n --- Starting Snowflake Client ---")
@@ -57,9 +58,9 @@ func NewSnowflakeClient(brokerURL, frontDomain string, iceAddresses []string, ke log.Printf("url: %v", strings.Join(server.URLs, " ")) }
- // Use potentially domain-fronting broker to rendezvous. + // Rendezvous with broker using the given parameters. broker, err := NewBrokerChannel( - brokerURL, frontDomain, CreateBrokerTransport(), + brokerURL, ampCacheURL, frontDomain, CreateBrokerTransport(), keepLocalAddresses) if err != nil { return nil, err diff --git a/client/snowflake.go b/client/snowflake.go index af9c2e4..ef06a2d 100644 --- a/client/snowflake.go +++ b/client/snowflake.go @@ -94,6 +94,7 @@ func main() { iceServersCommas := flag.String("ice", "", "comma-separated list of ICE servers") brokerURL := flag.String("url", "", "URL of signaling broker") frontDomain := flag.String("front", "", "front domain") + ampCacheURL := flag.String("ampcache", "", "URL of AMP cache to use as a proxy for signaling") logFilename := flag.String("log", "", "name of log file") logToStateDir := flag.Bool("log-to-state-dir", false, "resolve the log file relative to tor's pt state dir") keepLocalAddresses := flag.Bool("keep-local-addresses", false, "keep local LAN address ICE candidates") @@ -140,7 +141,7 @@ func main() {
iceAddresses := strings.Split(strings.TrimSpace(*iceServersCommas), ",")
- transport, err := sf.NewSnowflakeClient(*brokerURL, *frontDomain, iceAddresses, + transport, err := sf.NewSnowflakeClient(*brokerURL, *ampCacheURL, *frontDomain, iceAddresses, *keepLocalAddresses || *oldKeepLocalAddresses, *max) if err != nil { log.Fatal("Failed to start snowflake transport: ", err)
tor-commits@lists.torproject.org