obfuscator_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. "testing"
  27. "time"
  28. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  29. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  30. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/transforms"
  31. "golang.org/x/sync/errgroup"
  32. )
  33. func TestNonceTransformer(t *testing.T) {
  34. for quicVersion := range supportedVersionNumbers {
  35. if !isObfuscated(quicVersion) {
  36. continue
  37. }
  38. t.Run(quicVersion, func(t *testing.T) {
  39. runNonceTransformer(t, quicVersion)
  40. })
  41. }
  42. }
  43. func runNonceTransformer(t *testing.T, quicVersion string) {
  44. serverIdleTimeout = 1 * time.Second
  45. obfuscationKey := prng.HexString(32)
  46. listener, err := net.ListenPacket("udp", "127.0.0.1:0")
  47. if err != nil {
  48. t.Fatalf("Listen failed: %s", err)
  49. }
  50. serverAddress := listener.LocalAddr().(*net.UDPAddr)
  51. testGroup, testCtx := errgroup.WithContext(context.Background())
  52. testGroup.Go(func() error {
  53. var serverGroup errgroup.Group
  54. // reads the first packet and verifies the nonce prefix
  55. serverGroup.Go(func() error {
  56. b := make([]byte, 1024)
  57. _, _, err := listener.ReadFrom(b)
  58. if err != nil {
  59. return errors.Trace(err)
  60. }
  61. prefix := hex.EncodeToString(b[:NONCE_SIZE])
  62. if prefix != "ffff00000000000000000000" {
  63. return errors.Tracef("unexpected prefix: %s", prefix)
  64. }
  65. return nil
  66. })
  67. err = serverGroup.Wait()
  68. if err != nil {
  69. return errors.Trace(err)
  70. }
  71. return nil
  72. })
  73. // client
  74. testGroup.Go(func() error {
  75. ctx, cancelFunc := context.WithTimeout(
  76. context.Background(), 1*time.Second)
  77. defer cancelFunc()
  78. packetConn, err := net.ListenPacket("udp4", "127.0.0.1:0")
  79. if err != nil {
  80. return errors.Trace(err)
  81. }
  82. obfuscationPaddingSeed, err := prng.NewSeed()
  83. if err != nil {
  84. return errors.Trace(err)
  85. }
  86. var clientHelloSeed *prng.Seed
  87. if isClientHelloRandomized(quicVersion) {
  88. clientHelloSeed, err = prng.NewSeed()
  89. if err != nil {
  90. return errors.Trace(err)
  91. }
  92. }
  93. // Dial with nonce transformer
  94. Dial(
  95. ctx,
  96. packetConn,
  97. serverAddress,
  98. serverAddress.String(),
  99. quicVersion,
  100. clientHelloSeed,
  101. obfuscationKey,
  102. obfuscationPaddingSeed,
  103. &transforms.ObfuscatorSeedTransformerParameters{
  104. TransformName: "",
  105. TransformSeed: &prng.Seed{0},
  106. TransformSpec: transforms.Spec{{"^.{24}", "ffff00000000000000000000"}},
  107. },
  108. false,
  109. )
  110. return nil
  111. })
  112. go func() {
  113. testGroup.Wait()
  114. }()
  115. <-testCtx.Done()
  116. listener.Close()
  117. err = testGroup.Wait()
  118. if err != nil {
  119. t.Errorf("goroutine failed: %s", err)
  120. }
  121. }