github.com/mholt/caddy-l4@v0.0.0-20241104153248-ec8fae209322/modules/l4socks/socks5_matcher_test.go (about)

     1  package l4socks
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net"
     7  	"testing"
     8  
     9  	"github.com/caddyserver/caddy/v2"
    10  	"go.uber.org/zap"
    11  
    12  	"github.com/mholt/caddy-l4/layer4"
    13  )
    14  
    15  func TestSocks5Matcher_Match(t *testing.T) {
    16  	var curlSocks5Example1 = []byte{0x05, 0x02, 0x00, 0x01}
    17  	var curlSocks5Example2 = []byte{0x05, 0x03, 0x00, 0x01, 0x02}
    18  	var firefoxSocks5Example = []byte{0x05, 0x01, 0x00}
    19  
    20  	type test struct {
    21  		matcher     *Socks5Matcher
    22  		data        []byte
    23  		shouldMatch bool
    24  	}
    25  
    26  	tests := []test{
    27  		// match with defaults
    28  		{matcher: &Socks5Matcher{}, data: curlSocks5Example1, shouldMatch: true},
    29  		{matcher: &Socks5Matcher{}, data: curlSocks5Example2, shouldMatch: true},
    30  		{matcher: &Socks5Matcher{}, data: firefoxSocks5Example, shouldMatch: true},
    31  		{matcher: &Socks5Matcher{}, data: []byte("Hello World"), shouldMatch: false},
    32  
    33  		// match only no auth
    34  		{matcher: &Socks5Matcher{AuthMethods: []uint16{0}}, data: curlSocks5Example1, shouldMatch: false},
    35  		{matcher: &Socks5Matcher{AuthMethods: []uint16{0}}, data: curlSocks5Example2, shouldMatch: false},
    36  		{matcher: &Socks5Matcher{AuthMethods: []uint16{0}}, data: firefoxSocks5Example, shouldMatch: true},
    37  
    38  		// match custom auth
    39  		{matcher: &Socks5Matcher{AuthMethods: []uint16{129}}, data: curlSocks5Example1, shouldMatch: false},
    40  		{matcher: &Socks5Matcher{AuthMethods: []uint16{129}}, data: firefoxSocks5Example, shouldMatch: false},
    41  		{matcher: &Socks5Matcher{AuthMethods: []uint16{129}}, data: []byte{0x05, 0x01, 0x81}, shouldMatch: true},
    42  	}
    43  
    44  	ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
    45  	defer cancel()
    46  
    47  	for i, tc := range tests {
    48  		func() {
    49  			err := tc.matcher.Provision(ctx)
    50  			assertNoError(t, err)
    51  
    52  			in, out := net.Pipe()
    53  			defer func() {
    54  				_, _ = io.Copy(io.Discard, out)
    55  				_ = out.Close()
    56  			}()
    57  
    58  			cx := layer4.WrapConnection(out, []byte{}, zap.NewNop())
    59  			go func() {
    60  				_, err := in.Write(tc.data)
    61  				assertNoError(t, err)
    62  				_ = in.Close()
    63  			}()
    64  
    65  			matched, err := tc.matcher.Match(cx)
    66  			assertNoError(t, err)
    67  
    68  			if matched != tc.shouldMatch {
    69  				if tc.shouldMatch {
    70  					t.Fatalf("test %d: matcher did not match | %+v\n", i, tc.matcher)
    71  				} else {
    72  					t.Fatalf("test %d: matcher should not match | %+v\n", i, tc.matcher)
    73  				}
    74  			}
    75  		}()
    76  	}
    77  }