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