1/*
2 * Copyright (c) 2015, Psiphon Inc.
3 * All rights reserved.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package psiphon
21
22import (
23	"bytes"
24	"context"
25	"crypto/rand"
26	"crypto/tls"
27	"encoding/base64"
28	"encoding/json"
29	"fmt"
30	"io"
31	"io/ioutil"
32	"net"
33	"net/http"
34	"net/url"
35	"strings"
36	"sync"
37	"sync/atomic"
38	"time"
39
40	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/net/http2"
41	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
42	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
43	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
44	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
45	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
46	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
47	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic"
48	"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/upstreamproxy"
49	"github.com/ooni/psiphon/oopsi/golang.org/x/crypto/nacl/box"
50)
51
52// MeekConn is based on meek-client.go from Tor:
53//
54// https://gitweb.torproject.org/pluggable-transports/meek.git/blob/HEAD:/meek-client/meek-client.go
55// CC0 1.0 Universal
56
57const (
58	MEEK_PROTOCOL_VERSION           = 3
59	MEEK_MAX_REQUEST_PAYLOAD_LENGTH = 65536
60)
61
62type MeekMode int
63
64const (
65	MeekModeRelay = iota
66	MeekModeObfuscatedRoundTrip
67	MeekModePlaintextRoundTrip
68)
69
70// MeekConfig specifies the behavior of a MeekConn.
71type MeekConfig struct {
72
73	// DiagnosticID is the server ID to record in any diagnostics notices.
74	DiagnosticID string
75
76	// Parameters is the active set of parameters.Parameters to use
77	// for the meek dial.
78	Parameters *parameters.Parameters
79
80	// Mode selects the mode of operation:
81	//
82	// MeekModeRelay: encapsulates net.Conn flows in HTTP requests and responses;
83	// secures and obfuscates metadata in an encrypted HTTP cookie, making it
84	// suitable for non-TLS HTTP and HTTPS with unverifed server certificates;
85	// the caller is responsible for securing and obfuscating the net.Conn flows;
86	// the origin server should be a meek server; used for the meek tunnel
87	// protocols.
88	//
89	// MeekModeObfuscatedRoundTrip: enables ObfuscatedRoundTrip, which performs
90	// HTTP round trips; secures and obfuscates metadata, including the end point
91	// (or path), in an encrypted HTTP cookie, making it suitable for non-TLS
92	// HTTP and HTTPS with unverifed server certificates; the caller is
93	// responsible for securing and obfuscating request/response payloads; the
94	// origin server should be a meek server; used for tactics requests.
95	//
96	// MeekModePlaintextRoundTrip: enables RoundTrip; the MeekConn is an
97	// http.RoundTripper; there are no security or obfuscation measures at the
98	// HTTP level; TLS and server certificate verification is required; the
99	// origin server may be any HTTP(S) server.
100	//
101	// As with the other modes, MeekModePlaintextRoundTrip supports HTTP/2 with
102	// utls, and integration with DialParameters for replay -- which are not
103	// otherwise implemented if using just CustomTLSDialer and net.http.
104	Mode MeekMode
105
106	// DialAddress is the actual network address to dial to establish a
107	// connection to the meek server. This may be either a fronted or
108	// direct address. The address must be in the form "host:port",
109	// where host may be a domain name or IP address.
110	DialAddress string
111
112	// UseQUIC indicates whether to use HTTP/2 over QUIC.
113	UseQUIC bool
114
115	// QUICVersion indicates which QUIC version to use.
116	QUICVersion string
117
118	// UseHTTPS indicates whether to use HTTPS (true) or HTTP (false).
119	UseHTTPS bool
120
121	// TLSProfile specifies the value for CustomTLSConfig.TLSProfile for all
122	// underlying TLS connections created by this meek connection.
123	TLSProfile string
124
125	// NoDefaultTLSSessionID specifies the value for
126	// CustomTLSConfig.NoDefaultTLSSessionID for all underlying TLS connections
127	// created by this meek connection.
128	NoDefaultTLSSessionID bool
129
130	// RandomizedTLSProfileSeed specifies the value for
131	// CustomTLSConfig.RandomizedTLSProfileSeed for all underlying TLS
132	// connections created by this meek connection.
133	RandomizedTLSProfileSeed *prng.Seed
134
135	// UseObfuscatedSessionTickets indicates whether to use obfuscated session
136	// tickets. Assumes UseHTTPS is true. Ignored for MeekModePlaintextRoundTrip.
137	//
138	UseObfuscatedSessionTickets bool
139
140	// SNIServerName is the value to place in the TLS/QUIC SNI server_name field
141	// when HTTPS or QUIC is used.
142	SNIServerName string
143
144	// HostHeader is the value to place in the HTTP request Host header.
145	HostHeader string
146
147	// TransformedHostName records whether a hostname transformation is
148	// in effect. This value is used for stats reporting.
149	TransformedHostName bool
150
151	// VerifyServerName specifies a domain name that must appear in the server
152	// certificate. When blank, server certificate verification is disabled.
153	VerifyServerName string
154
155	// VerifyPins specifies one or more certificate pin values, one of which must
156	// appear in the verified server certificate chain. A pin value is the
157	// base64-encoded SHA2 digest of a certificate's public key. When specified,
158	// at least one pin must match at least one certificate in the chain, at any
159	// position; e.g., the root CA may be pinned, or the server certificate,
160	// etc.
161	VerifyPins []string
162
163	// ClientTunnelProtocol is the protocol the client is using. It's included in
164	// the meek cookie for optional use by the server, in cases where the server
165	// cannot unambiguously determine the tunnel protocol. ClientTunnelProtocol
166	// is used when selecting tactics targeted at specific protocols. Ignored for
167	// MeekModePlaintextRoundTrip.
168	ClientTunnelProtocol string
169
170	// NetworkLatencyMultiplier specifies a custom network latency multiplier to
171	// apply to client parameters used by this meek connection.
172	NetworkLatencyMultiplier float64
173
174	// The following values are used to create the obfuscated meek cookie.
175	// Ignored for MeekModePlaintextRoundTrip.
176
177	MeekCookieEncryptionPublicKey string
178	MeekObfuscatedKey             string
179	MeekObfuscatorPaddingSeed     *prng.Seed
180}
181
182// MeekConn is a network connection that tunnels net.Conn flows over HTTP and supports
183// "domain fronting". Meek sends client->server flow in HTTP request bodies and
184// receives server->client flow in HTTP response bodies. Polling is used to
185// approximate full duplex TCP. MeekConn also offers HTTP round trip modes.
186//
187// Domain fronting is a network obfuscation technique in which the connection to a web
188// server, typically a CDN, is indistinguishable from any other HTTPS
189// connection to the generic "fronting domain" -- the HTTP Host header is used
190// to route the requests to the actual destination. See
191// https://trac.torproject.org/projects/tor/wiki/doc/meek for more details.
192//
193// MeekConn also support unfronted operation, in which connections are made
194// without routing through a CDN; and plain HTTP operation, without TLS or
195// QUIC, with connection metadata obfuscated in HTTP cookies.
196type MeekConn struct {
197	params                    *parameters.Parameters
198	mode                      MeekMode
199	networkLatencyMultiplier  float64
200	isQUIC                    bool
201	url                       *url.URL
202	additionalHeaders         http.Header
203	cookie                    *http.Cookie
204	cookieSize                int
205	tlsPadding                int
206	limitRequestPayloadLength int
207	redialTLSProbability      float64
208	cachedTLSDialer           *cachedTLSDialer
209	transport                 transporter
210	mutex                     sync.Mutex
211	isClosed                  bool
212	runCtx                    context.Context
213	stopRunning               context.CancelFunc
214	relayWaitGroup            *sync.WaitGroup
215
216	// For MeekModeObfuscatedRoundTrip
217	meekCookieEncryptionPublicKey string
218	meekObfuscatedKey             string
219	meekObfuscatorPaddingSeed     *prng.Seed
220	clientTunnelProtocol          string
221
222	// For MeekModeRelay
223	fullReceiveBufferLength int
224	readPayloadChunkLength  int
225	emptyReceiveBuffer      chan *bytes.Buffer
226	partialReceiveBuffer    chan *bytes.Buffer
227	fullReceiveBuffer       chan *bytes.Buffer
228	emptySendBuffer         chan *bytes.Buffer
229	partialSendBuffer       chan *bytes.Buffer
230	fullSendBuffer          chan *bytes.Buffer
231}
232
233func (conn *MeekConn) getCustomParameters() parameters.ParametersAccessor {
234	return conn.params.GetCustom(conn.networkLatencyMultiplier)
235}
236
237// transporter is implemented by both http.Transport and upstreamproxy.ProxyAuthTransport.
238type transporter interface {
239	CloseIdleConnections()
240	RoundTrip(req *http.Request) (resp *http.Response, err error)
241}
242
243// DialMeek returns an initialized meek connection. A meek connection is
244// an HTTP session which does not depend on an underlying socket connection (although
245// persistent HTTP connections are used for performance). This function may not
246// wait for the connection to be established before returning.
247func DialMeek(
248	ctx context.Context,
249	meekConfig *MeekConfig,
250	dialConfig *DialConfig) (*MeekConn, error) {
251
252	if meekConfig.UseQUIC && meekConfig.UseHTTPS {
253		return nil, errors.TraceNew(
254			"invalid config: only one of UseQUIC or UseHTTPS may be set")
255	}
256
257	if meekConfig.UseQUIC &&
258		(meekConfig.VerifyServerName != "" || len(meekConfig.VerifyPins) > 0) {
259
260		// TODO: UseQUIC VerifyServerName and VerifyPins support (required for MeekModePlaintextRoundTrip).
261
262		return nil, errors.TraceNew(
263			"invalid config: VerifyServerName and VerifyPins not supported for UseQUIC")
264	}
265
266	skipVerify := meekConfig.VerifyServerName == ""
267	if len(meekConfig.VerifyPins) > 0 && skipVerify {
268		return nil, errors.TraceNew(
269			"invalid config: VerifyServerName must be set when VerifyPins is set")
270	}
271
272	if meekConfig.Mode == MeekModePlaintextRoundTrip &&
273		(!meekConfig.UseHTTPS || skipVerify) {
274		return nil, errors.TraceNew(
275			"invalid config: MeekModePlaintextRoundTrip requires UseHTTPS and VerifyServerName")
276	}
277
278	runCtx, stopRunning := context.WithCancel(context.Background())
279
280	cleanupStopRunning := true
281	cleanupCachedTLSDialer := true
282	var cachedTLSDialer *cachedTLSDialer
283
284	// Cleanup in error cases
285	defer func() {
286		if cleanupStopRunning {
287			stopRunning()
288		}
289		if cleanupCachedTLSDialer && cachedTLSDialer != nil {
290			cachedTLSDialer.close()
291		}
292	}()
293
294	meek := &MeekConn{
295		params:                   meekConfig.Parameters,
296		mode:                     meekConfig.Mode,
297		networkLatencyMultiplier: meekConfig.NetworkLatencyMultiplier,
298		isClosed:                 false,
299		runCtx:                   runCtx,
300		stopRunning:              stopRunning,
301		relayWaitGroup:           new(sync.WaitGroup),
302	}
303
304	if meek.mode == MeekModeRelay {
305		var err error
306		meek.cookie,
307			meek.tlsPadding,
308			meek.limitRequestPayloadLength,
309			meek.redialTLSProbability,
310			err =
311			makeMeekObfuscationValues(
312				meek.getCustomParameters(),
313				meekConfig.MeekCookieEncryptionPublicKey,
314				meekConfig.MeekObfuscatedKey,
315				meekConfig.MeekObfuscatorPaddingSeed,
316				meekConfig.ClientTunnelProtocol,
317				"")
318		if err != nil {
319			return nil, errors.Trace(err)
320		}
321
322		// For stats, record the size of the initial obfuscated cookie.
323		meek.cookieSize = len(meek.cookie.Name) + len(meek.cookie.Value)
324	}
325
326	// Configure transport: QUIC or HTTPS or HTTP
327
328	var (
329		scheme            string
330		transport         transporter
331		additionalHeaders http.Header
332		proxyUrl          func(*http.Request) (*url.URL, error)
333	)
334
335	if meekConfig.UseQUIC {
336
337		meek.isQUIC = true
338
339		scheme = "https"
340
341		udpDialer := func(ctx context.Context) (net.PacketConn, *net.UDPAddr, error) {
342			packetConn, remoteAddr, err := NewUDPConn(
343				ctx,
344				meekConfig.DialAddress,
345				dialConfig)
346			if err != nil {
347				return nil, nil, errors.Trace(err)
348			}
349			return packetConn, remoteAddr, nil
350		}
351
352		_, port, _ := net.SplitHostPort(meekConfig.DialAddress)
353		quicDialSNIAddress := fmt.Sprintf("%s:%s", meekConfig.SNIServerName, port)
354
355		var err error
356		transport, err = quic.NewQUICTransporter(
357			ctx,
358			func(message string) {
359				NoticeInfo(message)
360			},
361			udpDialer,
362			quicDialSNIAddress,
363			meekConfig.QUICVersion)
364		if err != nil {
365			return nil, errors.Trace(err)
366		}
367
368	} else if meekConfig.UseHTTPS {
369
370		// Custom TLS dialer:
371		//
372		//  1. ignores the HTTP request address and uses the fronting domain
373		//  2. optionally disables SNI -- SNI breaks fronting when used with certain CDNs.
374		//  3. may skip verifying the server cert.
375		//
376		// Reasoning for #3:
377		//
378		// With a TLS MiM attack in place, and server certs verified, we'll fail to connect because the client
379		// will refuse to connect. That's not a successful outcome.
380		//
381		// With a MiM attack in place, and server certs not verified, we'll fail to connect if the MiM is actively
382		// targeting Psiphon and classifying the HTTP traffic by Host header or payload signature.
383		//
384		// However, in the case of a passive MiM that's just recording traffic or an active MiM that's targeting
385		// something other than Psiphon, the client will connect. This is a successful outcome.
386		//
387		// What is exposed to the MiM? The Host header does not contain a Psiphon server IP address, just an
388		// unrelated, randomly generated domain name which cannot be used to block direct connections. The
389		// Psiphon server IP is sent over meek, but it's in the encrypted cookie.
390		//
391		// The payload (user traffic) gets its confidentiality and integrity from the underlying SSH protocol.
392		// So, nothing is leaked to the MiM apart from signatures which could be used to classify the traffic
393		// as Psiphon to possibly block it; but note that not revealing that the client is Psiphon is outside
394		// our threat model; we merely seek to evade mass blocking by taking steps that require progressively
395		// more effort to block.
396		//
397		// There is a subtle attack remaining: an adversary that can MiM some CDNs but not others (and so can
398		// classify Psiphon traffic on some CDNs but not others) may throttle non-MiM CDNs so that our server
399		// selection always chooses tunnels to the MiM CDN (without any server cert verification, we won't
400		// exclusively connect to non-MiM CDNs); then the adversary kills the underlying TCP connection after
401		// some short period. This is partially mitigated by tactics mechanisms.
402
403		scheme = "https"
404
405		tlsConfig := &CustomTLSConfig{
406			Parameters:                    meekConfig.Parameters,
407			DialAddr:                      meekConfig.DialAddress,
408			Dial:                          NewTCPDialer(dialConfig),
409			SNIServerName:                 meekConfig.SNIServerName,
410			SkipVerify:                    skipVerify,
411			VerifyServerName:              meekConfig.VerifyServerName,
412			VerifyPins:                    meekConfig.VerifyPins,
413			TLSProfile:                    meekConfig.TLSProfile,
414			NoDefaultTLSSessionID:         &meekConfig.NoDefaultTLSSessionID,
415			RandomizedTLSProfileSeed:      meekConfig.RandomizedTLSProfileSeed,
416			TLSPadding:                    meek.tlsPadding,
417			TrustedCACertificatesFilename: dialConfig.TrustedCACertificatesFilename,
418		}
419		tlsConfig.EnableClientSessionCache()
420
421		if meekConfig.UseObfuscatedSessionTickets {
422			tlsConfig.ObfuscatedSessionTicketKey = meekConfig.MeekObfuscatedKey
423		}
424
425		if meekConfig.Mode != MeekModePlaintextRoundTrip &&
426			meekConfig.MeekObfuscatedKey != "" {
427
428			// As the passthrough message is unique and indistinguishable from a normal
429			// TLS client random value, we set it unconditionally and not just for
430			// protocols which may support passthrough (even for those protocols,
431			// clients don't know which servers are configured to use it).
432
433			passthroughMessage, err := obfuscator.MakeTLSPassthroughMessage(
434				meekConfig.MeekObfuscatedKey)
435			if err != nil {
436				return nil, errors.Trace(err)
437			}
438			tlsConfig.PassthroughMessage = passthroughMessage
439		}
440
441		tlsDialer := NewCustomTLSDialer(tlsConfig)
442
443		// Pre-dial one TLS connection in order to inspect the negotiated
444		// application protocol. Then we create an HTTP/2 or HTTP/1.1 transport
445		// depending on which protocol was negotiated. The TLS dialer
446		// is assumed to negotiate only "h2" or "http/1.1"; or not negotiate
447		// an application protocol.
448		//
449		// We cannot rely on net/http's HTTP/2 support since it's only
450		// activated when http.Transport.DialTLS returns a golang crypto/tls.Conn;
451		// e.g., https://github.com/ooni/psiphon/oopsi/github.com/golang/go/blob/c8aec4095e089ff6ac50d18e97c3f46561f14f48/src/net/http/transport.go#L1040
452		//
453		// The pre-dialed connection is stored in a cachedTLSDialer, which will
454		// return the cached pre-dialed connection to its first Dial caller, and
455		// use the tlsDialer for all other Dials.
456		//
457		// cachedTLSDialer.close() must be called on all exits paths from this
458		// function and in meek.Close() to ensure the cached conn is closed in
459		// any case where no Dial call is made.
460		//
461		// The pre-dial must be interruptible so that DialMeek doesn't block and
462		// hang/delay a shutdown or end of establishment. So the pre-dial uses
463		// the Controller's PendingConns, not the MeekConn PendingConns. For this
464		// purpose, a special preDialer is configured.
465		//
466		// Only one pre-dial attempt is made; there are no retries. This differs
467		// from relayRoundTrip, which retries and may redial for each retry.
468		// Retries at the pre-dial phase are less useful since there's no active
469		// session to preserve, and establishment will simply try another server.
470		// Note that the underlying TCPDial may still try multiple IP addreses when
471		// the destination is a domain and it resolves to multiple IP adresses.
472
473		// The pre-dial is made within the parent dial context, so that DialMeek
474		// may be interrupted. Subsequent dials are made within the meek round trip
475		// request context. Since http.DialTLS doesn't take a context argument
476		// (yet; as of Go 1.9 this issue is still open: https://github.com/ooni/psiphon/oopsi/github.com/golang/go/issues/21526),
477		// cachedTLSDialer is used as a conduit to send the request context.
478		// meekConn.relayRoundTrip sets its request context into cachedTLSDialer,
479		// and cachedTLSDialer.dial uses that context.
480
481		// As DialAddr is set in the CustomTLSConfig, no address is required here.
482		preConn, err := tlsDialer(ctx, "tcp", "")
483		if err != nil {
484			return nil, errors.Trace(err)
485		}
486
487		cachedTLSDialer = newCachedTLSDialer(preConn, tlsDialer)
488
489		if IsTLSConnUsingHTTP2(preConn) {
490			NoticeInfo("negotiated HTTP/2 for %s", meekConfig.DiagnosticID)
491			transport = &http2.Transport{
492				DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) {
493					return cachedTLSDialer.dial(network, addr)
494				},
495			}
496		} else {
497			transport = &http.Transport{
498				DialTLS: func(network, addr string) (net.Conn, error) {
499					return cachedTLSDialer.dial(network, addr)
500				},
501			}
502		}
503
504	} else {
505
506		scheme = "http"
507
508		var dialer common.Dialer
509
510		// For HTTP, and when the meekConfig.DialAddress matches the
511		// meekConfig.HostHeader, we let http.Transport handle proxying.
512		// http.Transport will put the the HTTP server address in the HTTP
513		// request line. In this one case, we can use an HTTP proxy that does
514		// not offer CONNECT support.
515		if strings.HasPrefix(dialConfig.UpstreamProxyURL, "http://") &&
516			(meekConfig.DialAddress == meekConfig.HostHeader ||
517				meekConfig.DialAddress == meekConfig.HostHeader+":80") {
518
519			url, err := common.SafeParseURL(dialConfig.UpstreamProxyURL)
520			if err != nil {
521				return nil, errors.Trace(err)
522			}
523			proxyUrl = http.ProxyURL(url)
524
525			// Here, the dialer must use the address that http.Transport
526			// passes in (which will be proxy address).
527			copyDialConfig := new(DialConfig)
528			*copyDialConfig = *dialConfig
529			copyDialConfig.UpstreamProxyURL = ""
530
531			dialer = NewTCPDialer(copyDialConfig)
532
533		} else {
534
535			baseDialer := NewTCPDialer(dialConfig)
536
537			// The dialer ignores any address that http.Transport will pass in
538			// (derived from the HTTP request URL) and always dials
539			// meekConfig.DialAddress.
540			dialer = func(ctx context.Context, network, _ string) (net.Conn, error) {
541				return baseDialer(ctx, network, meekConfig.DialAddress)
542			}
543		}
544
545		httpTransport := &http.Transport{
546			Proxy:       proxyUrl,
547			DialContext: dialer,
548		}
549
550		if proxyUrl != nil {
551			// Wrap transport with a transport that can perform HTTP proxy auth negotiation
552			var err error
553			transport, err = upstreamproxy.NewProxyAuthTransport(httpTransport, dialConfig.CustomHeaders)
554			if err != nil {
555				return nil, errors.Trace(err)
556			}
557		} else {
558			transport = httpTransport
559		}
560	}
561
562	url := &url.URL{
563		Scheme: scheme,
564		Host:   meekConfig.HostHeader,
565		Path:   "/",
566	}
567
568	if meekConfig.UseHTTPS {
569		host, _, err := net.SplitHostPort(meekConfig.DialAddress)
570		if err != nil {
571			return nil, errors.Trace(err)
572		}
573		additionalHeaders = map[string][]string{
574			"X-Psiphon-Fronting-Address": {host},
575		}
576	} else {
577		if proxyUrl == nil {
578			additionalHeaders = dialConfig.CustomHeaders
579		}
580	}
581
582	meek.url = url
583	meek.additionalHeaders = additionalHeaders
584	meek.cachedTLSDialer = cachedTLSDialer
585	meek.transport = transport
586
587	// stopRunning and cachedTLSDialer will now be closed in meek.Close()
588	cleanupStopRunning = false
589	cleanupCachedTLSDialer = false
590
591	// Allocate relay resources, including buffers and running the relay
592	// go routine, only when running in relay mode.
593	if meek.mode == MeekModeRelay {
594
595		// The main loop of a MeekConn is run in the relay() goroutine.
596		// A MeekConn implements net.Conn concurrency semantics:
597		// "Multiple goroutines may invoke methods on a Conn simultaneously."
598		//
599		// Read() calls and relay() are synchronized by exchanging control of a single
600		// receiveBuffer (bytes.Buffer). This single buffer may be:
601		// - in the emptyReceiveBuffer channel when it is available and empty;
602		// - in the partialReadBuffer channel when it is available and contains data;
603		// - in the fullReadBuffer channel when it is available and full of data;
604		// - "checked out" by relay or Read when they are are writing to or reading from the
605		//   buffer, respectively.
606		// relay() will obtain the buffer from either the empty or partial channel but block when
607		// the buffer is full. Read will obtain the buffer from the partial or full channel when
608		// there is data to read but block when the buffer is empty.
609		// Write() calls and relay() are synchronized in a similar way, using a single
610		// sendBuffer.
611
612		p := meek.getCustomParameters()
613		if p.Bool(parameters.MeekLimitBufferSizes) {
614			meek.fullReceiveBufferLength = p.Int(parameters.MeekLimitedFullReceiveBufferLength)
615			meek.readPayloadChunkLength = p.Int(parameters.MeekLimitedReadPayloadChunkLength)
616		} else {
617			meek.fullReceiveBufferLength = p.Int(parameters.MeekFullReceiveBufferLength)
618			meek.readPayloadChunkLength = p.Int(parameters.MeekReadPayloadChunkLength)
619		}
620
621		meek.emptyReceiveBuffer = make(chan *bytes.Buffer, 1)
622		meek.partialReceiveBuffer = make(chan *bytes.Buffer, 1)
623		meek.fullReceiveBuffer = make(chan *bytes.Buffer, 1)
624		meek.emptySendBuffer = make(chan *bytes.Buffer, 1)
625		meek.partialSendBuffer = make(chan *bytes.Buffer, 1)
626		meek.fullSendBuffer = make(chan *bytes.Buffer, 1)
627
628		meek.emptyReceiveBuffer <- new(bytes.Buffer)
629		meek.emptySendBuffer <- new(bytes.Buffer)
630
631		meek.relayWaitGroup.Add(1)
632		go meek.relay()
633
634	} else if meek.mode == MeekModeObfuscatedRoundTrip {
635
636		meek.meekCookieEncryptionPublicKey = meekConfig.MeekCookieEncryptionPublicKey
637		meek.meekObfuscatedKey = meekConfig.MeekObfuscatedKey
638		meek.meekObfuscatorPaddingSeed = meekConfig.MeekObfuscatorPaddingSeed
639		meek.clientTunnelProtocol = meekConfig.ClientTunnelProtocol
640	}
641
642	return meek, nil
643}
644
645type cachedTLSDialer struct {
646	usedCachedConn int32
647	cachedConn     net.Conn
648	dialer         common.Dialer
649
650	mutex      sync.Mutex
651	requestCtx context.Context
652}
653
654func newCachedTLSDialer(cachedConn net.Conn, dialer common.Dialer) *cachedTLSDialer {
655	return &cachedTLSDialer{
656		cachedConn: cachedConn,
657		dialer:     dialer,
658	}
659}
660
661func (c *cachedTLSDialer) setRequestContext(requestCtx context.Context) {
662	// Note: not using sync.Value since underlying type of requestCtx may change.
663	c.mutex.Lock()
664	defer c.mutex.Unlock()
665	c.requestCtx = requestCtx
666}
667
668func (c *cachedTLSDialer) dial(network, addr string) (net.Conn, error) {
669	if atomic.CompareAndSwapInt32(&c.usedCachedConn, 0, 1) {
670		conn := c.cachedConn
671		c.cachedConn = nil
672		return conn, nil
673	}
674
675	c.mutex.Lock()
676	ctx := c.requestCtx
677	c.mutex.Unlock()
678	if ctx == nil {
679		ctx = context.Background()
680	}
681
682	return c.dialer(ctx, network, addr)
683}
684
685func (c *cachedTLSDialer) close() {
686	if atomic.CompareAndSwapInt32(&c.usedCachedConn, 0, 1) {
687		c.cachedConn.Close()
688		c.cachedConn = nil
689	}
690}
691
692// Close terminates the meek connection and releases its resources. In in
693// MeekModeRelay, Close waits for the relay goroutine to stop.
694func (meek *MeekConn) Close() (err error) {
695
696	// A mutex is required to support net.Conn concurrency semantics.
697
698	meek.mutex.Lock()
699	isClosed := meek.isClosed
700	meek.isClosed = true
701	meek.mutex.Unlock()
702
703	if !isClosed {
704		meek.stopRunning()
705		if meek.cachedTLSDialer != nil {
706			meek.cachedTLSDialer.close()
707		}
708
709		// stopRunning interrupts HTTP requests in progress by closing the context
710		// associated with the request. In the case of h2quic.RoundTripper, testing
711		// indicates that quic-go.receiveStream.readImpl in _not_ interrupted in
712		// this case, and so an in-flight FRONTED-MEEK-QUIC round trip may hang shutdown
713		// in relayRoundTrip->readPayload->...->quic-go.receiveStream.readImpl.
714		//
715		// To workaround this, we call CloseIdleConnections _before_ Wait, as, in
716		// the case of QUICTransporter, this closes the underlying UDP sockets which
717		// interrupts any blocking I/O calls.
718		//
719		// The standard CloseIdleConnections call _after_ wait is for the net/http
720		// case: it only closes idle connections, so the call should be after wait.
721		// This call is intended to clean up all network resources deterministically
722		// before Close returns.
723		if meek.isQUIC {
724			meek.transport.CloseIdleConnections()
725		}
726
727		meek.relayWaitGroup.Wait()
728		meek.transport.CloseIdleConnections()
729	}
730	return nil
731}
732
733// IsClosed implements the Closer interface. The return value
734// indicates whether the MeekConn has been closed.
735func (meek *MeekConn) IsClosed() bool {
736
737	meek.mutex.Lock()
738	isClosed := meek.isClosed
739	meek.mutex.Unlock()
740
741	return isClosed
742}
743
744// GetMetrics implements the common.MetricsSource interface.
745func (meek *MeekConn) GetMetrics() common.LogFields {
746	logFields := make(common.LogFields)
747	if meek.mode == MeekModeRelay {
748		logFields["meek_cookie_size"] = meek.cookieSize
749		logFields["meek_tls_padding"] = meek.tlsPadding
750		logFields["meek_limit_request"] = meek.limitRequestPayloadLength
751	}
752	return logFields
753}
754
755// ObfuscatedRoundTrip makes a request to the meek server and returns the
756// response. A new, obfuscated meek cookie is created for every request. The
757// specified end point is recorded in the cookie and is not exposed as
758// plaintext in the meek traffic. The caller is responsible for securing and
759// obfuscating the request body.
760//
761// ObfuscatedRoundTrip is not safe for concurrent use, and Close must not be
762// called concurrently. The caller must ensure only one ObfuscatedRoundTrip
763// call is active at once and that it completes or is cancelled before calling
764// Close.
765func (meek *MeekConn) ObfuscatedRoundTrip(
766	requestCtx context.Context, endPoint string, requestBody []byte) ([]byte, error) {
767
768	if meek.mode != MeekModeObfuscatedRoundTrip {
769		return nil, errors.TraceNew("operation unsupported")
770	}
771
772	cookie, _, _, _, err := makeMeekObfuscationValues(
773		meek.getCustomParameters(),
774		meek.meekCookieEncryptionPublicKey,
775		meek.meekObfuscatedKey,
776		meek.meekObfuscatorPaddingSeed,
777		meek.clientTunnelProtocol,
778		endPoint)
779	if err != nil {
780		return nil, errors.Trace(err)
781	}
782
783	// Note:
784	//
785	// - multiple, concurrent ObfuscatedRoundTrip calls are unsafe due to the
786	//   setDialerRequestContext calls in newRequest.
787	//
788	// - concurrent Close and ObfuscatedRoundTrip calls are unsafe as Close does
789	//   not synchronize with ObfuscatedRoundTrip before calling
790	//   meek.transport.CloseIdleConnections(), so resources could be left open.
791	//
792	// At this time, ObfuscatedRoundTrip is used for tactics in Controller and
793	// the concurrency constraints are satisfied.
794
795	request, err := meek.newRequest(
796		requestCtx, cookie, bytes.NewReader(requestBody), 0)
797	if err != nil {
798		return nil, errors.Trace(err)
799	}
800
801	meek.scheduleQUICCloseIdle(request)
802
803	response, err := meek.transport.RoundTrip(request)
804	if err == nil {
805		defer response.Body.Close()
806		if response.StatusCode != http.StatusOK {
807			err = fmt.Errorf("unexpected response status code: %d", response.StatusCode)
808		}
809	}
810	if err != nil {
811		return nil, errors.Trace(err)
812	}
813
814	responseBody, err := ioutil.ReadAll(response.Body)
815	if err != nil {
816		return nil, errors.Trace(err)
817	}
818
819	return responseBody, nil
820}
821
822// RoundTrip implements the http.RoundTripper interface. RoundTrip may only be
823// used when TLS and server certificate verification are configured. RoundTrip
824// does not implement any security or obfuscation at the HTTP layer.
825//
826// RoundTrip is not safe for concurrent use, and Close must not be called
827// concurrently. The caller must ensure only one RoundTrip call is active at
828// once and that it completes or is cancelled before calling Close.
829func (meek *MeekConn) RoundTrip(request *http.Request) (*http.Response, error) {
830
831	if meek.mode != MeekModePlaintextRoundTrip {
832		return nil, errors.TraceNew("operation unsupported")
833	}
834
835	requestCtx := request.Context()
836
837	// The setDialerRequestContext/CloseIdleConnections concurrency note in
838	// ObfuscatedRoundTrip applies to RoundTrip as well.
839
840	// Ensure dials are made within the request context.
841	meek.setDialerRequestContext(requestCtx)
842
843	meek.scheduleQUICCloseIdle(request)
844
845	return meek.transport.RoundTrip(request)
846}
847
848// Read reads data from the connection.
849// net.Conn Deadlines are ignored. net.Conn concurrency semantics are supported.
850func (meek *MeekConn) Read(buffer []byte) (n int, err error) {
851	if meek.mode != MeekModeRelay {
852		return 0, errors.TraceNew("operation unsupported")
853	}
854	if meek.IsClosed() {
855		return 0, errors.TraceNew("meek connection is closed")
856	}
857	// Block until there is received data to consume
858	var receiveBuffer *bytes.Buffer
859	select {
860	case receiveBuffer = <-meek.partialReceiveBuffer:
861	case receiveBuffer = <-meek.fullReceiveBuffer:
862	case <-meek.runCtx.Done():
863		return 0, errors.TraceNew("meek connection has closed")
864	}
865	n, err = receiveBuffer.Read(buffer)
866	meek.replaceReceiveBuffer(receiveBuffer)
867	return n, err
868}
869
870// Write writes data to the connection.
871// net.Conn Deadlines are ignored. net.Conn concurrency semantics are supported.
872func (meek *MeekConn) Write(buffer []byte) (n int, err error) {
873	if meek.mode != MeekModeRelay {
874		return 0, errors.TraceNew("operation unsupported")
875	}
876	if meek.IsClosed() {
877		return 0, errors.TraceNew("meek connection is closed")
878	}
879	// Repeats until all n bytes are written
880	n = len(buffer)
881	for len(buffer) > 0 {
882		// Block until there is capacity in the send buffer
883		var sendBuffer *bytes.Buffer
884		select {
885		case sendBuffer = <-meek.emptySendBuffer:
886		case sendBuffer = <-meek.partialSendBuffer:
887		case <-meek.runCtx.Done():
888			return 0, errors.TraceNew("meek connection has closed")
889		}
890		writeLen := meek.limitRequestPayloadLength - sendBuffer.Len()
891		if writeLen > 0 {
892			if writeLen > len(buffer) {
893				writeLen = len(buffer)
894			}
895			_, err = sendBuffer.Write(buffer[:writeLen])
896			buffer = buffer[writeLen:]
897		}
898		meek.replaceSendBuffer(sendBuffer)
899	}
900	return n, err
901}
902
903// LocalAddr is a stub implementation of net.Conn.LocalAddr
904func (meek *MeekConn) LocalAddr() net.Addr {
905	return nil
906}
907
908// RemoteAddr is a stub implementation of net.Conn.RemoteAddr
909func (meek *MeekConn) RemoteAddr() net.Addr {
910	return nil
911}
912
913// SetDeadline is a stub implementation of net.Conn.SetDeadline
914func (meek *MeekConn) SetDeadline(t time.Time) error {
915	return errors.TraceNew("not supported")
916}
917
918// SetReadDeadline is a stub implementation of net.Conn.SetReadDeadline
919func (meek *MeekConn) SetReadDeadline(t time.Time) error {
920	return errors.TraceNew("not supported")
921}
922
923// SetWriteDeadline is a stub implementation of net.Conn.SetWriteDeadline
924func (meek *MeekConn) SetWriteDeadline(t time.Time) error {
925	return errors.TraceNew("not supported")
926}
927
928func (meek *MeekConn) replaceReceiveBuffer(receiveBuffer *bytes.Buffer) {
929	switch {
930	case receiveBuffer.Len() == 0:
931		meek.emptyReceiveBuffer <- receiveBuffer
932	case receiveBuffer.Len() >= meek.fullReceiveBufferLength:
933		meek.fullReceiveBuffer <- receiveBuffer
934	default:
935		meek.partialReceiveBuffer <- receiveBuffer
936	}
937}
938
939func (meek *MeekConn) replaceSendBuffer(sendBuffer *bytes.Buffer) {
940	switch {
941	case sendBuffer.Len() == 0:
942		meek.emptySendBuffer <- sendBuffer
943	case sendBuffer.Len() >= meek.limitRequestPayloadLength:
944		meek.fullSendBuffer <- sendBuffer
945	default:
946		meek.partialSendBuffer <- sendBuffer
947	}
948}
949
950// relay sends and receives tunneled traffic (payload). An HTTP request is
951// triggered when data is in the write queue or at a polling interval.
952// There's a geometric increase, up to a maximum, in the polling interval when
953// no data is exchanged. Only one HTTP request is in flight at a time.
954func (meek *MeekConn) relay() {
955	// Note: meek.Close() calls here in relay() are made asynchronously
956	// (using goroutines) since Close() will wait on this WaitGroup.
957	defer meek.relayWaitGroup.Done()
958
959	p := meek.getCustomParameters()
960	interval := prng.JitterDuration(
961		p.Duration(parameters.MeekMinPollInterval),
962		p.Float(parameters.MeekMinPollIntervalJitter))
963	p.Close()
964
965	timeout := time.NewTimer(interval)
966	defer timeout.Stop()
967
968	for {
969		timeout.Reset(interval)
970
971		// Block until there is payload to send or it is time to poll
972		var sendBuffer *bytes.Buffer
973		select {
974		case sendBuffer = <-meek.partialSendBuffer:
975		case sendBuffer = <-meek.fullSendBuffer:
976		case <-timeout.C:
977			// In the polling case, send an empty payload
978		case <-meek.runCtx.Done():
979			// Drop through to second Done() check
980		}
981
982		// Check Done() again, to ensure it takes precedence
983		select {
984		case <-meek.runCtx.Done():
985			return
986		default:
987		}
988
989		sendPayloadSize := 0
990		if sendBuffer != nil {
991			sendPayloadSize = sendBuffer.Len()
992		}
993
994		// relayRoundTrip will replace sendBuffer (by calling replaceSendBuffer). This
995		// is a compromise to conserve memory. Using a second buffer here, we could
996		// copy sendBuffer and immediately replace it, unblocking meekConn.Write() and
997		// allowing more upstream payload to immediately enqueue. Instead, the request
998		// payload is read directly from sendBuffer, including retries. Only once the
999		// server has acknowledged the request payload is sendBuffer replaced. This
1000		// still allows meekConn.Write() to unblock before the round trip response is
1001		// read.
1002
1003		receivedPayloadSize, err := meek.relayRoundTrip(sendBuffer)
1004
1005		if err != nil {
1006			select {
1007			case <-meek.runCtx.Done():
1008				// In this case, meek.relayRoundTrip encountered Done(). Exit without
1009				// logging error.
1010				return
1011			default:
1012			}
1013			NoticeWarning("%s", errors.Trace(err))
1014			go meek.Close()
1015			return
1016		}
1017
1018		// Periodically re-dial the underlying TLS connection.
1019
1020		if prng.FlipWeightedCoin(meek.redialTLSProbability) {
1021			meek.transport.CloseIdleConnections()
1022		}
1023
1024		// Calculate polling interval. When data is received,
1025		// immediately request more. Otherwise, schedule next
1026		// poll with exponential back off. Jitter and coin
1027		// flips are used to avoid trivial, static traffic
1028		// timing patterns.
1029
1030		p := meek.getCustomParameters()
1031
1032		if receivedPayloadSize > 0 || sendPayloadSize > 0 {
1033
1034			interval = 0
1035
1036		} else if interval == 0 {
1037
1038			interval = prng.JitterDuration(
1039				p.Duration(parameters.MeekMinPollInterval),
1040				p.Float(parameters.MeekMinPollIntervalJitter))
1041
1042		} else {
1043
1044			if p.WeightedCoinFlip(parameters.MeekApplyPollIntervalMultiplierProbability) {
1045
1046				interval =
1047					time.Duration(float64(interval) *
1048						p.Float(parameters.MeekPollIntervalMultiplier))
1049			}
1050
1051			interval = prng.JitterDuration(
1052				interval,
1053				p.Float(parameters.MeekPollIntervalJitter))
1054
1055			if interval >= p.Duration(parameters.MeekMaxPollInterval) {
1056
1057				interval = prng.JitterDuration(
1058					p.Duration(parameters.MeekMaxPollInterval),
1059					p.Float(parameters.MeekMaxPollIntervalJitter))
1060			}
1061		}
1062
1063		p.Close()
1064	}
1065}
1066
1067// readCloseSignaller is an io.ReadCloser wrapper for an io.Reader
1068// that is passed, as the request body, to http.Transport.RoundTrip.
1069// readCloseSignaller adds the AwaitClosed call, which is used
1070// to schedule recycling the buffer underlying the reader only after
1071// RoundTrip has called Close and will no longer use the buffer.
1072// See: https://github.com/ooni/psiphon/oopsi/golang.org/pkg/net/http/#RoundTripper
1073type readCloseSignaller struct {
1074	context context.Context
1075	reader  io.Reader
1076	closed  chan struct{}
1077}
1078
1079func NewReadCloseSignaller(
1080	context context.Context,
1081	reader io.Reader) *readCloseSignaller {
1082
1083	return &readCloseSignaller{
1084		context: context,
1085		reader:  reader,
1086		closed:  make(chan struct{}, 1),
1087	}
1088}
1089
1090func (r *readCloseSignaller) Read(p []byte) (int, error) {
1091	return r.reader.Read(p)
1092}
1093
1094func (r *readCloseSignaller) Close() error {
1095	select {
1096	case r.closed <- struct{}{}:
1097	default:
1098	}
1099	return nil
1100}
1101
1102func (r *readCloseSignaller) AwaitClosed() bool {
1103	select {
1104	case <-r.context.Done():
1105	case <-r.closed:
1106		return true
1107	}
1108	return false
1109}
1110
1111// newRequest performs common request setup for both MeekModeRelay and
1112// MeekModeObfuscatedRoundTrip.
1113//
1114// newRequest is not safe for concurrent calls due to its use of
1115// setRequestContext.
1116//
1117// The caller must call the returned cancelFunc.
1118func (meek *MeekConn) newRequest(
1119	requestCtx context.Context,
1120	cookie *http.Cookie,
1121	body io.Reader,
1122	contentLength int) (*http.Request, error) {
1123
1124	// Ensure dials are made within the request context.
1125	meek.setDialerRequestContext(requestCtx)
1126
1127	request, err := http.NewRequest("POST", meek.url.String(), body)
1128	if err != nil {
1129		return nil, errors.Trace(err)
1130	}
1131
1132	request = request.WithContext(requestCtx)
1133
1134	// Content-Length may not be be set automatically due to the
1135	// underlying type of requestBody.
1136	if contentLength > 0 {
1137		request.ContentLength = int64(contentLength)
1138	}
1139
1140	meek.addAdditionalHeaders(request)
1141
1142	request.Header.Set("Content-Type", "application/octet-stream")
1143
1144	if cookie == nil {
1145		cookie = meek.cookie
1146	}
1147	request.AddCookie(cookie)
1148
1149	return request, nil
1150}
1151
1152// setDialerRequestContext ensures that underlying TLS/QUIC dials operate
1153// within the context of the request context. setDialerRequestContext must not
1154// be called while another request is already in flight.
1155func (meek *MeekConn) setDialerRequestContext(requestCtx context.Context) {
1156	if meek.isQUIC {
1157		meek.transport.(*quic.QUICTransporter).SetRequestContext(requestCtx)
1158	} else if meek.cachedTLSDialer != nil {
1159		meek.cachedTLSDialer.setRequestContext(requestCtx)
1160	}
1161}
1162
1163// Workaround for h2quic.RoundTripper context issue. See comment in
1164// MeekConn.Close.
1165func (meek *MeekConn) scheduleQUICCloseIdle(request *http.Request) {
1166	requestCtx := request.Context()
1167	if meek.isQUIC && requestCtx != context.Background() {
1168		go func() {
1169			<-requestCtx.Done()
1170			meek.transport.CloseIdleConnections()
1171		}()
1172	}
1173}
1174
1175// relayRoundTrip configures and makes the actual HTTP POST request
1176func (meek *MeekConn) relayRoundTrip(sendBuffer *bytes.Buffer) (int64, error) {
1177
1178	// Retries are made when the round trip fails. This adds resiliency
1179	// to connection interruption and intermittent failures.
1180	//
1181	// At least one retry is always attempted, and retries continue
1182	// while still within a brief deadline -- 5 seconds, currently the
1183	// deadline for an actively probed SSH connection to timeout. There
1184	// is a brief delay between retries, allowing for intermittent
1185	// failure states to resolve.
1186	//
1187	// Failure may occur at various stages of the HTTP request:
1188	//
1189	// 1. Before the request begins. In this case, the entire request
1190	//    may be rerun.
1191	//
1192	// 2. While sending the request payload. In this case, the client
1193	//    must resend its request payload. The server will not have
1194	//    relayed its partially received request payload.
1195	//
1196	// 3. After sending the request payload but before receiving
1197	//    a response. The client cannot distinguish between case 2 and
1198	//    this case, case 3. The client resends its payload and the
1199	//    server detects this and skips relaying the request payload.
1200	//
1201	// 4. While reading the response payload. The client will omit its
1202	//    request payload when retrying, as the server has already
1203	//    acknowledged it. The client will also indicate to the server
1204	//    the amount of response payload already received, and the
1205	//    server will skip resending the indicated amount of response
1206	//    payload.
1207	//
1208	// Retries are indicated to the server by adding a Range header,
1209	// which includes the response payload resend position.
1210
1211	defer func() {
1212		// Ensure sendBuffer is replaced, even in error code paths.
1213		if sendBuffer != nil {
1214			sendBuffer.Truncate(0)
1215			meek.replaceSendBuffer(sendBuffer)
1216		}
1217	}()
1218
1219	retries := uint(0)
1220
1221	p := meek.getCustomParameters()
1222	retryDeadline := time.Now().Add(p.Duration(parameters.MeekRoundTripRetryDeadline))
1223	retryDelay := p.Duration(parameters.MeekRoundTripRetryMinDelay)
1224	retryMaxDelay := p.Duration(parameters.MeekRoundTripRetryMaxDelay)
1225	retryMultiplier := p.Float(parameters.MeekRoundTripRetryMultiplier)
1226	p.Close()
1227
1228	serverAcknowledgedRequestPayload := false
1229
1230	receivedPayloadSize := int64(0)
1231
1232	for try := 0; ; try++ {
1233
1234		// Omit the request payload when retrying after receiving a
1235		// partial server response.
1236
1237		var signaller *readCloseSignaller
1238		var requestBody io.ReadCloser
1239		contentLength := 0
1240		if !serverAcknowledgedRequestPayload && sendBuffer != nil {
1241
1242			// sendBuffer will be replaced once the data is no longer needed,
1243			// when RoundTrip calls Close on the Body; this allows meekConn.Write()
1244			// to unblock and start buffering data for the next roung trip while
1245			// still reading the current round trip response. signaller provides
1246			// the hook for awaiting RoundTrip's call to Close.
1247
1248			signaller = NewReadCloseSignaller(meek.runCtx, bytes.NewReader(sendBuffer.Bytes()))
1249			requestBody = signaller
1250			contentLength = sendBuffer.Len()
1251		}
1252
1253		// - meek.stopRunning() will abort a round trip in flight
1254		// - round trip will abort if it exceeds timeout
1255		requestCtx, cancelFunc := context.WithTimeout(
1256			meek.runCtx,
1257			meek.getCustomParameters().Duration(parameters.MeekRoundTripTimeout))
1258		defer cancelFunc()
1259
1260		request, err := meek.newRequest(
1261			requestCtx,
1262			nil,
1263			requestBody,
1264			contentLength)
1265		if err != nil {
1266			// Don't retry when can't initialize a Request
1267			return 0, errors.Trace(err)
1268		}
1269
1270		expectedStatusCode := http.StatusOK
1271
1272		// When retrying, add a Range header to indicate how much
1273		// of the response was already received.
1274
1275		if try > 0 {
1276			expectedStatusCode = http.StatusPartialContent
1277			request.Header.Set("Range", fmt.Sprintf("bytes=%d-", receivedPayloadSize))
1278		}
1279
1280		response, err := meek.transport.RoundTrip(request)
1281
1282		// Wait for RoundTrip to call Close on the request body, when
1283		// there is one. This is necessary to ensure it's safe to
1284		// subsequently replace sendBuffer in both the success and
1285		// error cases.
1286		if signaller != nil {
1287			if !signaller.AwaitClosed() {
1288				// AwaitClosed encountered Done(). Abort immediately. Do not
1289				// replace sendBuffer, as we cannot be certain RoundTrip is
1290				// done with it. MeekConn.Write will exit on Done and not hang
1291				// awaiting sendBuffer.
1292				sendBuffer = nil
1293				return 0, errors.TraceNew("meek connection has closed")
1294			}
1295		}
1296
1297		if err != nil {
1298			select {
1299			case <-meek.runCtx.Done():
1300				// Exit without retrying and without logging error.
1301				return 0, errors.Trace(err)
1302			default:
1303			}
1304			NoticeWarning("meek round trip failed: %s", err)
1305			// ...continue to retry
1306		}
1307
1308		if err == nil {
1309
1310			if response.StatusCode != expectedStatusCode &&
1311				// Certain http servers return 200 OK where we expect 206, so accept that.
1312				!(expectedStatusCode == http.StatusPartialContent && response.StatusCode == http.StatusOK) {
1313
1314				// Don't retry when the status code is incorrect
1315				response.Body.Close()
1316				return 0, errors.Tracef(
1317					"unexpected status code: %d instead of %d",
1318					response.StatusCode, expectedStatusCode)
1319			}
1320
1321			// Update meek session cookie
1322			for _, c := range response.Cookies() {
1323				if meek.cookie.Name == c.Name {
1324					meek.cookie.Value = c.Value
1325					break
1326				}
1327			}
1328
1329			// Received the response status code, so the server
1330			// must have received the request payload.
1331			serverAcknowledgedRequestPayload = true
1332
1333			// sendBuffer is now no longer required for retries, and the
1334			// buffer may be replaced; this allows meekConn.Write() to unblock
1335			// and start buffering data for the next round trip while still
1336			// reading the current round trip response.
1337			if sendBuffer != nil {
1338				// Assumes signaller.AwaitClosed is called above, so
1339				// sendBuffer will no longer be accessed by RoundTrip.
1340				sendBuffer.Truncate(0)
1341				meek.replaceSendBuffer(sendBuffer)
1342				sendBuffer = nil
1343			}
1344
1345			readPayloadSize, err := meek.readPayload(response.Body)
1346			response.Body.Close()
1347
1348			// receivedPayloadSize is the number of response
1349			// payload bytes received and relayed. A retry can
1350			// resume after this position.
1351			receivedPayloadSize += readPayloadSize
1352
1353			if err != nil {
1354				NoticeWarning("meek read payload failed: %s", err)
1355				// ...continue to retry
1356			} else {
1357				// Round trip completed successfully
1358				break
1359			}
1360		}
1361
1362		// Release context resources immediately.
1363		cancelFunc()
1364
1365		// Either the request failed entirely, or there was a failure
1366		// streaming the response payload. Always retry once. Then
1367		// retry if time remains; when the next delay exceeds the time
1368		// remaining until the deadline, do not retry.
1369
1370		now := time.Now()
1371
1372		if retries >= 1 &&
1373			(now.After(retryDeadline) || retryDeadline.Sub(now) <= retryDelay) {
1374			return 0, errors.Trace(err)
1375		}
1376		retries += 1
1377
1378		delayTimer := time.NewTimer(retryDelay)
1379
1380		select {
1381		case <-delayTimer.C:
1382		case <-meek.runCtx.Done():
1383			delayTimer.Stop()
1384			return 0, errors.Trace(err)
1385		}
1386
1387		// Increase the next delay, to back off and avoid excessive
1388		// activity in conditions such as no network connectivity.
1389
1390		retryDelay = time.Duration(
1391			float64(retryDelay) * retryMultiplier)
1392		if retryDelay >= retryMaxDelay {
1393			retryDelay = retryMaxDelay
1394		}
1395	}
1396
1397	return receivedPayloadSize, nil
1398}
1399
1400// Add additional headers to the HTTP request using the same method we use for adding
1401// custom headers to HTTP proxy requests.
1402func (meek *MeekConn) addAdditionalHeaders(request *http.Request) {
1403	for name, value := range meek.additionalHeaders {
1404		// hack around special case of "Host" header
1405		// https://github.com/ooni/psiphon/oopsi/golang.org/src/net/http/request.go#L474
1406		// using URL.Opaque, see URL.RequestURI() https://github.com/ooni/psiphon/oopsi/golang.org/src/net/url/url.go#L915
1407		if name == "Host" {
1408			if len(value) > 0 {
1409				if request.URL.Opaque == "" {
1410					request.URL.Opaque = request.URL.Scheme + "://" + request.Host + request.URL.RequestURI()
1411				}
1412				request.Host = value[0]
1413			}
1414		} else {
1415			request.Header[name] = value
1416		}
1417	}
1418}
1419
1420// readPayload reads the HTTP response in chunks, making the read buffer available
1421// to MeekConn.Read() calls after each chunk; the intention is to allow bytes to
1422// flow back to the reader as soon as possible instead of buffering the entire payload.
1423//
1424// When readPayload returns an error, the totalSize output is remains valid -- it's the
1425// number of payload bytes successfully read and relayed.
1426func (meek *MeekConn) readPayload(
1427	receivedPayload io.ReadCloser) (totalSize int64, err error) {
1428
1429	defer receivedPayload.Close()
1430	totalSize = 0
1431	for {
1432		reader := io.LimitReader(receivedPayload, int64(meek.readPayloadChunkLength))
1433		// Block until there is capacity in the receive buffer
1434		var receiveBuffer *bytes.Buffer
1435		select {
1436		case receiveBuffer = <-meek.emptyReceiveBuffer:
1437		case receiveBuffer = <-meek.partialReceiveBuffer:
1438		case <-meek.runCtx.Done():
1439			return 0, nil
1440		}
1441		// Note: receiveBuffer size may exceed meek.fullReceiveBufferLength by up to the size
1442		// of one received payload. The meek.fullReceiveBufferLength value is just a guideline.
1443		n, err := receiveBuffer.ReadFrom(reader)
1444		meek.replaceReceiveBuffer(receiveBuffer)
1445		totalSize += n
1446		if err != nil {
1447			return totalSize, errors.Trace(err)
1448		}
1449		if n == 0 {
1450			break
1451		}
1452	}
1453	return totalSize, nil
1454}
1455
1456// makeMeekObfuscationValues creates the meek cookie, to be sent with initial
1457// meek HTTP request, and other meek obfuscation values. The cookies contains
1458// obfuscated metadata, including meek version and other protocol information.
1459//
1460// In round tripper mode, the cookie contains the destination endpoint for the
1461// round trip request.
1462//
1463// In relay mode, the server will create a session using the cookie values and
1464// send the session ID back to the client via Set-Cookie header. The client
1465// must use that value with all consequent HTTP requests.
1466//
1467// In plain HTTP meek protocols, the cookie is visible over the adversary
1468// network, so the cookie is encrypted and obfuscated.
1469//
1470// Obsolete meek cookie fields used by the legacy server stack are no longer
1471// sent. These include ServerAddress and SessionID.
1472//
1473// The request payload limit and TLS redial probability apply only to relay
1474// mode and are selected once and used for the duration of a meek connction.
1475func makeMeekObfuscationValues(
1476	p parameters.ParametersAccessor,
1477	meekCookieEncryptionPublicKey string,
1478	meekObfuscatedKey string,
1479	meekObfuscatorPaddingPRNGSeed *prng.Seed,
1480	clientTunnelProtocol string,
1481	endPoint string,
1482
1483) (cookie *http.Cookie,
1484	tlsPadding int,
1485	limitRequestPayloadLength int,
1486	redialTLSProbability float64,
1487	err error) {
1488
1489	if meekCookieEncryptionPublicKey == "" {
1490		return nil, 0, 0, 0.0, errors.TraceNew("missing public key")
1491	}
1492
1493	cookieData := &protocol.MeekCookieData{
1494		MeekProtocolVersion:  MEEK_PROTOCOL_VERSION,
1495		ClientTunnelProtocol: clientTunnelProtocol,
1496		EndPoint:             endPoint,
1497	}
1498	serializedCookie, err := json.Marshal(cookieData)
1499	if err != nil {
1500		return nil, 0, 0, 0.0, errors.Trace(err)
1501	}
1502
1503	// Encrypt the JSON data
1504	// NaCl box is used for encryption. The peer public key comes from the server entry.
1505	// Nonce is always all zeros, and is not sent in the cookie (the server also uses an all-zero nonce).
1506	// http://nacl.cace-project.eu/box.html:
1507	// "There is no harm in having the same nonce for different messages if the {sender, receiver} sets are
1508	// different. This is true even if the sets overlap. For example, a sender can use the same nonce for two
1509	// different messages if the messages are sent to two different public keys."
1510	var nonce [24]byte
1511	var publicKey [32]byte
1512	decodedPublicKey, err := base64.StdEncoding.DecodeString(meekCookieEncryptionPublicKey)
1513	if err != nil {
1514		return nil, 0, 0, 0.0, errors.Trace(err)
1515	}
1516	copy(publicKey[:], decodedPublicKey)
1517	ephemeralPublicKey, ephemeralPrivateKey, err := box.GenerateKey(rand.Reader)
1518	if err != nil {
1519		return nil, 0, 0, 0.0, errors.Trace(err)
1520	}
1521	box := box.Seal(nil, serializedCookie, &nonce, &publicKey, ephemeralPrivateKey)
1522	encryptedCookie := make([]byte, 32+len(box))
1523	copy(encryptedCookie[0:32], ephemeralPublicKey[0:32])
1524	copy(encryptedCookie[32:], box)
1525
1526	maxPadding := p.Int(parameters.MeekCookieMaxPadding)
1527
1528	// Obfuscate the encrypted data. NewClientObfuscator checks that
1529	// meekObfuscatedKey isn't missing.
1530	obfuscator, err := obfuscator.NewClientObfuscator(
1531		&obfuscator.ObfuscatorConfig{
1532			Keyword:         meekObfuscatedKey,
1533			PaddingPRNGSeed: meekObfuscatorPaddingPRNGSeed,
1534			MaxPadding:      &maxPadding})
1535	if err != nil {
1536		return nil, 0, 0, 0.0, errors.Trace(err)
1537	}
1538	obfuscatedCookie := obfuscator.SendSeedMessage()
1539	seedLen := len(obfuscatedCookie)
1540	obfuscatedCookie = append(obfuscatedCookie, encryptedCookie...)
1541	obfuscator.ObfuscateClientToServer(obfuscatedCookie[seedLen:])
1542
1543	cookieNamePRNG, err := obfuscator.GetDerivedPRNG("meek-cookie-name")
1544	if err != nil {
1545		return nil, 0, 0, 0.0, errors.Trace(err)
1546	}
1547
1548	// Format the HTTP cookie
1549	// The format is <random letter 'A'-'Z'>=<base64 data>, which is intended to match common cookie formats.
1550	A := int('A')
1551	Z := int('Z')
1552	// letterIndex is integer in range [int('A'), int('Z')]
1553	letterIndex := cookieNamePRNG.Intn(Z - A + 1)
1554
1555	cookie = &http.Cookie{
1556		Name:  string(byte(A + letterIndex)),
1557		Value: base64.StdEncoding.EncodeToString(obfuscatedCookie)}
1558
1559	tlsPadding = 0
1560	limitRequestPayloadLength = MEEK_MAX_REQUEST_PAYLOAD_LENGTH
1561	redialTLSProbability = 0.0
1562
1563	tunnelProtocols := p.TunnelProtocols(parameters.MeekTrafficShapingLimitProtocols)
1564	if (len(tunnelProtocols) == 0 ||
1565		common.Contains(tunnelProtocols, clientTunnelProtocol)) &&
1566		p.WeightedCoinFlip(parameters.MeekTrafficShapingProbability) {
1567
1568		limitRequestPayloadLengthPRNG, err := obfuscator.GetDerivedPRNG(
1569			"meek-limit-request-payload-length")
1570		if err != nil {
1571			return nil, 0, 0, 0.0, errors.Trace(err)
1572		}
1573
1574		minLength := p.Int(parameters.MeekMinLimitRequestPayloadLength)
1575		if minLength > MEEK_MAX_REQUEST_PAYLOAD_LENGTH {
1576			minLength = MEEK_MAX_REQUEST_PAYLOAD_LENGTH
1577		}
1578		maxLength := p.Int(parameters.MeekMaxLimitRequestPayloadLength)
1579		if maxLength > MEEK_MAX_REQUEST_PAYLOAD_LENGTH {
1580			maxLength = MEEK_MAX_REQUEST_PAYLOAD_LENGTH
1581		}
1582
1583		limitRequestPayloadLength = limitRequestPayloadLengthPRNG.Range(
1584			minLength, maxLength)
1585
1586		minPadding := p.Int(parameters.MeekMinTLSPadding)
1587		maxPadding := p.Int(parameters.MeekMaxTLSPadding)
1588
1589		// Maximum padding size per RFC 7685
1590		if maxPadding > 65535 {
1591			maxPadding = 65535
1592		}
1593
1594		if maxPadding > 0 {
1595			tlsPaddingPRNG, err := obfuscator.GetDerivedPRNG(
1596				"meek-tls-padding")
1597			if err != nil {
1598				return nil, 0, 0, 0.0, errors.Trace(err)
1599			}
1600
1601			tlsPadding = tlsPaddingPRNG.Range(minPadding, maxPadding)
1602		}
1603
1604		redialTLSProbability = p.Float(parameters.MeekRedialTLSProbability)
1605	}
1606
1607	return cookie, tlsPadding, limitRequestPayloadLength, redialTLSProbability, nil
1608}
1609