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