github.com/psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/meekConn.go (about)

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