obfuscator_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. //go:build !PSIPHON_DISABLE_QUIC
  2. // +build !PSIPHON_DISABLE_QUIC
  3. /*
  4. * Copyright (c) 2023, Psiphon Inc.
  5. * All rights reserved.
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. package quic
  22. import (
  23. "context"
  24. "encoding/hex"
  25. "net"
  26. "strings"
  27. "testing"
  28. "time"
  29. tls "github.com/Psiphon-Labs/psiphon-tls"
  30. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  31. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  32. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  33. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/transforms"
  34. "golang.org/x/sync/errgroup"
  35. )
  36. func TestNonceTransformer(t *testing.T) {
  37. for quicVersion := range supportedVersionNumbers {
  38. if !isObfuscated(quicVersion) {
  39. continue
  40. }
  41. t.Run(quicVersion, func(t *testing.T) {
  42. runNonceTransformer(t, quicVersion)
  43. })
  44. }
  45. }
  46. func runNonceTransformer(t *testing.T, quicVersion string) {
  47. serverIdleTimeout = 1 * time.Second
  48. obfuscationKey := prng.HexString(32)
  49. listener, err := net.ListenPacket("udp", "127.0.0.1:0")
  50. if err != nil {
  51. t.Fatalf("Listen failed: %s", err)
  52. }
  53. serverAddress := listener.LocalAddr().(*net.UDPAddr)
  54. testGroup, testCtx := errgroup.WithContext(context.Background())
  55. testGroup.Go(func() error {
  56. var serverGroup errgroup.Group
  57. // reads the first packet and verifies the nonce prefix
  58. serverGroup.Go(func() error {
  59. b := make([]byte, 1024)
  60. _, _, err := listener.ReadFrom(b)
  61. if err != nil {
  62. return errors.Trace(err)
  63. }
  64. prefix := hex.EncodeToString(b[:NONCE_SIZE])
  65. if prefix != "ffff00000000000000000000" {
  66. return errors.Tracef("unexpected prefix: %s", prefix)
  67. }
  68. return nil
  69. })
  70. err = serverGroup.Wait()
  71. if err != nil {
  72. return errors.Trace(err)
  73. }
  74. return nil
  75. })
  76. // client
  77. testGroup.Go(func() error {
  78. ctx, cancelFunc := context.WithTimeout(
  79. context.Background(), 1*time.Second)
  80. defer cancelFunc()
  81. packetConn, err := net.ListenPacket("udp4", "127.0.0.1:0")
  82. if err != nil {
  83. return errors.Trace(err)
  84. }
  85. obfuscationPaddingSeed, err := prng.NewSeed()
  86. if err != nil {
  87. return errors.Trace(err)
  88. }
  89. var clientHelloSeed *prng.Seed
  90. if isClientHelloRandomized(quicVersion) {
  91. clientHelloSeed, err = prng.NewSeed()
  92. if err != nil {
  93. return errors.Trace(err)
  94. }
  95. }
  96. // Dial with nonce transformer
  97. _, err = Dial(
  98. ctx,
  99. packetConn,
  100. serverAddress,
  101. serverAddress.String(),
  102. quicVersion,
  103. clientHelloSeed,
  104. obfuscationKey,
  105. obfuscationPaddingSeed,
  106. &transforms.ObfuscatorSeedTransformerParameters{
  107. TransformName: "",
  108. TransformSeed: &prng.Seed{0},
  109. TransformSpec: transforms.Spec{{"^.{24}", "ffff00000000000000000000"}},
  110. },
  111. false,
  112. 0,
  113. false,
  114. false, // Disable obfuscated PSK
  115. common.WrapClientSessionCache(tls.NewLRUClientSessionCache(0), "test"),
  116. )
  117. // A timeout (deadline exceeded) is expected since the stub server
  118. // just reads the prefix and doesn't perform a QUIC handshake. Any
  119. // other dial error is a failure.
  120. if err == nil || !strings.HasSuffix(err.Error(), "context deadline exceeded") {
  121. return errors.Trace(err)
  122. }
  123. return nil
  124. })
  125. go func() {
  126. testGroup.Wait()
  127. }()
  128. <-testCtx.Done()
  129. listener.Close()
  130. err = testGroup.Wait()
  131. if err != nil {
  132. t.Errorf("goroutine failed: %s", err)
  133. }
  134. }