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  }