From 12e645e9d21188f727a371e3cc45472286b0129b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 16 Apr 2022 18:03:58 +0800 Subject: [PATCH] Fixes --- cli/geosite/main.go | 7 +- common/geosite/matcher.go | 35 ++++++++- common/trieset/domain.go | 12 +-- go.mod | 8 +- go.sum | 16 ++-- protocol/shadowsocks/shadowaead/aead.go | 76 ++++++++++++------- .../shadowsocks/shadowaead_2022/protocol.go | 23 ++++-- 7 files changed, 121 insertions(+), 56 deletions(-) diff --git a/cli/geosite/main.go b/cli/geosite/main.go index 6c7c1f5..42dfd18 100644 --- a/cli/geosite/main.go +++ b/cli/geosite/main.go @@ -162,9 +162,12 @@ find: for _, domain := range geoSite.Domain { if domain.Type == routercommon.Domain_Full { domains = append(domains, domain.Value) + } else if domain.Type == routercommon.Domain_RootDomain { + domains = append(domains, "+."+domain.Value) + } else if domain.Type == routercommon.Domain_Plain { + logrus.Warn("ignore match rule ", geoSite.CountryCode, " ", domain.Value) } else { - domains = append(domains, domain.Value) - domains = append(domains, "."+domain.Value) + domains = append(domains, "regexp:"+domain.Value) } } loaded[strings.ToLower(geoSite.CountryCode)] = common.Uniq(domains) diff --git a/common/geosite/matcher.go b/common/geosite/matcher.go index 368ecb5..50cd330 100644 --- a/common/geosite/matcher.go +++ b/common/geosite/matcher.go @@ -1,21 +1,50 @@ package geosite import ( + "regexp" + "strings" + + E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/trieset" ) type Matcher struct { - ds *trieset.DomainSet + ds *trieset.DomainSet + regex []*regexp.Regexp } func (m *Matcher) Match(domain string) bool { - return m.ds.Has(domain) + match := m.ds.Has(domain) + if match { + return match + } + if m.regex != nil { + for _, pattern := range m.regex { + match = pattern.MatchString(domain) + if match { + return match + } + } + } + return false } func NewMatcher(domains []string) (*Matcher, error) { + var regex []*regexp.Regexp + for i := range domains { + domain := domains[i] + if strings.HasPrefix(domain, "regexp:") { + domain = domain[7:] + pattern, err := regexp.Compile(domain) + if err != nil { + return nil, E.CauseF(err, "compile regex rule ", domain) + } + regex = append(regex, pattern) + } + } ds, err := trieset.New(domains) if err != nil { return nil, err } - return &Matcher{ds}, nil + return &Matcher{ds, regex}, nil } diff --git a/common/trieset/domain.go b/common/trieset/domain.go index ef01f0d..f8ce7a1 100644 --- a/common/trieset/domain.go +++ b/common/trieset/domain.go @@ -72,19 +72,19 @@ func (ds *DomainSet) has(key []byte, nodeId, bmIdx int) bool { } func New(domains []string) (*DomainSet, error) { - list := make([]string, len(domains)) + list := make([]string, 0, len(domains)) - for i, domain := range domains { - if domain == "" || domain[len(domain)-1] == '.' { - return nil, ErrInvalidDomain + for _, domain := range domains { + if domain == "" || domain[len(domain)-1] == '.' || strings.HasPrefix(domain, "regexp:") { + continue } domain = string(reverse(domain)) if strings.HasSuffix(domain, "+") { - list[i] = domain[:len(domain)-1] + list = append(list, domain[:len(domain)-1]) list = append(list, domain[:len(domain)-2]) } else { - list[i] = domain + list = append(list, domain) } } diff --git a/go.mod b/go.mod index ec988b8..90e400a 100644 --- a/go.mod +++ b/go.mod @@ -5,16 +5,16 @@ go 1.18 require ( github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.7.0 - github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c + github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb github.com/sirupsen/logrus v1.8.1 github.com/spf13/cobra v1.4.0 github.com/stretchr/testify v1.7.1 github.com/ulikunitz/xz v0.5.10 github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e github.com/v2fly/v2ray-core/v5 v5.0.3 - golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 - golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 - golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 + golang.org/x/net v0.0.0-20220412020605-290c469a71a5 + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d google.golang.org/protobuf v1.28.0 lukechampine.com/blake3 v1.1.7 diff --git a/go.sum b/go.sum index da66399..bb85b9f 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c h1:pqy40B3MQWYrza7YZXOXgl0Nf0QGFqrOC0BKae1UNAA= -github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= +github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U= +github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= @@ -58,13 +58,13 @@ github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU= github.com/v2fly/v2ray-core/v5 v5.0.3 h1:2rnJ9vZbBQ7V4upWsoUVYGoqZl4grrx8SxOReKx+jjc= github.com/v2fly/v2ray-core/v5 v5.0.3/go.mod h1:zhDdsUJcNE8LcLRA3l7fEQ6QLuveD4/OLbQM2CceSHM= -golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM= -golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3 h1:EN5+DfgmRMvRUrMGERW2gQl3Vc+Z7ZMnI/xdEpPSf0c= -golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5 h1:bRb386wvrE+oBNdF1d/Xh9mQrfQ4ecYhW5qJ5GvTGT4= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= -golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d h1:q4JksJ2n0fmbXC0Aj0eOs6E0AcPqnKglxWXWFqGD6x0= diff --git a/protocol/shadowsocks/shadowaead/aead.go b/protocol/shadowsocks/shadowaead/aead.go index ca26fcc..b700fa8 100644 --- a/protocol/shadowsocks/shadowaead/aead.go +++ b/protocol/shadowsocks/shadowaead/aead.go @@ -9,6 +9,7 @@ import ( "github.com/sagernet/sing/common/buf" ) +//https://shadowsocks.org/en/wiki/AEAD-Ciphers.html const ( MaxPacketSize = 16*1024 - 1 PacketLengthBufferSize = 2 @@ -17,7 +18,7 @@ const ( type Reader struct { upstream io.Reader cipher cipher.AEAD - data []byte + buffer []byte nonce []byte index int cached int @@ -27,11 +28,20 @@ func NewReader(upstream io.Reader, cipher cipher.AEAD, maxPacketSize int) *Reade return &Reader{ upstream: upstream, cipher: cipher, - data: make([]byte, maxPacketSize+PacketLengthBufferSize+cipher.Overhead()*2), + buffer: make([]byte, maxPacketSize+PacketLengthBufferSize+cipher.Overhead()*2), nonce: make([]byte, cipher.NonceSize()), } } +func NewRawReader(upstream io.Reader, cipher cipher.AEAD, buffer []byte, nonce []byte) *Reader { + return &Reader{ + upstream: upstream, + cipher: cipher, + buffer: buffer, + nonce: nonce, + } +} + func (r *Reader) Upstream() io.Reader { return r.upstream } @@ -46,7 +56,7 @@ func (r *Reader) SetUpstream(reader io.Reader) { func (r *Reader) WriteTo(writer io.Writer) (n int64, err error) { if r.cached > 0 { - writeN, writeErr := writer.Write(r.data[r.index : r.index+r.cached]) + writeN, writeErr := writer.Write(r.buffer[r.index : r.index+r.cached]) if writeErr != nil { return int64(writeN), writeErr } @@ -54,27 +64,27 @@ func (r *Reader) WriteTo(writer io.Writer) (n int64, err error) { } for { start := PacketLengthBufferSize + r.cipher.Overhead() - _, err = io.ReadFull(r.upstream, r.data[:start]) + _, err = io.ReadFull(r.upstream, r.buffer[:start]) if err != nil { return } - _, err = r.cipher.Open(r.data[:0], r.nonce, r.data[:start], nil) + _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:start], nil) if err != nil { return } increaseNonce(r.nonce) - length := int(binary.BigEndian.Uint16(r.data[:PacketLengthBufferSize])) + length := int(binary.BigEndian.Uint16(r.buffer[:PacketLengthBufferSize])) end := length + r.cipher.Overhead() - _, err = io.ReadFull(r.upstream, r.data[:end]) + _, err = io.ReadFull(r.upstream, r.buffer[:end]) if err != nil { return } - _, err = r.cipher.Open(r.data[:0], r.nonce, r.data[:end], nil) + _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:end], nil) if err != nil { return } increaseNonce(r.nonce) - writeN, writeErr := writer.Write(r.data[:length]) + writeN, writeErr := writer.Write(r.buffer[:length]) if writeErr != nil { return int64(writeN), writeErr } @@ -84,22 +94,22 @@ func (r *Reader) WriteTo(writer io.Writer) (n int64, err error) { func (r *Reader) Read(b []byte) (n int, err error) { if r.cached > 0 { - n = copy(b, r.data[r.index:r.index+r.cached]) + n = copy(b, r.buffer[r.index:r.index+r.cached]) r.cached -= n r.index += n return } start := PacketLengthBufferSize + r.cipher.Overhead() - _, err = io.ReadFull(r.upstream, r.data[:start]) + _, err = io.ReadFull(r.upstream, r.buffer[:start]) if err != nil { return 0, err } - _, err = r.cipher.Open(r.data[:0], r.nonce, r.data[:start], nil) + _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:start], nil) if err != nil { return 0, err } increaseNonce(r.nonce) - length := int(binary.BigEndian.Uint16(r.data[:PacketLengthBufferSize])) + length := int(binary.BigEndian.Uint16(r.buffer[:PacketLengthBufferSize])) end := length + r.cipher.Overhead() if len(b) >= end { @@ -115,16 +125,16 @@ func (r *Reader) Read(b []byte) (n int, err error) { increaseNonce(r.nonce) return length, nil } else { - _, err = io.ReadFull(r.upstream, r.data[:end]) + _, err = io.ReadFull(r.upstream, r.buffer[:end]) if err != nil { return 0, err } - _, err = r.cipher.Open(r.data[:0], r.nonce, r.data[:end], nil) + _, err = r.cipher.Open(r.buffer[:0], r.nonce, r.buffer[:end], nil) if err != nil { return 0, err } increaseNonce(r.nonce) - n = copy(b, r.data[:length]) + n = copy(b, r.buffer[:length]) r.cached = length - n r.index = n return @@ -134,21 +144,31 @@ func (r *Reader) Read(b []byte) (n int, err error) { type Writer struct { upstream io.Writer cipher cipher.AEAD - data []byte - nonce []byte maxPacketSize int + buffer []byte + nonce []byte } func NewWriter(upstream io.Writer, cipher cipher.AEAD, maxPacketSize int) *Writer { return &Writer{ upstream: upstream, cipher: cipher, - data: make([]byte, maxPacketSize+PacketLengthBufferSize+cipher.Overhead()*2), + buffer: make([]byte, maxPacketSize+PacketLengthBufferSize+cipher.Overhead()*2), nonce: make([]byte, cipher.NonceSize()), maxPacketSize: maxPacketSize, } } +func NewRawWriter(upstream io.Writer, cipher cipher.AEAD, maxPacketSize int, buffer []byte, nonce []byte) *Writer { + return &Writer{ + upstream: upstream, + cipher: cipher, + maxPacketSize: maxPacketSize, + buffer: buffer, + nonce: nonce, + } +} + func (w *Writer) Upstream() io.Writer { return w.upstream } @@ -164,16 +184,16 @@ func (w *Writer) SetWriter(writer io.Writer) { func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) { for { offset := w.cipher.Overhead() + PacketLengthBufferSize - readN, readErr := r.Read(w.data[offset : offset+w.maxPacketSize]) + readN, readErr := r.Read(w.buffer[offset : offset+w.maxPacketSize]) if readErr != nil { return 0, readErr } - binary.BigEndian.PutUint16(w.data[:PacketLengthBufferSize], uint16(readN)) - w.cipher.Seal(w.data[:0], w.nonce, w.data[:PacketLengthBufferSize], nil) + binary.BigEndian.PutUint16(w.buffer[:PacketLengthBufferSize], uint16(readN)) + w.cipher.Seal(w.buffer[:0], w.nonce, w.buffer[:PacketLengthBufferSize], nil) increaseNonce(w.nonce) - packet := w.cipher.Seal(w.data[offset:offset], w.nonce, w.data[offset:offset+readN], nil) + packet := w.cipher.Seal(w.buffer[offset:offset], w.nonce, w.buffer[offset:offset+readN], nil) increaseNonce(w.nonce) - _, err = w.upstream.Write(w.data[:offset+len(packet)]) + _, err = w.upstream.Write(w.buffer[:offset+len(packet)]) if err != nil { return } @@ -191,13 +211,13 @@ func (w *Writer) Write(p []byte) (n int, err error) { } for _, data := range buf.ForeachN(p, w.maxPacketSize) { - binary.BigEndian.PutUint16(w.data[:PacketLengthBufferSize], uint16(len(data))) - w.cipher.Seal(w.data[:0], w.nonce, w.data[:PacketLengthBufferSize], nil) + binary.BigEndian.PutUint16(w.buffer[:PacketLengthBufferSize], uint16(len(data))) + w.cipher.Seal(w.buffer[:0], w.nonce, w.buffer[:PacketLengthBufferSize], nil) increaseNonce(w.nonce) offset := w.cipher.Overhead() + PacketLengthBufferSize - packet := w.cipher.Seal(w.data[offset:offset], w.nonce, data, nil) + packet := w.cipher.Seal(w.buffer[offset:offset], w.nonce, data, nil) increaseNonce(w.nonce) - _, err = w.upstream.Write(w.data[:offset+len(packet)]) + _, err = w.upstream.Write(w.buffer[:offset+len(packet)]) if err != nil { return } diff --git a/protocol/shadowsocks/shadowaead_2022/protocol.go b/protocol/shadowsocks/shadowaead_2022/protocol.go index fad55a0..6afc0da 100644 --- a/protocol/shadowsocks/shadowaead_2022/protocol.go +++ b/protocol/shadowsocks/shadowaead_2022/protocol.go @@ -35,7 +35,18 @@ const ( PacketNonceSize = 24 MinRequestHeaderSize = 1 + 8 MinResponseHeaderSize = MinRequestHeaderSize + KeySaltSize - MaxPacketSize = 64 * 1024 + MaxPacketSize = 65535 + shadowaead.PacketLengthBufferSize + nonceSize*2 +) + +const ( + // crypto/cipher.gcmStandardNonceSize + // golang.org/x/crypto/chacha20poly1305.NonceSize + nonceSize = 12 + + // Overhead + // crypto/cipher.gcmTagSize + // golang.org/x/crypto/chacha20poly1305.Overhead + overhead = 16 ) var ( @@ -83,10 +94,10 @@ func New(method string, psk []byte, secureRNG io.Reader) (shadowsocks.Method, er } func Blake3DeriveKey(secret, salt []byte, keyLength int) []byte { - sessionKey := make([]byte, len(secret)+len(salt)) + sessionKey := make([]byte, 2*KeySaltSize) copy(sessionKey, secret) copy(sessionKey[len(secret):], salt) - outKey := make([]byte, keyLength) + outKey := buf.Make(keyLength) blake3.DeriveKey(outKey, "shadowsocks 2022 session subkey", sessionKey) return outKey } @@ -249,7 +260,8 @@ func (c *clientConn) readResponse() error { return nil } - salt := make([]byte, KeySaltSize) + _salt := make([]byte, KeySaltSize) + salt := common.Dup(_salt) _, err := io.ReadFull(c.Conn, salt) if err != nil { return err @@ -282,7 +294,8 @@ func (c *clientConn) readResponse() error { return ErrBadTimestamp } - requestSalt := make([]byte, KeySaltSize) + _requestSalt := make([]byte, KeySaltSize) + requestSalt := common.Dup(_requestSalt) _, err = io.ReadFull(reader, requestSalt) if err != nil { return err