github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/ss2022/stream_test.go (about) 1 package ss2022 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/rand" 7 "io" 8 "net/netip" 9 "sync" 10 "testing" 11 12 "github.com/database64128/shadowsocks-go/conn" 13 "github.com/database64128/shadowsocks-go/pipe" 14 "github.com/database64128/shadowsocks-go/zerocopy" 15 ) 16 17 func testShadowStreamReadWriter(t *testing.T, ctx context.Context, allowSegmentedFixedLengthHeader bool, clientCipherConfig *ClientCipherConfig, userCipherConfig UserCipherConfig, identityCipherConfig ServerIdentityCipherConfig, userLookupMap UserLookupMap, clientInitialPayload, unsafeRequestStreamPrefix, unsafeResponseStreamPrefix []byte) { 18 pl, pr := pipe.NewDuplexPipe() 19 plo := zerocopy.SimpleDirectReadWriteCloserOpener{DirectReadWriteCloser: pl} 20 clientTargetAddr := conn.AddrFromIPPort(netip.AddrPortFrom(netip.IPv6Unspecified(), 53)) 21 c := TCPClient{ 22 rwo: &plo, 23 readOnceOrFull: readOnceOrFullFunc(allowSegmentedFixedLengthHeader), 24 cipherConfig: clientCipherConfig, 25 unsafeRequestStreamPrefix: unsafeRequestStreamPrefix, 26 unsafeResponseStreamPrefix: unsafeResponseStreamPrefix, 27 } 28 s := NewTCPServer(allowSegmentedFixedLengthHeader, userCipherConfig, identityCipherConfig, unsafeRequestStreamPrefix, unsafeResponseStreamPrefix) 29 s.ReplaceUserLookupMap(userLookupMap) 30 31 var ( 32 crw zerocopy.ReadWriter 33 srw zerocopy.ReadWriter 34 serverTargetAddr conn.Addr 35 serverInitialPayload []byte 36 cerr, serr error 37 ) 38 39 var wg sync.WaitGroup 40 wg.Add(2) 41 42 go func() { 43 _, crw, cerr = c.Dial(ctx, clientTargetAddr, clientInitialPayload) 44 wg.Done() 45 }() 46 47 go func() { 48 srw, serverTargetAddr, serverInitialPayload, _, serr = s.Accept(pr) 49 if serr == nil && len(serverInitialPayload) < len(clientInitialPayload) { 50 // Read excess payload. 51 b := make([]byte, len(clientInitialPayload)) 52 copy(b, serverInitialPayload) 53 scrw := zerocopy.NewCopyReadWriter(srw) 54 _, serr = io.ReadFull(scrw, b[len(serverInitialPayload):]) 55 serverInitialPayload = b 56 } 57 wg.Done() 58 }() 59 60 wg.Wait() 61 if cerr != nil { 62 t.Fatal(cerr) 63 } 64 if serr != nil { 65 t.Fatal(serr) 66 } 67 68 if !clientTargetAddr.Equals(serverTargetAddr) { 69 t.Errorf("Target address mismatch: c: %s, s: %s", clientTargetAddr, serverTargetAddr) 70 } 71 if !bytes.Equal(clientInitialPayload, serverInitialPayload) { 72 t.Errorf("Initial payload mismatch: c: %v, s: %v", clientInitialPayload, serverInitialPayload) 73 } 74 75 zerocopy.ReadWriterTestFunc(t, crw, srw) 76 } 77 78 func testShadowStreamReadWriterReplay(t *testing.T, ctx context.Context, clientCipherConfig *ClientCipherConfig, userCipherConfig UserCipherConfig, identityCipherConfig ServerIdentityCipherConfig, userLookupMap UserLookupMap) { 79 pl, pr := pipe.NewDuplexPipe() 80 plo := zerocopy.SimpleDirectReadWriteCloserOpener{DirectReadWriteCloser: pl} 81 clientTargetAddr := conn.AddrFromIPPort(netip.AddrPortFrom(netip.IPv6Unspecified(), 53)) 82 c := TCPClient{ 83 rwo: &plo, 84 readOnceOrFull: readOnceExpectFull, 85 cipherConfig: clientCipherConfig, 86 } 87 s := NewTCPServer(false, userCipherConfig, identityCipherConfig, nil, nil) 88 s.ReplaceUserLookupMap(userLookupMap) 89 90 var cerr, serr error 91 ctrlCh := make(chan struct{}) 92 93 // Start client. 94 go func() { 95 _, _, cerr = c.Dial(ctx, clientTargetAddr, nil) 96 close(ctrlCh) 97 }() 98 99 // Hijack client request and save it in b. 100 b := make([]byte, 1440) 101 n, err := pr.Read(b) 102 if err != nil { 103 t.Fatal(err) 104 } 105 sendFunc := func() { 106 _, err = pl.Write(b[:n]) 107 if err != nil { 108 t.Error(err) 109 } 110 } 111 112 // Ensure client success. 113 <-ctrlCh 114 if cerr != nil { 115 t.Fatal(cerr) 116 } 117 118 // Actually send the request. 119 go sendFunc() 120 121 // Start server. 122 _, _, _, _, serr = s.Accept(pr) 123 if serr != nil { 124 t.Fatal(serr) 125 } 126 127 // Send it again. 128 go sendFunc() 129 130 // Start server from replay. 131 _, _, _, _, serr = s.Accept(pr) 132 if serr != ErrRepeatedSalt { 133 t.Errorf("Expected ErrRepeatedSalt, got %v", serr) 134 } 135 } 136 137 func testShadowStreamReadWriterWithCipher(t *testing.T, ctx context.Context, clientCipherConfig *ClientCipherConfig, userCipherConfig UserCipherConfig, identityCipherConfig ServerIdentityCipherConfig, userLookupMap UserLookupMap) { 138 smallInitialPayload := make([]byte, 1024) 139 largeInitialPayload := make([]byte, 128*1024) 140 unsafeRequestStreamPrefix := make([]byte, 64) 141 unsafeResponseStreamPrefix := make([]byte, 64) 142 143 if _, err := rand.Read(smallInitialPayload); err != nil { 144 t.Fatal(err) 145 } 146 if _, err := rand.Read(largeInitialPayload); err != nil { 147 t.Fatal(err) 148 } 149 if _, err := rand.Read(unsafeRequestStreamPrefix); err != nil { 150 t.Fatal(err) 151 } 152 if _, err := rand.Read(unsafeResponseStreamPrefix); err != nil { 153 t.Fatal(err) 154 } 155 156 t.Run("NoInitialPayload", func(t *testing.T) { 157 testShadowStreamReadWriter(t, ctx, false, clientCipherConfig, userCipherConfig, identityCipherConfig, userLookupMap, nil, nil, nil) 158 }) 159 t.Run("SmallInitialPayload", func(t *testing.T) { 160 testShadowStreamReadWriter(t, ctx, false, clientCipherConfig, userCipherConfig, identityCipherConfig, userLookupMap, smallInitialPayload, nil, nil) 161 }) 162 t.Run("LargeInitialPayload", func(t *testing.T) { 163 testShadowStreamReadWriter(t, ctx, false, clientCipherConfig, userCipherConfig, identityCipherConfig, userLookupMap, largeInitialPayload, nil, nil) 164 }) 165 t.Run("UnsafeStreamPrefix", func(t *testing.T) { 166 testShadowStreamReadWriter(t, ctx, false, clientCipherConfig, userCipherConfig, identityCipherConfig, userLookupMap, nil, unsafeRequestStreamPrefix, unsafeResponseStreamPrefix) 167 }) 168 t.Run("AllowSegmentedFixedLengthHeader", func(t *testing.T) { 169 testShadowStreamReadWriter(t, ctx, true, clientCipherConfig, userCipherConfig, identityCipherConfig, userLookupMap, nil, nil, nil) 170 }) 171 172 t.Run("Replay", func(t *testing.T) { 173 testShadowStreamReadWriterReplay(t, ctx, clientCipherConfig, userCipherConfig, identityCipherConfig, userLookupMap) 174 }) 175 } 176 177 func TestShadowStreamReadWriterNoEIH(t *testing.T) { 178 ctx := context.Background() 179 clientCipherConfig128, userCipherConfig128, err := newRandomCipherConfigTupleNoEIH("2022-blake3-aes-128-gcm", false) 180 if err != nil { 181 t.Fatal(err) 182 } 183 clientCipherConfig256, userCipherConfig256, err := newRandomCipherConfigTupleNoEIH("2022-blake3-aes-256-gcm", false) 184 if err != nil { 185 t.Fatal(err) 186 } 187 188 t.Run("128", func(t *testing.T) { 189 testShadowStreamReadWriterWithCipher(t, ctx, clientCipherConfig128, userCipherConfig128, ServerIdentityCipherConfig{}, nil) 190 }) 191 t.Run("256", func(t *testing.T) { 192 testShadowStreamReadWriterWithCipher(t, ctx, clientCipherConfig256, userCipherConfig256, ServerIdentityCipherConfig{}, nil) 193 }) 194 } 195 196 func TestShadowStreamReadWriterWithEIH(t *testing.T) { 197 ctx := context.Background() 198 clientCipherConfig128, identityCipherConfig128, userLookupMap128, err := newRandomCipherConfigTupleWithEIH("2022-blake3-aes-128-gcm", false) 199 if err != nil { 200 t.Fatal(err) 201 } 202 clientCipherConfig256, identityCipherConfig256, userLookupMap256, err := newRandomCipherConfigTupleWithEIH("2022-blake3-aes-256-gcm", false) 203 if err != nil { 204 t.Fatal(err) 205 } 206 207 t.Run("128", func(t *testing.T) { 208 testShadowStreamReadWriterWithCipher(t, ctx, clientCipherConfig128, UserCipherConfig{}, identityCipherConfig128, userLookupMap128) 209 }) 210 t.Run("256", func(t *testing.T) { 211 testShadowStreamReadWriterWithCipher(t, ctx, clientCipherConfig256, UserCipherConfig{}, identityCipherConfig256, userLookupMap256) 212 }) 213 }