This commit is contained in:
世界 2022-04-16 18:03:58 +08:00
parent 12408d60a0
commit 12e645e9d2
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
7 changed files with 121 additions and 56 deletions

View file

@ -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)

View file

@ -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
}

View file

@ -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)
}
}

8
go.mod
View file

@ -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

16
go.sum
View file

@ -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=

View file

@ -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
}

View file

@ -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