From 3f988e077d92a8beefa76e016e52eaa509a02e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Mon, 9 May 2022 17:06:39 +0800 Subject: [PATCH] Fix shadowsocks multi service --- protocol/shadowsocks/service.go | 6 -- .../shadowsocks/shadowaead_2022/protocol.go | 2 +- .../shadowsocks/shadowaead_2022/service.go | 3 +- .../shadowaead_2022/service_multi.go | 17 +++-- .../shadowaead_2022/service_multi_test.go | 73 +++++++++++++++++++ 5 files changed, 86 insertions(+), 15 deletions(-) create mode 100644 protocol/shadowsocks/shadowaead_2022/service_multi_test.go diff --git a/protocol/shadowsocks/service.go b/protocol/shadowsocks/service.go index f09e030..14716a5 100644 --- a/protocol/shadowsocks/service.go +++ b/protocol/shadowsocks/service.go @@ -21,12 +21,6 @@ type Handler interface { E.Handler } -type MultiUserService[U comparable] interface { - Service - AddUser(user U, key []byte) - RemoveUser(user U) -} - type UserContext[U comparable] struct { context.Context User U diff --git a/protocol/shadowsocks/shadowaead_2022/protocol.go b/protocol/shadowsocks/shadowaead_2022/protocol.go index 9b67374..1d5dea7 100644 --- a/protocol/shadowsocks/shadowaead_2022/protocol.go +++ b/protocol/shadowsocks/shadowaead_2022/protocol.go @@ -74,7 +74,7 @@ func New(method string, pskList [][KeySaltSize]byte, secureRNG io.Reader) (shado } if len(pskList) > 1 { - pskHash := make([]byte, len(pskList)-1*aes.BlockSize) + pskHash := make([]byte, (len(pskList)-1)*aes.BlockSize) for i, psk := range pskList { if i == 0 { continue diff --git a/protocol/shadowsocks/shadowaead_2022/service.go b/protocol/shadowsocks/shadowaead_2022/service.go index 667a987..39af8fd 100644 --- a/protocol/shadowsocks/shadowaead_2022/service.go +++ b/protocol/shadowsocks/shadowaead_2022/service.go @@ -119,7 +119,8 @@ func (s *Service) newConnection(ctx context.Context, conn net.Conn, metadata M.M return E.Cause(err, "read timestamp") } - if math.Abs(float64(time.Now().Unix()-int64(epoch))) > 30 { + diff := int(math.Abs(float64(time.Now().Unix() - int64(epoch)))) + if diff > 30 { return ErrBadTimestamp } diff --git a/protocol/shadowsocks/shadowaead_2022/service_multi.go b/protocol/shadowsocks/shadowaead_2022/service_multi.go index 81412ce..ca827ea 100644 --- a/protocol/shadowsocks/shadowaead_2022/service_multi.go +++ b/protocol/shadowsocks/shadowaead_2022/service_multi.go @@ -30,9 +30,9 @@ type MultiService[U comparable] struct { uPSKHashR map[[aes.BlockSize]byte]U } -func (s *MultiService[U]) AddUser(user U, key []byte) { +func (s *MultiService[U]) AddUser(user U, key [KeySaltSize]byte) { var uPSKHash [aes.BlockSize]byte - hash512 := blake3.Sum512(key) + hash512 := blake3.Sum512(key[:]) copy(uPSKHash[:], hash512[:]) if oldHash, loaded := s.uPSKHash[user]; loaded { @@ -42,9 +42,7 @@ func (s *MultiService[U]) AddUser(user U, key []byte) { s.uPSKHash[user] = uPSKHash s.uPSKHashR[uPSKHash] = user - var uPSK [KeySaltSize]byte - copy(uPSK[:], key) - s.uPSK[user] = uPSK + s.uPSK[user] = key } func (s *MultiService[U]) RemoveUser(user U) { @@ -55,7 +53,7 @@ func (s *MultiService[U]) RemoveUser(user U) { delete(s.uPSKHash, user) } -func NewMultiService[U comparable](method string, iPSK [KeySaltSize]byte, secureRNG io.Reader, udpTimeout int64, handler shadowsocks.Handler) (shadowsocks.MultiUserService[U], error) { +func NewMultiService[U comparable](method string, iPSK [KeySaltSize]byte, secureRNG io.Reader, udpTimeout int64, handler shadowsocks.Handler) (*MultiService[U], error) { switch method { case "2022-blake3-aes-128-gcm": case "2022-blake3-aes-256-gcm": @@ -70,6 +68,10 @@ func NewMultiService[U comparable](method string, iPSK [KeySaltSize]byte, secure s := &MultiService[U]{ Service: ss.(*Service), + + uPSK: make(map[U][KeySaltSize]byte), + uPSKHash: make(map[U][aes.BlockSize]byte), + uPSKHashR: make(map[[aes.BlockSize]byte]U), } return s, nil } @@ -266,7 +268,8 @@ process: if err != nil { goto returnErr } - if math.Abs(float64(uint64(time.Now().Unix())-epoch)) > 30 { + diff := int(math.Abs(float64(time.Now().Unix() - int64(epoch)))) + if diff > 30 { err = ErrBadTimestamp goto returnErr } diff --git a/protocol/shadowsocks/shadowaead_2022/service_multi_test.go b/protocol/shadowsocks/shadowaead_2022/service_multi_test.go new file mode 100644 index 0000000..64c41c3 --- /dev/null +++ b/protocol/shadowsocks/shadowaead_2022/service_multi_test.go @@ -0,0 +1,73 @@ +package shadowaead_2022_test + +import ( + "context" + "net" + "sync" + "testing" + + "github.com/sagernet/sing/common" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" + "github.com/sagernet/sing/common/random" + "github.com/sagernet/sing/protocol/shadowsocks/shadowaead_2022" +) + +func TestMultiService(t *testing.T) { + method := "2022-blake3-aes-128-gcm" + var iPSK [shadowaead_2022.KeySaltSize]byte + random.Default.Read(iPSK[:]) + + var wg sync.WaitGroup + + multiService, err := shadowaead_2022.NewMultiService[string](method, iPSK, random.Default, 500, &multiHandler{t, &wg}) + if err != nil { + t.Fatal(err) + } + + var uPSK [shadowaead_2022.KeySaltSize]byte + random.Default.Read(uPSK[:]) + multiService.AddUser("my user", uPSK) + + client, err := shadowaead_2022.New(method, [][shadowaead_2022.KeySaltSize]byte{iPSK, uPSK}, random.Default) + if err != nil { + t.Fatal(err) + } + wg.Add(1) + + serverConn, clientConn := net.Pipe() + defer common.Close(serverConn, clientConn) + go func() { + err := multiService.NewConnection(context.Background(), serverConn, M.Metadata{}) + if err != nil { + t.Error(err) + return + } + }() + _, err = client.DialConn(clientConn, M.ParseSocksaddr("test.com:443")) + if err != nil { + t.Fatal(err) + } + wg.Wait() +} + +type multiHandler struct { + t *testing.T + wg *sync.WaitGroup +} + +func (h *multiHandler) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { + if metadata.Destination.String() != "test.com:443" { + h.t.Error("bad destination") + } + h.wg.Done() + return nil +} + +func (h *multiHandler) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error { + return nil +} + +func (h *multiHandler) HandleError(err error) { + h.t.Error(err) +}