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