Refine geosite

This commit is contained in:
世界 2022-04-15 19:30:31 +08:00
parent 5991cfc072
commit 12408d60a0
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
27 changed files with 739 additions and 263 deletions

View file

@ -2,11 +2,28 @@
Do you hear the people sing?
```shell
# geo resources
go install -v -trimpath -ldflags "-s -w -buildid=" ./cli/get-geoip
go install -v -trimpath -ldflags "-s -w -buildid=" ./cli/gen-geosite
### geosite
# ss-local
```shell
go install -v -trimpath -ldflags "-s -w -buildid=" ./cli/geosite
```
create from v2ray
`geosite add v2ray`
create cn only dat
`geosite add v2ray cn`
### geoip
```shell
wget 'https://github.com/Dreamacro/maxmind-geoip/releases/latest/download/Country.mmdb'
```
### ss-local
```shell
go install -v -trimpath -ldflags "-s -w -buildid=" ./cli/ss-local
```

View file

@ -1,60 +0,0 @@
package main
import (
"encoding/binary"
"io"
"net/http"
"os"
"github.com/klauspost/compress/zstd"
"github.com/sagernet/sing/common/rw"
"github.com/sirupsen/logrus"
"github.com/ulikunitz/xz"
"github.com/v2fly/v2ray-core/v5/app/router/routercommon"
"google.golang.org/protobuf/proto"
)
func main() {
response, err := http.Get("https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat.xz")
if err != nil {
logrus.Fatal(err)
}
defer response.Body.Close()
reader, err := xz.NewReader(response.Body)
if err != nil {
logrus.Fatal(err)
}
data, err := io.ReadAll(reader)
if err != nil {
logrus.Fatal(err)
}
geosite := routercommon.GeoSiteList{}
if err = proto.Unmarshal(data, &geosite); err != nil {
logrus.Fatal(err)
}
output, err := os.Create("geosite.dat")
if err != nil {
logrus.Fatal(err)
}
binary.Write(output, binary.BigEndian, byte(0)) // version
writer, _ := zstd.NewWriter(output)
rw.WriteUVariant(writer, uint64(len(geosite.Entry)))
for _, site := range geosite.Entry {
rw.WriteVString(writer, site.CountryCode)
domains := make([]string, 0, len(site.Domain))
for _, domain := range site.Domain {
if domain.Type == routercommon.Domain_Full {
domains = append(domains, domain.Value)
} else {
domains = append(domains, domain.Value)
domains = append(domains, "."+domain.Value)
}
}
rw.WriteUVariant(writer, uint64(len(domains)))
for _, domain := range domains {
rw.WriteVString(writer, domain)
}
}
writer.Close()
output.Close()
}

209
cli/geosite/main.go Normal file
View file

@ -0,0 +1,209 @@
package main
import (
"bytes"
"io/ioutil"
"os"
"strings"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/geosite"
N "github.com/sagernet/sing/common/network"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/ulikunitz/xz"
"github.com/v2fly/v2ray-core/v5/app/router/routercommon"
"google.golang.org/protobuf/proto"
)
var path string
func main() {
command := &cobra.Command{
Use: "geosite ...",
}
command.PersistentFlags().StringVarP(&path, "file", "f", "geosite.dat", "set resource path")
command.AddCommand(&cobra.Command{
Use: "list",
Short: "List codes",
PreRun: load,
Run: edit,
})
command.AddCommand(&cobra.Command{
Use: "keep",
Short: "Keep selected codes",
PreRun: load,
Run: keep,
Args: cobra.MinimumNArgs(1),
})
command.AddCommand(&cobra.Command{
Use: "add <v2ray | loyalsoldier | path | url> [code]...",
Short: "Add codes form external file or url",
PreRun: load0,
Run: add,
Args: cobra.MinimumNArgs(1),
})
if err := command.Execute(); err != nil {
logrus.Fatal(err)
}
}
var site map[string][]string
func load(cmd *cobra.Command, args []string) {
geoFile, err := os.Open(path)
if err != nil {
logrus.Fatal(E.Cause(err, "open geo resources"))
}
defer geoFile.Close()
site, err = geosite.Read(geoFile)
if err != nil {
logrus.Fatal(E.Cause(err, "read geo resources"))
}
}
func load0(cmd *cobra.Command, args []string) {
geoFile, err := os.Open(path)
if err == nil {
defer geoFile.Close()
site, err = geosite.Read(geoFile)
if err != nil {
logrus.Fatal(E.Cause(err, "read geo resources"))
}
}
site = make(map[string][]string)
}
func edit(cmd *cobra.Command, args []string) {
for code := range site {
println(strings.ToLower(code))
}
}
func keep(cmd *cobra.Command, args []string) {
kept := make(map[string][]string)
for _, code := range args {
code = strings.ToUpper(code)
if domains, exists := site[code]; exists {
kept[code] = domains
} else {
logrus.Fatal("code ", strings.ToLower(code), " do not exists!")
}
}
geoFile, err := os.Create(path)
if err != nil {
logrus.Fatal(err)
}
defer geoFile.Close()
err = geosite.Write(geoFile, kept)
if err != nil {
logrus.Fatal(err)
}
}
func add(cmd *cobra.Command, args []string) {
resource := args[0]
find:
switch resource {
case "v2ray":
for _, dir := range []string{
"/usr/share/v2ray",
"/usr/local/share/v2ray",
"/opt/share/v2ray",
} {
file := dir + "/geosite.dat"
if common.FileExists(file) {
resource = file
break find
}
}
resource = "https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat.xz"
case "loyalsoldier":
resource = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat"
}
var data []byte
var err error
if strings.HasPrefix(resource, "http://") || strings.HasPrefix(resource, "https://") {
logrus.Info("download ", resource)
data, err = N.Get(resource)
if err != nil {
logrus.Fatal(err)
}
} else {
logrus.Info("open ", resource)
file, err := os.Open(resource)
if err != nil {
logrus.Fatal(err)
}
data, err = ioutil.ReadAll(file)
file.Close()
if err != nil {
logrus.Fatal("read ", resource, ": ", err)
}
}
{
if strings.HasSuffix(resource, ".xz") {
decoder, err := xz.NewReader(bytes.NewReader(data))
if err == nil {
data, _ = ioutil.ReadAll(decoder)
}
}
}
loaded := make(map[string][]string)
{
geositeList := routercommon.GeoSiteList{}
err = proto.Unmarshal(data, &geositeList)
if err == nil {
for _, geoSite := range geositeList.Entry {
domains := make([]string, 0, len(geoSite.Domain))
for _, domain := range geoSite.Domain {
if domain.Type == routercommon.Domain_Full {
domains = append(domains, domain.Value)
} else {
domains = append(domains, domain.Value)
domains = append(domains, "."+domain.Value)
}
}
loaded[strings.ToLower(geoSite.CountryCode)] = common.Uniq(domains)
}
goto finish
}
}
{
loaded, _ = geosite.Read(bytes.NewReader(data))
}
finish:
if len(loaded) == 0 {
logrus.Fatal("unknown resource format")
}
if len(args) > 1 {
for _, code := range args[1:] {
code = strings.ToLower(code)
if domains, exists := loaded[code]; exists {
site[code] = domains
} else {
logrus.Fatal("code ", code, " do not exists!")
}
}
} else {
for code, domains := range loaded {
site[code] = domains
}
}
for code, domains := range site {
site[code] = common.Uniq(domains)
}
geoFile, err := os.Create(path)
if err != nil {
logrus.Fatal(err)
}
defer geoFile.Close()
err = geosite.Write(geoFile, site)
if err != nil {
logrus.Fatal(err)
}
logrus.Info("saved ", path)
}

View file

@ -1,27 +0,0 @@
package main
import (
"io"
"net/http"
"os"
"github.com/sirupsen/logrus"
)
func main() {
response, err := http.Get("https://github.com/Dreamacro/maxmind-geoip/releases/latest/download/Country.mmdb")
if err != nil {
logrus.Fatal(err)
}
defer response.Body.Close()
output, err := os.Create("Country.mmdb")
if err != nil {
logrus.Fatal(err)
}
defer output.Close()
_, err = io.Copy(output, response.Body)
if err != nil {
os.RemoveAll("Country.mmdb")
logrus.Fatal(err)
}
}

View file

@ -258,13 +258,18 @@ func NewLocalClient(f *flags) (*LocalClient, error) {
return nil, E.Cause(err, "geosite.dat not found")
}
geositeMatcher, err := geosite.LoadGeositeMatcher(geodata, f.Bypass)
site, err := geosite.ReadArray(geodata, f.Bypass)
if err != nil {
return nil, err
}
geositeMatcher, err := geosite.NewMatcher(site)
if err != nil {
return nil, err
}
client.Matcher = geositeMatcher
debug.FreeOSMemory()
}
debug.FreeOSMemory()
return client, nil
}

View file

@ -22,3 +22,21 @@ func GetBytes() []byte {
func PutBytes(buffer []byte) {
pool.Put(buffer)
}
func Make(size int) []byte {
var buffer []byte
if size <= 64 {
buffer = make([]byte, 64)
} else if size <= 1024 {
buffer = make([]byte, 1024)
} else if size <= 4096 {
buffer = make([]byte, 4096)
} else if size <= 16384 {
buffer = make([]byte, 16384)
} else if size <= 65535 {
buffer = make([]byte, 65535)
} else {
buffer = make([]byte, size)
}
return buffer[:size]
}

View file

@ -5,6 +5,7 @@ import (
"io"
"log"
"strings"
"unsafe"
)
func Any[T any](array []T, block func(it T) bool) bool {
@ -53,6 +54,11 @@ func Find[T any](arr []T, block func(it T) bool) T {
return defaultValue
}
func Dup[T any](obj T) T {
p := uintptr(unsafe.Pointer(&obj))
return *(*T)(unsafe.Pointer(p))
}
func Uniq[T comparable](arr []T) []T {
result := make([]T, 0, len(arr))
seen := make(map[T]struct{}, len(arr))

View file

@ -42,6 +42,9 @@ func New(message ...any) error {
}
func Cause(cause error, message string) Exception {
if cause == nil {
return nil
}
return exception{message, cause}
}

View file

@ -1,14 +1,6 @@
package geosite
import (
"bufio"
"encoding/binary"
"io"
"strings"
"github.com/klauspost/compress/zstd"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
"github.com/sagernet/sing/common/trieset"
)
@ -20,58 +12,10 @@ func (m *Matcher) Match(domain string) bool {
return m.ds.Has(domain)
}
func LoadGeositeMatcher(reader io.Reader, code string) (*Matcher, error) {
version, err := rw.ReadByte(reader)
func NewMatcher(domains []string) (*Matcher, error) {
ds, err := trieset.New(domains)
if err != nil {
return nil, err
}
if version != 0 {
return nil, E.New("bad geosite data")
}
decoder, err := zstd.NewReader(reader, zstd.WithDecoderLowmem(true), zstd.WithDecoderConcurrency(1))
if err != nil {
return nil, err
}
defer decoder.Close()
bufferedReader := bufio.NewReader(decoder)
geositeLength, err := binary.ReadUvarint(bufferedReader)
if err != nil {
return nil, err
}
for geositeLength > 0 {
geositeLength--
countryCode, err := rw.ReadVString(bufferedReader)
if err != nil {
return nil, err
}
domainLength, err := binary.ReadUvarint(bufferedReader)
if err != nil {
return nil, err
}
if strings.EqualFold(code, countryCode) {
domains := make([]string, 0, domainLength)
for domainLength > 0 {
domainLength--
domain, err := rw.ReadVString(bufferedReader)
if err != nil {
return nil, err
}
domains = append(domains, domain)
}
ds, err := trieset.New(domains)
if err != nil {
return nil, err
}
return &Matcher{ds}, nil
} else {
for domainLength > 0 {
domainLength--
_, err = rw.ReadVString(bufferedReader)
if err != nil {
return nil, err
}
}
}
}
return nil, E.New(code, " not found in geosite")
return &Matcher{ds}, nil
}

View file

@ -1,21 +0,0 @@
package geosite
import (
"os"
"testing"
)
func TestGeosite(t *testing.T) {
geosite, err := os.Open("../../geosite.dat")
if err != nil {
t.Skip("no geosite found")
return
}
matcher, err := LoadGeositeMatcher(geosite, "cn")
if err != nil {
t.Fatal(err)
}
if !matcher.Match("baidu.cn") {
t.Fatal("match failed")
}
}

238
common/geosite/metadata.go Normal file
View file

@ -0,0 +1,238 @@
package geosite
import (
"bytes"
"io"
"sort"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
)
func Write(writer io.Writer, geosite map[string][]string) error {
keys := make([]string, 0, len(geosite))
for code := range geosite {
keys = append(keys, code)
}
sort.Strings(keys)
content := &bytes.Buffer{}
index := make(map[string]int)
for _, code := range keys {
index[code] = content.Len()
for _, domain := range geosite[code] {
if err := rw.WriteVString(content, domain); err != nil {
return err
}
}
}
err := rw.WriteByte(writer, 0)
if err != nil {
return err
}
err = rw.WriteUVariant(writer, uint64(len(keys)))
if err != nil {
return err
}
for _, code := range keys {
err = rw.WriteVString(writer, code)
if err != nil {
return err
}
err = rw.WriteUVariant(writer, uint64(index[code]))
if err != nil {
return err
}
err = rw.WriteUVariant(writer, uint64(len(geosite[code])))
if err != nil {
return err
}
}
_, err = writer.Write(content.Bytes())
if err != nil {
return err
}
return nil
}
func Read(reader io.Reader, codes ...string) (map[string][]string, error) {
version, err := rw.ReadByte(reader)
if err != nil {
return nil, err
}
if version != 0 {
return nil, E.New("bad version")
}
length, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
keys := make([]string, length)
domainIndex := make(map[string]int)
domainLength := make(map[string]int)
for i := 0; i < int(length); i++ {
code, err := rw.ReadVString(reader)
if err != nil {
return nil, err
}
keys[i] = code
codeIndex, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
codeLength, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
domainIndex[code] = int(codeIndex)
domainLength[code] = int(codeLength)
}
site := make(map[string][]string)
for _, code := range keys {
if len(codes) == 0 || common.Contains(codes, code) {
domains := make([]string, domainLength[code])
for i := range domains {
domains[i], err = rw.ReadVString(reader)
if err != nil {
return nil, err
}
}
site[code] = domains
} else {
dLength := domainLength[code]
for i := 0; i < dLength; i++ {
_, err = rw.ReadVString(reader)
if err != nil {
return nil, err
}
}
}
}
return site, nil
}
func ReadSeek(reader io.ReadSeeker, codes ...string) (map[string][]string, error) {
version, err := rw.ReadByte(reader)
if err != nil {
return nil, err
}
if version != 0 {
return nil, E.New("bad version")
}
length, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
keys := make([]string, length)
domainIndex := make(map[string]int)
domainLength := make(map[string]int)
for i := 0; i < int(length); i++ {
code, err := rw.ReadVString(reader)
if err != nil {
return nil, err
}
keys[i] = code
codeIndex, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
codeLength, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
domainIndex[code] = int(codeIndex)
domainLength[code] = int(codeLength)
}
if len(codes) == 0 {
codes = keys
}
site := make(map[string][]string)
counter := &rw.ReadCounter{Reader: reader}
for _, code := range codes {
domains := make([]string, domainLength[code])
if _, exists := domainIndex[code]; !exists {
return nil, E.New("code ", code, " not exists!")
}
_, err = reader.Seek(int64(domainIndex[code])-counter.Count(), io.SeekCurrent)
if err != nil {
return nil, err
}
for i := range domains {
domains[i], err = rw.ReadVString(reader)
if err != nil {
return nil, err
}
}
site[code] = domains
}
return site, nil
}
func ReadArray(reader io.ReadSeeker, codes ...string) ([]string, error) {
version, err := rw.ReadByte(reader)
if err != nil {
return nil, err
}
if version != 0 {
return nil, E.New("bad version")
}
length, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
keys := make([]string, length)
domainIndex := make(map[string]int)
domainLength := make(map[string]int)
for i := 0; i < int(length); i++ {
code, err := rw.ReadVString(reader)
if err != nil {
return nil, err
}
keys[i] = code
codeIndex, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
codeLength, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
domainIndex[code] = int(codeIndex)
domainLength[code] = int(codeLength)
}
if len(codes) == 0 {
codes = keys
}
var domainL int
for _, code := range keys {
if _, exists := domainIndex[code]; !exists {
return nil, E.New("code ", code, " not exists!")
}
domainL += domainLength[code]
}
domains := make([]string, 0, domainL)
counter := &rw.ReadCounter{Reader: reader}
for _, code := range codes {
_, err := reader.Seek(int64(domainIndex[code])-counter.Count(), io.SeekCurrent)
if err != nil {
return nil, err
}
codeL := domainLength[code]
for i := 0; i < codeL; i++ {
domain, err := rw.ReadVString(reader)
if err != nil {
return nil, err
}
domains = append(domains, domain)
}
}
return domains, nil
}

84
common/geosite/reader.go Normal file
View file

@ -0,0 +1,84 @@
package geosite
import (
"io"
"strings"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
)
type Reader struct {
reader io.ReadSeeker
counter *rw.ReadCounter
domainIndex map[string]int
domainLength map[string]int
cache map[string][]string
}
func NewReader(reader io.ReadSeeker) (*Reader, error) {
r := &Reader{
reader: reader,
counter: &rw.ReadCounter{Reader: reader},
domainIndex: map[string]int{},
domainLength: map[string]int{},
cache: map[string][]string{},
}
version, err := rw.ReadByte(reader)
if err != nil {
return nil, err
}
if version != 0 {
return nil, E.New("bad version")
}
length, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
for i := 0; i < int(length); i++ {
code, err := rw.ReadVString(reader)
if err != nil {
return nil, err
}
domainIndex, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
domainLength, err := rw.ReadUVariant(reader)
if err != nil {
return nil, err
}
r.domainIndex[code] = int(domainIndex)
r.domainLength[code] = int(domainLength)
}
return r, nil
}
func (r *Reader) Load(code string) ([]string, error) {
code = strings.ToLower(code)
if cache, ok := r.cache[code]; ok {
return cache, nil
}
index, exists := r.domainIndex[code]
if !exists {
return nil, E.New("code ", code, " not exists!")
}
_, err := r.reader.Seek(int64(index)-r.counter.Count(), io.SeekCurrent)
if err != nil {
return nil, err
}
r.counter.Reset()
dLength := r.domainLength[code]
domains := make([]string, dLength)
for i := 0; i < dLength; i++ {
domains[i], err = rw.ReadVString(r.counter)
if err != nil {
return nil, err
}
}
r.cache[code] = domains
return domains, nil
}

7
common/lowmem/debug.go Normal file
View file

@ -0,0 +1,7 @@
//go:build debug
package lowmem
func init() {
Enabled = true
}

13
common/lowmem/free.go Normal file
View file

@ -0,0 +1,13 @@
package lowmem
import (
"runtime"
)
var Enabled = false
func Free() {
if Enabled {
runtime.GC()
}
}

12
common/network/dialer.go Normal file
View file

@ -0,0 +1,12 @@
package network
import (
"context"
"net"
)
type ContextDialer interface {
DialContext(ctx context.Context, network, address string) (net.Conn, error)
}
var SystemDialer ContextDialer = &net.Dialer{}

View file

@ -18,6 +18,15 @@ func HTTPClientWithNetwork(network string) *http.Client {
}
}
func Get(url string) ([]byte, error) {
response, err := http.Get(url)
if err != nil {
return nil, err
}
defer response.Body.Close()
return ioutil.ReadAll(response.Body)
}
func GetContext(ctx context.Context, client *http.Client, url string) ([]byte, error) {
request, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {

View file

@ -41,7 +41,7 @@ func ReadFromVar(writerVar *io.Writer, reader io.Reader) (int64, error) {
}
func CopyConn(ctx context.Context, conn net.Conn, dest net.Conn) error {
return task.Run(context.Background(), func() error {
err := task.Run(ctx, func() error {
defer CloseRead(conn)
defer CloseWrite(dest)
return common.Error(io.Copy(dest, conn))
@ -50,6 +50,9 @@ func CopyConn(ctx context.Context, conn net.Conn, dest net.Conn) error {
defer CloseWrite(conn)
return common.Error(io.Copy(conn, dest))
})
conn.Close()
dest.Close()
return err
}
func CopyPacketConn(ctx context.Context, conn net.PacketConn, outPacketConn net.PacketConn) error {

27
common/rw/count.go Normal file
View file

@ -0,0 +1,27 @@
package rw
import (
"io"
"sync/atomic"
)
type ReadCounter struct {
io.Reader
count int64
}
func (r *ReadCounter) Read(p []byte) (n int, err error) {
n, err = r.Reader.Read(p)
if n > 0 {
atomic.AddInt64(&r.count, int64(n))
}
return
}
func (r *ReadCounter) Count() int64 {
return r.count
}
func (r *ReadCounter) Reset() {
atomic.StoreInt64(&r.count, 0)
}

View file

@ -14,12 +14,12 @@ func CloseRead(conn io.Closer) error {
if closer, ok := conn.(ReadCloser); ok {
return closer.CloseRead()
}
return conn.Close()
return nil
}
func CloseWrite(conn io.Closer) error {
if closer, ok := conn.(WriteCloser); ok {
return closer.CloseWrite()
}
return conn.Close()
return nil
}

View file

@ -7,14 +7,23 @@ import (
"github.com/sagernet/sing/common"
)
type InputStream interface {
type stubByteReader struct {
io.Reader
io.ByteReader
}
type OutputStream interface {
io.Writer
io.ByteWriter
func (r stubByteReader) ReadByte() (byte, error) {
return ReadByte(r)
}
func ToByteReader(reader io.Reader) io.ByteReader {
if byteReader, ok := reader.(io.ByteReader); ok {
return byteReader
}
return &stubByteReader{reader}
}
func ReadUVariant(reader io.Reader) (uint64, error) {
return binary.ReadUvarint(ToByteReader(reader))
}
func WriteUVariant(writer io.Writer, value uint64) error {
@ -30,8 +39,8 @@ func WriteVString(writer io.Writer, value string) error {
return WriteString(writer, value)
}
func ReadVString(reader InputStream) (string, error) {
length, err := binary.ReadUvarint(reader)
func ReadVString(reader io.Reader) (string, error) {
length, err := binary.ReadUvarint(ToByteReader(reader))
if err != nil {
return "", err
}

12
debug.go Normal file
View file

@ -0,0 +1,12 @@
//go:build debug
package sing
import (
"net/http"
_ "net/http/pprof"
)
func init() {
go http.ListenAndServe(":8964", nil)
}

3
go.mod
View file

@ -3,8 +3,6 @@ module github.com/sagernet/sing
go 1.18
require (
github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41
github.com/klauspost/compress v1.15.1
github.com/openacid/low v0.1.21
github.com/oschwald/geoip2-golang v1.7.0
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c
@ -34,7 +32,6 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

57
go.sum
View file

@ -6,44 +6,20 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E=
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41 h1:Yg3n3AI7GoHnWt7dyjsLPU+TEuZfPAg0OdiA3MJUV6I=
github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A=
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0=
@ -65,13 +41,10 @@ github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c h1:pqy40B3M
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c/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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -79,49 +52,19 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA=
github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
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

@ -131,7 +131,7 @@ func (r *Reader) Read(b []byte) (n int, err error) {
}
}
type AEADWriter struct {
type Writer struct {
upstream io.Writer
cipher cipher.AEAD
data []byte
@ -139,8 +139,8 @@ type AEADWriter struct {
maxPacketSize int
}
func NewWriter(upstream io.Writer, cipher cipher.AEAD, maxPacketSize int) *AEADWriter {
return &AEADWriter{
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),
@ -149,19 +149,19 @@ func NewWriter(upstream io.Writer, cipher cipher.AEAD, maxPacketSize int) *AEADW
}
}
func (w *AEADWriter) Upstream() io.Writer {
func (w *Writer) Upstream() io.Writer {
return w.upstream
}
func (w *AEADWriter) Replaceable() bool {
func (w *Writer) Replaceable() bool {
return false
}
func (w *AEADWriter) SetWriter(writer io.Writer) {
func (w *Writer) SetWriter(writer io.Writer) {
w.upstream = writer
}
func (w *AEADWriter) ReadFrom(r io.Reader) (n int64, err error) {
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])
@ -185,7 +185,7 @@ func (w *AEADWriter) ReadFrom(r io.Reader) (n int64, err error) {
}
}
func (w *AEADWriter) Write(p []byte) (n int, err error) {
func (w *Writer) Write(p []byte) (n int, err error) {
if len(p) == 0 {
return
}

View file

@ -110,6 +110,32 @@ func (m *Method) KeyLength() int {
return m.keySaltLength
}
func (m *Method) ReadRequest(upstream io.Reader) (io.Reader, error) {
saltBuffer := buf.Make(m.keySaltLength)
salt := common.Dup(saltBuffer)
_, err := io.ReadFull(upstream, salt)
if err != nil {
return nil, E.Cause(err, "read salt")
}
if m.replayFilter != nil {
if !m.replayFilter.Check(salt) {
return nil, E.New("salt not unique")
}
}
return NewReader(upstream, m.constructor(Kdf(m.key, salt, m.keySaltLength)), MaxPacketSize), nil
}
func (m *Method) WriteResponse(upstream io.Writer) (io.Writer, error) {
saltBuffer := buf.Make(m.keySaltLength)
salt := common.Dup(saltBuffer)
common.Must1(io.ReadFull(m.secureRNG, salt))
_, err := upstream.Write(salt)
if err != nil {
return nil, err
}
return NewWriter(upstream, m.constructor(Kdf(m.key, salt, m.keySaltLength)), MaxPacketSize), nil
}
func (m *Method) DialConn(conn net.Conn, destination *M.AddrPort) (net.Conn, error) {
shadowsocksConn := &clientConn{
Conn: conn,
@ -131,19 +157,19 @@ func (m *Method) DialPacketConn(conn net.Conn) socks.PacketConn {
return &aeadPacketConn{conn, m}
}
func (m *Method) EncodePacket(key []byte, buffer *buf.Buffer) error {
cipher := m.constructor(Kdf(key, buffer.To(m.keySaltLength), m.keySaltLength))
cipher.Seal(buffer.From(m.keySaltLength)[:0], rw.ZeroBytes[:cipher.NonceSize()], buffer.From(m.keySaltLength), nil)
buffer.Extend(cipher.Overhead())
func (m *Method) EncodePacket(buffer *buf.Buffer) error {
c := m.constructor(Kdf(m.key, buffer.To(m.keySaltLength), m.keySaltLength))
c.Seal(buffer.From(m.keySaltLength)[:0], rw.ZeroBytes[:c.NonceSize()], buffer.From(m.keySaltLength), nil)
buffer.Extend(c.Overhead())
return nil
}
func (m *Method) DecodePacket(key []byte, buffer *buf.Buffer) error {
func (m *Method) DecodePacket(buffer *buf.Buffer) error {
if buffer.Len() < m.keySaltLength {
return E.New("bad packet")
}
aead := m.constructor(Kdf(key, buffer.To(m.keySaltLength), m.keySaltLength))
packet, err := aead.Open(buffer.Index(m.keySaltLength), rw.ZeroBytes[:aead.NonceSize()], buffer.From(m.keySaltLength), nil)
c := m.constructor(Kdf(m.key, buffer.To(m.keySaltLength), m.keySaltLength))
packet, err := c.Open(buffer.Index(m.keySaltLength), rw.ZeroBytes[:c.NonceSize()], buffer.From(m.keySaltLength), nil)
if err != nil {
return err
}
@ -222,7 +248,7 @@ func (c *clientConn) readResponse() error {
}
if c.method.replayFilter != nil {
if !c.method.replayFilter.Check(salt) {
return E.New("salt is not unique")
return E.New("salt not unique")
}
}
c.reader = NewReader(
@ -288,7 +314,7 @@ func (c *aeadPacketConn) WritePacket(buffer *buf.Buffer, destination *M.AddrPort
return err
}
buffer = buffer.WriteBufferAtFirst(header)
err = c.method.EncodePacket(c.method.key, buffer)
err = c.method.EncodePacket(buffer)
if err != nil {
return err
}
@ -301,7 +327,7 @@ func (c *aeadPacketConn) ReadPacket(buffer *buf.Buffer) (*M.AddrPort, error) {
return nil, err
}
buffer.Truncate(n)
err = c.method.DecodePacket(c.method.key, buffer)
err = c.method.DecodePacket(buffer)
if err != nil {
return nil, err
}

View file

@ -256,7 +256,7 @@ func (c *clientConn) readResponse() error {
}
if !c.method.replayFilter.Check(salt) {
return E.New("salt is not unique")
return E.New("salt not unique")
}
reader := shadowaead.NewReader(

View file

@ -6,6 +6,7 @@ import (
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/lowmem"
M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/sing/common/redir"
)
@ -105,6 +106,7 @@ func (l *Listener) loop() {
if hErr != nil {
l.handler.HandleError(&Error{Conn: tcpConn, Cause: hErr})
}
lowmem.Free()
}()
}
}