github.com/database64128/shadowsocks-go@v1.7.0/ss2022/stream_test.go (about)

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