github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/quic.go (about) 1 //go:build !PSIPHON_DISABLE_QUIC 2 // +build !PSIPHON_DISABLE_QUIC 3 4 /* 5 * Copyright (c) 2018, Psiphon Inc. 6 * All rights reserved. 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * 21 */ 22 23 /* 24 25 Package quic wraps github.com/lucas-clemente/quic-go with net.Listener and 26 net.Conn types that provide a drop-in replacement for net.TCPConn. 27 28 Each QUIC session has exactly one stream, which is the equivilent of a TCP 29 stream. 30 31 Conns returned from Accept will have an established QUIC session and are 32 configured to perform a deferred AcceptStream on the first Read or Write. 33 34 Conns returned from Dial have an established QUIC session and stream. Dial 35 accepts a Context input which may be used to cancel the dial. 36 37 Conns mask or translate qerr.PeerGoingAway to io.EOF as appropriate. 38 39 QUIC idle timeouts and keep alives are tuned to mitigate aggressive UDP NAT 40 timeouts on mobile data networks while accounting for the fact that mobile 41 devices in standby/sleep may not be able to initiate the keep alive. 42 43 */ 44 package quic 45 46 import ( 47 "context" 48 "crypto/tls" 49 "fmt" 50 "io" 51 "net" 52 "net/http" 53 "os" 54 "sync" 55 "sync/atomic" 56 "syscall" 57 "time" 58 59 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common" 60 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors" 61 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator" 62 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng" 63 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol" 64 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/values" 65 ietf_quic "github.com/Psiphon-Labs/quic-go" 66 "github.com/Psiphon-Labs/quic-go/http3" 67 ) 68 69 const ( 70 SERVER_HANDSHAKE_TIMEOUT = 30 * time.Second 71 SERVER_IDLE_TIMEOUT = 5 * time.Minute 72 CLIENT_IDLE_TIMEOUT = 30 * time.Second 73 UDP_PACKET_WRITE_TIMEOUT = 1 * time.Second 74 ) 75 76 // Enabled indicates if QUIC functionality is enabled. 77 func Enabled() bool { 78 return true 79 } 80 81 const ietfQUIC1VersionNumber = 0x1 82 83 var supportedVersionNumbers = map[string]uint32{ 84 protocol.QUIC_VERSION_GQUIC39: uint32(0x51303339), 85 protocol.QUIC_VERSION_GQUIC43: uint32(0x51303433), 86 protocol.QUIC_VERSION_GQUIC44: uint32(0x51303434), 87 protocol.QUIC_VERSION_OBFUSCATED: uint32(0x51303433), 88 protocol.QUIC_VERSION_V1: ietfQUIC1VersionNumber, 89 protocol.QUIC_VERSION_RANDOMIZED_V1: ietfQUIC1VersionNumber, 90 protocol.QUIC_VERSION_OBFUSCATED_V1: uint32(ietfQUIC1VersionNumber), 91 protocol.QUIC_VERSION_DECOY_V1: uint32(ietfQUIC1VersionNumber), 92 } 93 94 func isObfuscated(quicVersion string) bool { 95 return quicVersion == protocol.QUIC_VERSION_OBFUSCATED || 96 quicVersion == protocol.QUIC_VERSION_OBFUSCATED_V1 || 97 quicVersion == protocol.QUIC_VERSION_DECOY_V1 98 } 99 100 func isDecoy(quicVersion string) bool { 101 return quicVersion == protocol.QUIC_VERSION_DECOY_V1 102 } 103 104 func isClientHelloRandomized(quicVersion string) bool { 105 return quicVersion == protocol.QUIC_VERSION_RANDOMIZED_V1 106 } 107 108 func isIETF(quicVersion string) bool { 109 versionNumber, ok := supportedVersionNumbers[quicVersion] 110 if !ok { 111 return false 112 } 113 return isIETFVersionNumber(versionNumber) 114 } 115 116 func isIETFVersionNumber(versionNumber uint32) bool { 117 return versionNumber == ietfQUIC1VersionNumber 118 } 119 120 func isGQUIC(quicVersion string) bool { 121 return quicVersion == protocol.QUIC_VERSION_GQUIC39 || 122 quicVersion == protocol.QUIC_VERSION_GQUIC43 || 123 quicVersion == protocol.QUIC_VERSION_GQUIC44 || 124 quicVersion == protocol.QUIC_VERSION_OBFUSCATED 125 } 126 127 func getALPN(versionNumber uint32) string { 128 return "h3" 129 } 130 131 // quic_test overrides the server idle timeout. 132 var serverIdleTimeout = SERVER_IDLE_TIMEOUT 133 134 // Listener is a net.Listener. 135 type Listener struct { 136 quicListener 137 obfuscatedPacketConn *ObfuscatedPacketConn 138 clientRandomHistory *obfuscator.SeedHistory 139 } 140 141 // Listen creates a new Listener. 142 func Listen( 143 logger common.Logger, 144 irregularTunnelLogger func(string, error, common.LogFields), 145 address string, 146 obfuscationKey string, 147 enableGQUIC bool) (net.Listener, error) { 148 149 certificate, privateKey, err := common.GenerateWebServerCertificate( 150 values.GetHostName()) 151 if err != nil { 152 return nil, errors.Trace(err) 153 } 154 155 tlsCertificate, err := tls.X509KeyPair( 156 []byte(certificate), []byte(privateKey)) 157 if err != nil { 158 return nil, errors.Trace(err) 159 } 160 161 addr, err := net.ResolveUDPAddr("udp", address) 162 if err != nil { 163 return nil, errors.Trace(err) 164 } 165 166 udpConn, err := net.ListenUDP("udp", addr) 167 if err != nil { 168 return nil, errors.Trace(err) 169 } 170 171 seed, err := prng.NewSeed() 172 if err != nil { 173 udpConn.Close() 174 return nil, errors.Trace(err) 175 } 176 177 obfuscatedPacketConn, err := NewObfuscatedPacketConn( 178 udpConn, true, false, false, obfuscationKey, seed) 179 if err != nil { 180 udpConn.Close() 181 return nil, errors.Trace(err) 182 } 183 184 // QUIC clients must prove knowledge of the obfuscated key via a message 185 // sent in the TLS ClientHello random field, or receive no UDP packets 186 // back from the server. This anti-probing mechanism is implemented using 187 // the existing Passthrough message and SeedHistory replay detection 188 // mechanisms. The replay history TTL is set to the validity period of 189 // the passthrough message. 190 // 191 // Irregular events are logged for invalid client activity. 192 193 clientRandomHistory := obfuscator.NewSeedHistory( 194 &obfuscator.SeedHistoryConfig{SeedTTL: obfuscator.TLS_PASSTHROUGH_TIME_PERIOD}) 195 196 verifyClientHelloRandom := func(remoteAddr net.Addr, clientHelloRandom []byte) bool { 197 198 ok := obfuscator.VerifyTLSPassthroughMessage( 199 true, obfuscationKey, clientHelloRandom) 200 if !ok { 201 irregularTunnelLogger( 202 common.IPAddressFromAddr(remoteAddr), 203 errors.TraceNew("invalid client random message"), 204 nil) 205 return false 206 } 207 208 // Replay history is set to non-strict mode, allowing for a legitimate 209 // client to resend its Initial packet, as may happen. Since the 210 // source _port_ should be the same as the source IP in this case, we use 211 // the full IP:port value as the client address from which a replay is 212 // allowed. 213 // 214 // The non-strict case where ok is true and logFields is not nil is 215 // ignored, and nothing is logged in that scenario. 216 217 ok, logFields := clientRandomHistory.AddNew( 218 false, remoteAddr.String(), "client-hello-random", clientHelloRandom) 219 if !ok && logFields != nil { 220 irregularTunnelLogger( 221 common.IPAddressFromAddr(remoteAddr), 222 errors.TraceNew("duplicate client random message"), 223 *logFields) 224 } 225 226 return ok 227 } 228 229 var quicListener quicListener 230 231 if !enableGQUIC { 232 233 // When gQUIC is disabled, skip the muxListener entirely. This allows 234 // quic-go to enable ECN operations as the packet conn is a 235 // quic-goOOBCapablePacketConn; this provides some performance 236 // optimizations and also generate packets that may be harder to 237 // fingerprint, due to lack of ECN bits in IP packets otherwise. 238 // Skipping muxListener also avoids the additional overhead of 239 // pumping read packets though mux channels. 240 241 tlsConfig, ietfQUICConfig := makeIETFConfig( 242 obfuscatedPacketConn, verifyClientHelloRandom, tlsCertificate) 243 244 listener, err := ietf_quic.Listen( 245 obfuscatedPacketConn, tlsConfig, ietfQUICConfig) 246 if err != nil { 247 obfuscatedPacketConn.Close() 248 return nil, errors.Trace(err) 249 } 250 251 quicListener = &ietfQUICListener{Listener: listener} 252 253 } else { 254 255 // Note that, due to nature of muxListener, full accepts may happen before 256 // return and caller calls Accept. 257 258 muxListener, err := newMuxListener( 259 logger, verifyClientHelloRandom, obfuscatedPacketConn, tlsCertificate) 260 if err != nil { 261 obfuscatedPacketConn.Close() 262 return nil, errors.Trace(err) 263 } 264 265 quicListener = muxListener 266 } 267 268 return &Listener{ 269 quicListener: quicListener, 270 obfuscatedPacketConn: obfuscatedPacketConn, 271 clientRandomHistory: clientRandomHistory, 272 }, nil 273 } 274 275 func makeIETFConfig( 276 conn *ObfuscatedPacketConn, 277 verifyClientHelloRandom func(net.Addr, []byte) bool, 278 tlsCertificate tls.Certificate) (*tls.Config, *ietf_quic.Config) { 279 280 tlsConfig := &tls.Config{ 281 Certificates: []tls.Certificate{tlsCertificate}, 282 NextProtos: []string{getALPN(ietfQUIC1VersionNumber)}, 283 } 284 285 ietfQUICConfig := &ietf_quic.Config{ 286 HandshakeIdleTimeout: SERVER_HANDSHAKE_TIMEOUT, 287 MaxIdleTimeout: serverIdleTimeout, 288 MaxIncomingStreams: 1, 289 MaxIncomingUniStreams: -1, 290 KeepAlive: true, 291 292 // The quic-go server may respond with a version negotiation packet 293 // before reaching the Initial packet processing with its 294 // anti-probing defense. This may happen even for a malformed packet. 295 // To prevent all responses to probers, version negotiation is 296 // disabled, which disables sending these packets. The fact that the 297 // server does not issue version negotiation packets may be a 298 // fingerprint itself, but, regardless, probers cannot ellicit any 299 // reponse from the server without providing a well-formed Initial 300 // packet with a valid Client Hello random value. 301 // 302 // Limitation: once version negotiate is required, the order of 303 // quic-go operations may need to be changed in order to first check 304 // the Initial/Client Hello, and then issue any required version 305 // negotiation packet. 306 DisableVersionNegotiationPackets: true, 307 308 VerifyClientHelloRandom: verifyClientHelloRandom, 309 ServerMaxPacketSizeAdjustment: conn.serverMaxPacketSizeAdjustment, 310 } 311 312 return tlsConfig, ietfQUICConfig 313 } 314 315 // Accept returns a net.Conn that wraps a single QUIC session and stream. The 316 // stream establishment is deferred until the first Read or Write, allowing 317 // Accept to be called in a fast loop while goroutines spawned to handle each 318 // net.Conn will perform the blocking AcceptStream. 319 func (listener *Listener) Accept() (net.Conn, error) { 320 321 session, err := listener.quicListener.Accept() 322 if err != nil { 323 return nil, errors.Trace(err) 324 } 325 326 return &Conn{ 327 session: session, 328 deferredAcceptStream: true, 329 }, nil 330 } 331 332 func (listener *Listener) Close() error { 333 334 // First close the underlying packet conn to ensure all quic-go goroutines 335 // as well as any blocking Accept call goroutine is interrupted. Note 336 // that muxListener does this as well, so this is for the IETF-only case. 337 _ = listener.obfuscatedPacketConn.Close() 338 339 return listener.quicListener.Close() 340 } 341 342 // Dial establishes a new QUIC session and stream to the server specified by 343 // address. 344 // 345 // packetConn is used as the underlying packet connection for QUIC. The dial 346 // may be cancelled by ctx; packetConn will be closed if the dial is 347 // cancelled or fails. 348 // 349 // Keep alive and idle timeout functionality in QUIC is disabled as these 350 // aspects are expected to be handled at a higher level. 351 func Dial( 352 ctx context.Context, 353 packetConn net.PacketConn, 354 remoteAddr *net.UDPAddr, 355 quicSNIAddress string, 356 quicVersion string, 357 clientHelloSeed *prng.Seed, 358 obfuscationKey string, 359 obfuscationPaddingSeed *prng.Seed, 360 disablePathMTUDiscovery bool) (net.Conn, error) { 361 362 if quicVersion == "" { 363 return nil, errors.TraceNew("missing version") 364 } 365 366 if isClientHelloRandomized(quicVersion) && clientHelloSeed == nil { 367 return nil, errors.TraceNew("missing client hello randomization values") 368 } 369 370 // obfuscationKey is always required, as it is used for anti-probing even 371 // when not obfuscating the QUIC payload. 372 if (isObfuscated(quicVersion) && obfuscationPaddingSeed == nil) || obfuscationKey == "" { 373 return nil, errors.TraceNew("missing obfuscation values") 374 } 375 376 versionNumber, ok := supportedVersionNumbers[quicVersion] 377 if !ok { 378 return nil, errors.Tracef("unsupported version: %s", quicVersion) 379 } 380 381 // Fail if the destination port is invalid. Network operations should fail 382 // quickly in this case, but IETF quic-go has been observed to timeout, 383 // instead of failing quickly, in the case of invalid destination port 0. 384 if remoteAddr.Port <= 0 || remoteAddr.Port >= 65536 { 385 return nil, errors.Tracef("invalid destination port: %d", remoteAddr.Port) 386 } 387 388 udpConn, ok := packetConn.(udpConn) 389 if !ok { 390 return nil, errors.TraceNew("packetConn must implement net.UDPConn functions") 391 } 392 393 // Ensure blocked packet writes eventually timeout. 394 packetConn = &writeTimeoutUDPConn{ 395 udpConn: udpConn, 396 } 397 398 maxPacketSizeAdjustment := 0 399 400 if isObfuscated(quicVersion) { 401 obfuscatedPacketConn, err := NewObfuscatedPacketConn( 402 packetConn, 403 false, 404 isIETFVersionNumber(versionNumber), 405 isDecoy(quicVersion), 406 obfuscationKey, 407 obfuscationPaddingSeed) 408 if err != nil { 409 return nil, errors.Trace(err) 410 } 411 packetConn = obfuscatedPacketConn 412 413 // Reserve space for packet obfuscation overhead so that quic-go will 414 // continue to produce packets of max size 1280. 415 maxPacketSizeAdjustment = OBFUSCATED_MAX_PACKET_SIZE_ADJUSTMENT 416 } 417 418 // As an anti-probing measure, QUIC clients must prove knowledge of the 419 // server obfuscation key in the first client packet sent to the server. In 420 // the case of QUIC, the first packet, the Initial packet, contains a TLS 421 // Client Hello, and we set the client random field to a value that both 422 // proves knowledge of the obfuscation key and is indistiguishable from 423 // random. This is the same "passthrough" technique used for TLS, although 424 // for QUIC the server simply doesn't respond to any packets instead of 425 // passing traffic through to a different server. 426 // 427 // Limitation: the legacy gQUIC implementation does not support this 428 // anti-probling measure; gQUIC must be disabled to ensure no response 429 // from the server. 430 431 var getClientHelloRandom func() ([]byte, error) 432 if obfuscationKey != "" { 433 getClientHelloRandom = func() ([]byte, error) { 434 random, err := obfuscator.MakeTLSPassthroughMessage(true, obfuscationKey) 435 if err != nil { 436 return nil, errors.Trace(err) 437 } 438 return random, nil 439 } 440 } 441 442 session, err := dialQUIC( 443 ctx, 444 packetConn, 445 remoteAddr, 446 quicSNIAddress, 447 versionNumber, 448 clientHelloSeed, 449 getClientHelloRandom, 450 maxPacketSizeAdjustment, 451 disablePathMTUDiscovery, 452 false) 453 if err != nil { 454 packetConn.Close() 455 return nil, errors.Trace(err) 456 } 457 458 type dialResult struct { 459 conn *Conn 460 err error 461 } 462 463 resultChannel := make(chan dialResult) 464 465 go func() { 466 467 stream, err := session.OpenStream() 468 if err != nil { 469 session.Close() 470 resultChannel <- dialResult{err: err} 471 return 472 } 473 474 resultChannel <- dialResult{ 475 conn: &Conn{ 476 packetConn: packetConn, 477 session: session, 478 stream: stream, 479 }, 480 } 481 }() 482 483 var conn *Conn 484 485 select { 486 case result := <-resultChannel: 487 conn, err = result.conn, result.err 488 case <-ctx.Done(): 489 err = ctx.Err() 490 // Interrupt the goroutine 491 session.Close() 492 <-resultChannel 493 } 494 495 if err != nil { 496 packetConn.Close() 497 return nil, errors.Trace(err) 498 } 499 500 return conn, nil 501 } 502 503 // udpConn matches net.UDPConn, which implements both net.Conn and 504 // net.PacketConn. udpConn enables handling of Dial packetConn inputs that 505 // are not concrete *net.UDPConn types but which still implement all the 506 // required functions. A udpConn instance can be passed to quic-go; various 507 // quic-go code paths check that the input conn implements net.Conn and/or 508 // net.PacketConn. 509 // 510 // TODO: add *AddrPort functions introduced in Go 1.18 511 type udpConn interface { 512 Close() error 513 File() (f *os.File, err error) 514 LocalAddr() net.Addr 515 Read(b []byte) (int, error) 516 ReadFrom(b []byte) (int, net.Addr, error) 517 ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) 518 ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error) 519 RemoteAddr() net.Addr 520 SetDeadline(t time.Time) error 521 SetReadBuffer(bytes int) error 522 SetReadDeadline(t time.Time) error 523 SetWriteBuffer(bytes int) error 524 SetWriteDeadline(t time.Time) error 525 SyscallConn() (syscall.RawConn, error) 526 Write(b []byte) (int, error) 527 WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) 528 WriteTo(b []byte, addr net.Addr) (int, error) 529 WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) 530 } 531 532 // writeTimeoutUDPConn sets write deadlines before each UDP packet write. 533 // 534 // Generally, a UDP packet write doesn't block. However, Go's 535 // internal/poll.FD.WriteMsg continues to loop when syscall.SendmsgN fails 536 // with EAGAIN, which indicates that an OS socket buffer is currently full; 537 // in certain OS states this may cause WriteMsgUDP/etc. to block 538 // indefinitely. In this scenario, we want to instead behave as if the packet 539 // were dropped, so we set a write deadline which will eventually interrupt 540 // any EAGAIN loop. 541 // 542 // Note that quic-go manages read deadlines; we set only the write deadline 543 // here. 544 type writeTimeoutUDPConn struct { 545 udpConn 546 } 547 548 func (conn *writeTimeoutUDPConn) Write(b []byte) (int, error) { 549 550 err := conn.SetWriteDeadline(time.Now().Add(UDP_PACKET_WRITE_TIMEOUT)) 551 if err != nil { 552 return 0, errors.Trace(err) 553 } 554 555 // Do not wrap any I/O err returned by udpConn 556 return conn.udpConn.Write(b) 557 } 558 559 func (conn *writeTimeoutUDPConn) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (int, int, error) { 560 561 err := conn.SetWriteDeadline(time.Now().Add(UDP_PACKET_WRITE_TIMEOUT)) 562 if err != nil { 563 return 0, 0, errors.Trace(err) 564 } 565 566 // Do not wrap any I/O err returned by udpConn 567 return conn.udpConn.WriteMsgUDP(b, oob, addr) 568 } 569 570 func (conn *writeTimeoutUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) { 571 572 err := conn.SetWriteDeadline(time.Now().Add(UDP_PACKET_WRITE_TIMEOUT)) 573 if err != nil { 574 return 0, errors.Trace(err) 575 } 576 577 // Do not wrap any I/O err returned by udpConn 578 return conn.udpConn.WriteTo(b, addr) 579 } 580 581 func (conn *writeTimeoutUDPConn) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) { 582 583 err := conn.SetWriteDeadline(time.Now().Add(UDP_PACKET_WRITE_TIMEOUT)) 584 if err != nil { 585 return 0, errors.Trace(err) 586 } 587 588 // Do not wrap any I/O err returned by udpConn 589 return conn.udpConn.WriteToUDP(b, addr) 590 } 591 592 // Conn is a net.Conn and psiphon/common.Closer. 593 type Conn struct { 594 packetConn net.PacketConn 595 session quicSession 596 597 deferredAcceptStream bool 598 599 acceptMutex sync.Mutex 600 acceptErr error 601 stream quicStream 602 603 readMutex sync.Mutex 604 writeMutex sync.Mutex 605 606 isClosed int32 607 } 608 609 func (conn *Conn) doDeferredAcceptStream() error { 610 conn.acceptMutex.Lock() 611 defer conn.acceptMutex.Unlock() 612 613 if conn.stream != nil { 614 return nil 615 } 616 617 if conn.acceptErr != nil { 618 return conn.acceptErr 619 } 620 621 stream, err := conn.session.AcceptStream() 622 if err != nil { 623 conn.session.Close() 624 conn.acceptErr = errors.Trace(err) 625 return conn.acceptErr 626 } 627 628 conn.stream = stream 629 630 return nil 631 } 632 633 func (conn *Conn) Read(b []byte) (int, error) { 634 635 if conn.deferredAcceptStream { 636 err := conn.doDeferredAcceptStream() 637 if err != nil { 638 return 0, errors.Trace(err) 639 } 640 } 641 642 // Add mutex to provide full net.Conn concurrency semantics. 643 // https://github.com/lucas-clemente/quic-go/blob/9cc23135d0477baf83aa4715de39ae7070039cb2/stream.go#L64 644 // "Read() and Write() may be called concurrently, but multiple calls to 645 // "Read() or Write() individually must be synchronized manually." 646 conn.readMutex.Lock() 647 defer conn.readMutex.Unlock() 648 649 n, err := conn.stream.Read(b) 650 if conn.session.isErrorIndicatingClosed(err) { 651 _ = conn.Close() 652 err = io.EOF 653 } 654 return n, err 655 } 656 657 func (conn *Conn) Write(b []byte) (int, error) { 658 659 if conn.deferredAcceptStream { 660 err := conn.doDeferredAcceptStream() 661 if err != nil { 662 return 0, errors.Trace(err) 663 } 664 } 665 666 conn.writeMutex.Lock() 667 defer conn.writeMutex.Unlock() 668 669 n, err := conn.stream.Write(b) 670 if conn.session.isErrorIndicatingClosed(err) { 671 _ = conn.Close() 672 if n == len(b) { 673 err = nil 674 } 675 } 676 return n, err 677 } 678 679 func (conn *Conn) Close() error { 680 err := conn.session.Close() 681 if conn.packetConn != nil { 682 err1 := conn.packetConn.Close() 683 if err == nil { 684 err = err1 685 } 686 } 687 atomic.StoreInt32(&conn.isClosed, 1) 688 return err 689 } 690 691 func (conn *Conn) IsClosed() bool { 692 return atomic.LoadInt32(&conn.isClosed) == 1 693 } 694 695 func (conn *Conn) LocalAddr() net.Addr { 696 return conn.session.LocalAddr() 697 } 698 699 func (conn *Conn) RemoteAddr() net.Addr { 700 return conn.session.RemoteAddr() 701 } 702 703 func (conn *Conn) SetDeadline(t time.Time) error { 704 705 if conn.deferredAcceptStream { 706 err := conn.doDeferredAcceptStream() 707 if err != nil { 708 return errors.Trace(err) 709 } 710 } 711 712 return conn.stream.SetDeadline(t) 713 } 714 715 func (conn *Conn) SetReadDeadline(t time.Time) error { 716 717 if conn.deferredAcceptStream { 718 err := conn.doDeferredAcceptStream() 719 if err != nil { 720 return errors.Trace(err) 721 } 722 } 723 724 return conn.stream.SetReadDeadline(t) 725 } 726 727 func (conn *Conn) SetWriteDeadline(t time.Time) error { 728 729 if conn.deferredAcceptStream { 730 err := conn.doDeferredAcceptStream() 731 if err != nil { 732 return errors.Trace(err) 733 } 734 } 735 736 return conn.stream.SetWriteDeadline(t) 737 } 738 739 // QUICTransporter implements the psiphon.transporter interface, used in 740 // psiphon.MeekConn for HTTP requests, which requires a RoundTripper and 741 // CloseIdleConnections. 742 type QUICTransporter struct { 743 quicRoundTripper 744 noticeEmitter func(string) 745 udpDialer func(ctx context.Context) (net.PacketConn, *net.UDPAddr, error) 746 quicSNIAddress string 747 quicVersion string 748 clientHelloSeed *prng.Seed 749 disablePathMTUDiscovery bool 750 packetConn atomic.Value 751 752 mutex sync.Mutex 753 ctx context.Context 754 } 755 756 // NewQUICTransporter creates a new QUICTransporter. 757 func NewQUICTransporter( 758 ctx context.Context, 759 noticeEmitter func(string), 760 udpDialer func(ctx context.Context) (net.PacketConn, *net.UDPAddr, error), 761 quicSNIAddress string, 762 quicVersion string, 763 clientHelloSeed *prng.Seed, 764 disablePathMTUDiscovery bool) (*QUICTransporter, error) { 765 766 if quicVersion == "" { 767 return nil, errors.TraceNew("missing version") 768 } 769 770 versionNumber, ok := supportedVersionNumbers[quicVersion] 771 if !ok { 772 return nil, errors.Tracef("unsupported version: %s", quicVersion) 773 } 774 775 if isClientHelloRandomized(quicVersion) && clientHelloSeed == nil { 776 return nil, errors.TraceNew("missing client hello randomization values") 777 } 778 779 t := &QUICTransporter{ 780 noticeEmitter: noticeEmitter, 781 udpDialer: udpDialer, 782 quicSNIAddress: quicSNIAddress, 783 quicVersion: quicVersion, 784 clientHelloSeed: clientHelloSeed, 785 disablePathMTUDiscovery: disablePathMTUDiscovery, 786 ctx: ctx, 787 } 788 789 if isIETFVersionNumber(versionNumber) { 790 t.quicRoundTripper = &http3.RoundTripper{Dial: t.dialIETFQUIC} 791 } else { 792 var err error 793 t.quicRoundTripper, err = gQUICRoundTripper(t) 794 if err != nil { 795 return nil, errors.Trace(err) 796 } 797 } 798 799 return t, nil 800 } 801 802 func (t *QUICTransporter) SetRequestContext(ctx context.Context) { 803 // Note: can't use sync.Value since underlying type of ctx changes. 804 t.mutex.Lock() 805 defer t.mutex.Unlock() 806 t.ctx = ctx 807 } 808 809 // CloseIdleConnections wraps QUIC RoundTripper.Close, which provides the 810 // necessary functionality for psiphon.transporter as used by 811 // psiphon.MeekConn. Note that, unlike http.Transport.CloseIdleConnections, 812 // the connections are closed regardless of idle status. 813 func (t *QUICTransporter) CloseIdleConnections() { 814 815 // This operation doesn't prevent a concurrent http3.client.dial from 816 // establishing a new packet conn; we also rely on the request context to 817 // fully interrupt and stop a http3.RoundTripper. 818 819 t.closePacketConn() 820 t.quicRoundTripper.Close() 821 } 822 823 func (t *QUICTransporter) closePacketConn() { 824 packetConn := t.packetConn.Load() 825 if p, ok := packetConn.(net.PacketConn); ok { 826 p.Close() 827 } 828 } 829 830 func (t *QUICTransporter) dialIETFQUIC( 831 _, _ string, _ *tls.Config, _ *ietf_quic.Config) (ietf_quic.EarlySession, error) { 832 session, err := t.dialQUIC() 833 if err != nil { 834 return nil, errors.Trace(err) 835 } 836 return session.(*ietfQUICSession).Session.(ietf_quic.EarlySession), nil 837 } 838 839 func (t *QUICTransporter) dialQUIC() (retSession quicSession, retErr error) { 840 841 defer func() { 842 if retErr != nil && t.noticeEmitter != nil { 843 t.noticeEmitter(fmt.Sprintf("QUICTransporter.dialQUIC failed: %s", retErr)) 844 } 845 }() 846 847 versionNumber, ok := supportedVersionNumbers[t.quicVersion] 848 if !ok { 849 return nil, errors.Tracef("unsupported version: %s", t.quicVersion) 850 } 851 852 t.mutex.Lock() 853 ctx := t.ctx 854 t.mutex.Unlock() 855 if ctx == nil { 856 ctx = context.Background() 857 } 858 859 packetConn, remoteAddr, err := t.udpDialer(ctx) 860 if err != nil { 861 return nil, errors.Trace(err) 862 } 863 864 session, err := dialQUIC( 865 ctx, 866 packetConn, 867 remoteAddr, 868 t.quicSNIAddress, 869 versionNumber, 870 t.clientHelloSeed, 871 nil, 872 0, 873 t.disablePathMTUDiscovery, 874 true) 875 if err != nil { 876 packetConn.Close() 877 return nil, errors.Trace(err) 878 } 879 880 // dialQUIC uses quic-go.DialContext as we must create our own UDP sockets to 881 // set properties such as BIND_TO_DEVICE. However, when DialContext is used, 882 // quic-go does not take responsibiity for closing the underlying packetConn 883 // when the QUIC session is closed. 884 // 885 // We track the most recent packetConn in QUICTransporter and close it: 886 // - when CloseIdleConnections is called, as it is by psiphon.MeekConn when 887 // it is closing; 888 // - here in dialFunc, with the assumption that only one concurrent QUIC 889 // session is used per h2quic.RoundTripper. 890 // 891 // This code also assume no concurrent calls to dialFunc, as otherwise a race 892 // condition exists between closePacketConn and Store. 893 894 t.closePacketConn() 895 t.packetConn.Store(packetConn) 896 897 return session, nil 898 } 899 900 // The following code provides support for using both gQUIC and IETF QUIC, 901 // which are implemented in two different branches (now forks) of quic-go. 902 // (The gQUIC functions are now located in gquic.go and the entire gQUIC 903 // quic-go stack may be conditionally excluded from builds). 904 // 905 // dialQUIC uses the appropriate quic-go and returns quicSession which wraps 906 // either a ietf_quic.Session or gquic.Session. 907 // 908 // muxPacketConn provides a multiplexing listener that directs packets to 909 // either a ietf_quic.Listener or a gquic.Listener based on the content of the 910 // packet. 911 912 type quicListener interface { 913 Close() error 914 Addr() net.Addr 915 Accept() (quicSession, error) 916 } 917 918 type quicSession interface { 919 io.Closer 920 LocalAddr() net.Addr 921 RemoteAddr() net.Addr 922 AcceptStream() (quicStream, error) 923 OpenStream() (quicStream, error) 924 isErrorIndicatingClosed(err error) bool 925 } 926 927 type quicStream interface { 928 io.Reader 929 io.Writer 930 io.Closer 931 SetReadDeadline(t time.Time) error 932 SetWriteDeadline(t time.Time) error 933 SetDeadline(t time.Time) error 934 } 935 936 type quicRoundTripper interface { 937 http.RoundTripper 938 Close() error 939 } 940 941 type ietfQUICListener struct { 942 ietf_quic.Listener 943 } 944 945 func (l *ietfQUICListener) Accept() (quicSession, error) { 946 // A specific context is not provided since the interface needs to match the 947 // gquic-go API, which lacks context support. 948 session, err := l.Listener.Accept(context.Background()) 949 if err != nil { 950 return nil, errors.Trace(err) 951 } 952 return &ietfQUICSession{Session: session}, nil 953 } 954 955 type ietfQUICSession struct { 956 ietf_quic.Session 957 } 958 959 func (s *ietfQUICSession) AcceptStream() (quicStream, error) { 960 // A specific context is not provided since the interface needs to match the 961 // gquic-go API, which lacks context support. 962 // 963 // TODO: once gQUIC support is retired, this context may be used in place 964 // of the deferredAcceptStream mechanism. 965 stream, err := s.Session.AcceptStream(context.Background()) 966 if err != nil { 967 return nil, errors.Trace(err) 968 } 969 return stream, nil 970 } 971 972 func (s *ietfQUICSession) OpenStream() (quicStream, error) { 973 return s.Session.OpenStream() 974 } 975 976 func (s *ietfQUICSession) Close() error { 977 return s.Session.CloseWithError(0, "") 978 } 979 980 func (s *ietfQUICSession) isErrorIndicatingClosed(err error) bool { 981 if err == nil { 982 return false 983 } 984 errStr := err.Error() 985 // The target errors are of type qerr.ApplicationError and 986 // qerr.IdleTimeoutError, but these are not exported by quic-go. 987 return errStr == "Application error 0x0" || 988 errStr == "timeout: no recent network activity" 989 } 990 991 func dialQUIC( 992 ctx context.Context, 993 packetConn net.PacketConn, 994 remoteAddr *net.UDPAddr, 995 quicSNIAddress string, 996 versionNumber uint32, 997 clientHelloSeed *prng.Seed, 998 getClientHelloRandom func() ([]byte, error), 999 clientMaxPacketSizeAdjustment int, 1000 disablePathMTUDiscovery bool, 1001 dialEarly bool) (quicSession, error) { 1002 1003 if isIETFVersionNumber(versionNumber) { 1004 quicConfig := &ietf_quic.Config{ 1005 HandshakeIdleTimeout: time.Duration(1<<63 - 1), 1006 MaxIdleTimeout: CLIENT_IDLE_TIMEOUT, 1007 KeepAlive: true, 1008 Versions: []ietf_quic.VersionNumber{ 1009 ietf_quic.VersionNumber(versionNumber)}, 1010 ClientHelloSeed: clientHelloSeed, 1011 GetClientHelloRandom: getClientHelloRandom, 1012 ClientMaxPacketSizeAdjustment: clientMaxPacketSizeAdjustment, 1013 DisablePathMTUDiscovery: disablePathMTUDiscovery, 1014 } 1015 1016 deadline, ok := ctx.Deadline() 1017 if ok { 1018 quicConfig.HandshakeIdleTimeout = time.Until(deadline) 1019 } 1020 1021 var dialSession ietf_quic.Session 1022 var err error 1023 tlsConfig := &tls.Config{ 1024 InsecureSkipVerify: true, 1025 NextProtos: []string{getALPN(versionNumber)}, 1026 } 1027 1028 if dialEarly { 1029 dialSession, err = ietf_quic.DialEarlyContext( 1030 ctx, 1031 packetConn, 1032 remoteAddr, 1033 quicSNIAddress, 1034 tlsConfig, 1035 quicConfig) 1036 } else { 1037 dialSession, err = ietf_quic.DialContext( 1038 ctx, 1039 packetConn, 1040 remoteAddr, 1041 quicSNIAddress, 1042 tlsConfig, 1043 quicConfig) 1044 } 1045 if err != nil { 1046 return nil, errors.Trace(err) 1047 } 1048 1049 return &ietfQUICSession{Session: dialSession}, nil 1050 1051 } else { 1052 1053 quicSession, err := gQUICDialContext( 1054 ctx, 1055 packetConn, 1056 remoteAddr, 1057 quicSNIAddress, 1058 versionNumber) 1059 if err != nil { 1060 return nil, errors.Trace(err) 1061 } 1062 1063 return quicSession, nil 1064 } 1065 } 1066 1067 const ( 1068 muxPacketQueueSize = 128 1069 muxPacketBufferSize = 1452 // quic-go.MaxReceivePacketSize 1070 ) 1071 1072 type packet struct { 1073 addr net.Addr 1074 size int 1075 data []byte 1076 } 1077 1078 // muxPacketConn delivers packets to a specific quic-go listener. 1079 type muxPacketConn struct { 1080 localAddr net.Addr 1081 listener *muxListener 1082 packets chan *packet 1083 } 1084 1085 func newMuxPacketConn(localAddr net.Addr, listener *muxListener) *muxPacketConn { 1086 return &muxPacketConn{ 1087 localAddr: localAddr, 1088 listener: listener, 1089 packets: make(chan *packet, muxPacketQueueSize), 1090 } 1091 } 1092 1093 func (conn *muxPacketConn) ReadFrom(b []byte) (int, net.Addr, error) { 1094 1095 select { 1096 case p := <-conn.packets: 1097 1098 // If b is too short, the packet is truncated. This won't happen as long as 1099 // muxPacketBufferSize matches quic-go.MaxReceivePacketSize. 1100 copy(b, p.data[0:p.size]) 1101 n := p.size 1102 addr := p.addr 1103 1104 // Clear and replace packet buffer. 1105 p.size = 0 1106 conn.listener.packets <- p 1107 1108 return n, addr, nil 1109 case <-conn.listener.stopBroadcast: 1110 return 0, nil, io.EOF 1111 } 1112 } 1113 1114 func (conn *muxPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { 1115 return conn.listener.conn.WriteTo(b, addr) 1116 } 1117 1118 func (conn *muxPacketConn) Close() error { 1119 // This Close won't unblock Read/Write operations or propagate the Close 1120 // signal up to muxListener. The correct way to shutdown is to call 1121 // muxListener.Close. 1122 return nil 1123 } 1124 1125 func (conn *muxPacketConn) LocalAddr() net.Addr { 1126 return conn.localAddr 1127 } 1128 1129 func (conn *muxPacketConn) SetDeadline(t time.Time) error { 1130 return errors.TraceNew("not supported") 1131 } 1132 1133 func (conn *muxPacketConn) SetReadDeadline(t time.Time) error { 1134 return errors.TraceNew("not supported") 1135 } 1136 1137 func (conn *muxPacketConn) SetWriteDeadline(t time.Time) error { 1138 return errors.TraceNew("not supported") 1139 } 1140 1141 // SetReadBuffer and SyscallConn provide passthroughs to the underlying 1142 // net.UDPConn implementations, used to optimize the UDP receive buffer size. 1143 // See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size 1144 // and ietf_quic.setReceiveBuffer. Only the IETF stack will access these 1145 // functions. 1146 // 1147 // Limitation: due to the relayPackets/ReadFrom scheme, this simple 1148 // passthrough does not suffice to provide access to ReadMsgUDP for 1149 // https://godoc.org/github.com/lucas-clemente/quic-go#ECNCapablePacketConn. 1150 1151 func (conn *muxPacketConn) SetReadBuffer(bytes int) error { 1152 c, ok := conn.listener.conn.OOBCapablePacketConn.(interface { 1153 SetReadBuffer(int) error 1154 }) 1155 if !ok { 1156 return errors.TraceNew("not supported") 1157 } 1158 return c.SetReadBuffer(bytes) 1159 } 1160 1161 func (conn *muxPacketConn) SyscallConn() (syscall.RawConn, error) { 1162 c, ok := conn.listener.conn.OOBCapablePacketConn.(interface { 1163 SyscallConn() (syscall.RawConn, error) 1164 }) 1165 if !ok { 1166 return nil, errors.TraceNew("not supported") 1167 } 1168 return c.SyscallConn() 1169 } 1170 1171 // muxListener is a multiplexing packet conn listener which relays packets to 1172 // multiple quic-go listeners. 1173 type muxListener struct { 1174 logger common.Logger 1175 isClosed int32 1176 runWaitGroup *sync.WaitGroup 1177 stopBroadcast chan struct{} 1178 conn *ObfuscatedPacketConn 1179 packets chan *packet 1180 acceptedSessions chan quicSession 1181 ietfQUICConn *muxPacketConn 1182 ietfQUICListener quicListener 1183 gQUICConn *muxPacketConn 1184 gQUICListener quicListener 1185 } 1186 1187 func newMuxListener( 1188 logger common.Logger, 1189 verifyClientHelloRandom func(net.Addr, []byte) bool, 1190 conn *ObfuscatedPacketConn, 1191 tlsCertificate tls.Certificate) (*muxListener, error) { 1192 1193 listener := &muxListener{ 1194 logger: logger, 1195 runWaitGroup: new(sync.WaitGroup), 1196 stopBroadcast: make(chan struct{}), 1197 conn: conn, 1198 packets: make(chan *packet, muxPacketQueueSize), 1199 acceptedSessions: make(chan quicSession, 2), // 1 per listener 1200 } 1201 1202 // All packet relay buffers are allocated in advance. 1203 for i := 0; i < muxPacketQueueSize; i++ { 1204 listener.packets <- &packet{data: make([]byte, muxPacketBufferSize)} 1205 } 1206 1207 listener.ietfQUICConn = newMuxPacketConn(conn.LocalAddr(), listener) 1208 1209 tlsConfig, ietfQUICConfig := makeIETFConfig( 1210 conn, verifyClientHelloRandom, tlsCertificate) 1211 1212 il, err := ietf_quic.Listen(listener.ietfQUICConn, tlsConfig, ietfQUICConfig) 1213 if err != nil { 1214 return nil, errors.Trace(err) 1215 } 1216 listener.ietfQUICListener = &ietfQUICListener{Listener: il} 1217 1218 listener.gQUICConn = newMuxPacketConn(conn.LocalAddr(), listener) 1219 1220 gl, err := gQUICListen(listener.gQUICConn, tlsCertificate, serverIdleTimeout) 1221 if err != nil { 1222 listener.ietfQUICListener.Close() 1223 return nil, errors.Trace(err) 1224 } 1225 listener.gQUICListener = gl 1226 1227 listener.runWaitGroup.Add(3) 1228 go listener.relayPackets() 1229 go listener.relayAcceptedSessions(listener.gQUICListener) 1230 go listener.relayAcceptedSessions(listener.ietfQUICListener) 1231 1232 return listener, nil 1233 } 1234 1235 func (listener *muxListener) relayPackets() { 1236 defer listener.runWaitGroup.Done() 1237 1238 for { 1239 1240 var p *packet 1241 select { 1242 case p = <-listener.packets: 1243 case <-listener.stopBroadcast: 1244 return 1245 } 1246 1247 // Read network packets. The DPI functionality of the obfuscation layer 1248 // identifies the type of QUIC, gQUIC or IETF, in addition to identifying 1249 // and processing obfuscation. This type information determines which 1250 // quic-go receives the packet. 1251 // 1252 // Network errors are not relayed to quic-go, as it will shut down the 1253 // server on any error returned from ReadFrom, even net.Error.Temporary() 1254 // errors. 1255 1256 var isIETF bool 1257 var err error 1258 p.size, _, _, p.addr, isIETF, err = listener.conn.readPacketWithType(p.data, nil) 1259 if err != nil { 1260 if listener.logger != nil { 1261 message := "readFromWithType failed" 1262 if e, ok := err.(net.Error); ok && e.Temporary() { 1263 listener.logger.WithTraceFields( 1264 common.LogFields{"error": err}).Debug(message) 1265 } else { 1266 listener.logger.WithTraceFields( 1267 common.LogFields{"error": err}).Warning(message) 1268 } 1269 } 1270 // TODO: propagate non-temporary errors to Accept? 1271 listener.packets <- p 1272 continue 1273 } 1274 1275 // Send the packet to the correct quic-go. The packet is dropped if the 1276 // target quic-go packet queue is full. 1277 1278 if isIETF { 1279 select { 1280 case listener.ietfQUICConn.packets <- p: 1281 default: 1282 listener.packets <- p 1283 } 1284 } else { 1285 select { 1286 case listener.gQUICConn.packets <- p: 1287 default: 1288 listener.packets <- p 1289 } 1290 } 1291 } 1292 } 1293 1294 func (listener *muxListener) relayAcceptedSessions(l quicListener) { 1295 defer listener.runWaitGroup.Done() 1296 for { 1297 session, err := l.Accept() 1298 if err != nil { 1299 if listener.logger != nil { 1300 message := "Accept failed" 1301 if e, ok := err.(net.Error); ok && e.Temporary() { 1302 listener.logger.WithTraceFields( 1303 common.LogFields{"error": err}).Debug(message) 1304 } else { 1305 listener.logger.WithTraceFields( 1306 common.LogFields{"error": err}).Warning(message) 1307 } 1308 } 1309 // TODO: propagate non-temporary errors to Accept? 1310 select { 1311 case <-listener.stopBroadcast: 1312 return 1313 default: 1314 } 1315 continue 1316 } 1317 select { 1318 case listener.acceptedSessions <- session: 1319 case <-listener.stopBroadcast: 1320 return 1321 } 1322 } 1323 } 1324 1325 func (listener *muxListener) Accept() (quicSession, error) { 1326 select { 1327 case conn := <-listener.acceptedSessions: 1328 return conn, nil 1329 case <-listener.stopBroadcast: 1330 return nil, errors.TraceNew("closed") 1331 } 1332 } 1333 1334 func (listener *muxListener) Close() error { 1335 1336 // Ensure close channel only called once. 1337 if !atomic.CompareAndSwapInt32(&listener.isClosed, 0, 1) { 1338 return nil 1339 } 1340 1341 close(listener.stopBroadcast) 1342 1343 var retErr error 1344 1345 err := listener.gQUICListener.Close() 1346 if err != nil && retErr == nil { 1347 retErr = errors.Trace(err) 1348 } 1349 1350 err = listener.ietfQUICListener.Close() 1351 if err != nil && retErr == nil { 1352 retErr = errors.Trace(err) 1353 } 1354 1355 err = listener.conn.Close() 1356 if err != nil && retErr == nil { 1357 retErr = errors.Trace(err) 1358 } 1359 1360 listener.runWaitGroup.Wait() 1361 1362 return retErr 1363 } 1364 1365 func (listener *muxListener) Addr() net.Addr { 1366 return listener.conn.LocalAddr() 1367 }