Compare commits

...

25 Commits

Author SHA1 Message Date
世界
e929dde13e documentation: Update changelog 2023-07-09 07:54:08 +08:00
世界
9d75385bbb Fix async FakeIP save 2023-07-08 16:21:11 +08:00
世界
1c526feec1 Update dependencies 2023-07-08 16:19:28 +08:00
世界
7df26986de documentation: Update changelog 2023-07-07 14:23:45 +08:00
世界
5f2d23a12d Fix multi error 2023-07-07 13:57:28 +08:00
世界
d9e65c0969 Fix syscall copy packet 2023-07-07 13:42:42 +08:00
世界
ec1160924f Fix save FakeIP cache 2023-07-07 12:51:38 +08:00
世界
230e8f895d Fix close quic.Listener 2023-07-07 12:43:22 +08:00
世界
af79378734 Update dependencies 2023-07-03 21:47:32 +08:00
世界
07ce5e0d22 Remove stack buffer usage 2023-07-03 21:45:32 +08:00
世界
9c8565cf21 platform: Add group interface 2023-07-02 18:46:41 +08:00
世界
5ad0ea2b5a Try fix StreamDomainNameQuery 2023-07-02 16:38:38 +08:00
世界
e482053c8a documentation: Update changelog 2023-06-27 11:31:24 +08:00
世界
945713d886 Update dependencies 2023-06-27 11:13:30 +08:00
世界
9bb62ad6b5 Check duplicated outbound tag 2023-06-26 18:47:52 +08:00
世界
c2bda9fbde Fix DNS rewrite_ttl logic 2023-06-23 16:12:25 +08:00
世界
1d1db62a44 Prevent write packet IPv6 packet to tun IPv4 connection 2023-06-21 13:29:24 +08:00
世界
39405373f8 documentation: Update changelog 2023-06-19 14:11:41 +08:00
世界
22a7988d3f Update dependencies 2023-06-19 14:11:41 +08:00
世界
b2092fafb7 Fix ios build
Cannot use errno as method and variable due to conflict with objc
2023-06-19 14:11:40 +08:00
世界
cc7b5d8280 Unwrap 4in6 address received by client packet conn 2023-06-19 13:29:41 +08:00
世界
702d96a738 platform: Improve local DNS transport 2023-06-18 10:00:32 +08:00
世界
b9f34f1309 documentation: Update changelog 2023-06-17 12:21:18 +08:00
世界
07724a0ddd Update dependencies 2023-06-17 12:17:43 +08:00
世界
83c3454685 Update quic-go 2023-06-15 14:52:25 +08:00
53 changed files with 975 additions and 499 deletions

View File

@@ -89,8 +89,8 @@ lib:
lib_install:
go get -v -d
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.0.0-20230413023804-244d7ff07035
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.0.0-20230413023804-244d7ff07035
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.0.0-20230701084532-493ee2e45182
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.0.0-20230701084532-493ee2e45182
clean:
rm -rf bin dist sing-box

View File

@@ -31,6 +31,7 @@ type Tracker interface {
}
type OutboundGroup interface {
Outbound
Now() string
All() []string
}

View File

@@ -4,6 +4,7 @@ import (
"net/netip"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common/logger"
)
type FakeIPStore interface {
@@ -18,6 +19,7 @@ type FakeIPStorage interface {
FakeIPMetadata() *FakeIPMetadata
FakeIPSaveMetadata(metadata *FakeIPMetadata) error
FakeIPStore(address netip.Addr, domain string) error
FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger)
FakeIPLoad(address netip.Addr) (string, bool)
FakeIPReset() error
}

View File

@@ -4,12 +4,6 @@ type PreStarter interface {
PreStart() error
}
func PreStart(starter any) error {
if preService, ok := starter.(PreStarter); ok {
err := preService.PreStart()
if err != nil {
return err
}
}
return nil
type PostStarter interface {
PostStart() error
}

25
box.go
View File

@@ -211,10 +211,12 @@ func (s *Box) Start() error {
func (s *Box) preStart() error {
for serviceName, service := range s.preServices {
s.logger.Trace("pre-start ", serviceName)
err := adapter.PreStart(service)
if err != nil {
return E.Cause(err, "pre-starting ", serviceName)
if preService, isPreService := service.(adapter.PreStarter); isPreService {
s.logger.Trace("pre-start ", serviceName)
err := preService.PreStart()
if err != nil {
return E.Cause(err, "pre-starting ", serviceName)
}
}
}
err := s.startOutbounds()
@@ -249,13 +251,26 @@ func (s *Box) start() error {
return E.Cause(err, "initialize inbound/", in.Type(), "[", tag, "]")
}
}
return nil
}
func (s *Box) postStart() error {
for serviceName, service := range s.postServices {
s.logger.Trace("starting ", service)
err = service.Start()
err := service.Start()
if err != nil {
return E.Cause(err, "start ", serviceName)
}
}
for serviceName, service := range s.outbounds {
if lateService, isLateService := service.(adapter.PostStarter); isLateService {
s.logger.Trace("post-starting ", service)
err := lateService.PostStart()
if err != nil {
return E.Cause(err, "post-start ", serviceName)
}
}
}
return nil
}

View File

@@ -19,6 +19,9 @@ func (s *Box) startOutbounds() error {
} else {
outboundTag = outboundToStart.Tag()
}
if _, exists := outbounds[outboundTag]; exists {
return E.New("outbound tag ", outboundTag, " duplicated")
}
outboundTags[outboundToStart] = outboundTag
outbounds[outboundTag] = outboundToStart
}

View File

@@ -40,6 +40,7 @@ var (
sharedFlags []string
debugFlags []string
sharedTags []string
iosTags []string
debugTags []string
)
@@ -53,7 +54,8 @@ func init() {
sharedFlags = append(sharedFlags, "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid=")
debugFlags = append(debugFlags, "-X github.com/sagernet/sing-box/constant.Version="+currentTag)
sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_dhcp", "with_wireguard", "with_utls", "with_clash_api")
sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_utls", "with_clash_api")
iosTags = append(iosTags, "with_dhcp", "with_low_memory", "with_conntrack")
debugTags = append(debugTags, "debug")
}
@@ -114,7 +116,7 @@ func buildiOS() {
args = append(args, debugFlags...)
}
tags := append(sharedTags, "with_low_memory", "with_conntrack")
tags := append(sharedTags, iosTags...)
args = append(args, "-tags")
if !debugEnabled {
args = append(args, strings.Join(tags, ","))
@@ -131,7 +133,7 @@ func buildiOS() {
log.Fatal(err)
}
copyPath := filepath.Join("..", "sing-box-for-ios")
copyPath := filepath.Join("..", "sing-box-for-apple")
if rw.FileExists(copyPath) {
targetDir := filepath.Join(copyPath, "Libbox.xcframework")
targetDir, _ = filepath.Abs(targetDir)

View File

@@ -1,87 +0,0 @@
package debugio
import (
"net"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
type LogConn struct {
N.ExtendedConn
logger log.Logger
prefix string
}
func NewLogConn(conn net.Conn, logger log.Logger, prefix string) N.ExtendedConn {
return &LogConn{bufio.NewExtendedConn(conn), logger, prefix}
}
func (c *LogConn) Read(p []byte) (n int, err error) {
n, err = c.ExtendedConn.Read(p)
if n > 0 {
c.logger.Debug(c.prefix, " read ", buf.EncodeHexString(p[:n]))
}
return
}
func (c *LogConn) Write(p []byte) (n int, err error) {
c.logger.Debug(c.prefix, " write ", buf.EncodeHexString(p))
return c.ExtendedConn.Write(p)
}
func (c *LogConn) ReadBuffer(buffer *buf.Buffer) error {
err := c.ExtendedConn.ReadBuffer(buffer)
if err == nil {
c.logger.Debug(c.prefix, " read buffer ", buf.EncodeHexString(buffer.Bytes()))
}
return err
}
func (c *LogConn) WriteBuffer(buffer *buf.Buffer) error {
c.logger.Debug(c.prefix, " write buffer ", buf.EncodeHexString(buffer.Bytes()))
return c.ExtendedConn.WriteBuffer(buffer)
}
func (c *LogConn) Upstream() any {
return c.ExtendedConn
}
type LogPacketConn struct {
N.NetPacketConn
logger log.Logger
prefix string
}
func NewLogPacketConn(conn net.PacketConn, logger log.Logger, prefix string) N.NetPacketConn {
return &LogPacketConn{bufio.NewPacketConn(conn), logger, prefix}
}
func (c *LogPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
n, addr, err = c.NetPacketConn.ReadFrom(p)
if n > 0 {
c.logger.Debug(c.prefix, " read from ", addr, " ", buf.EncodeHexString(p[:n]))
}
return
}
func (c *LogPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
c.logger.Debug(c.prefix, " write to ", addr, " ", buf.EncodeHexString(p))
return c.NetPacketConn.WriteTo(p, addr)
}
func (c *LogPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
destination, err = c.NetPacketConn.ReadPacket(buffer)
if err == nil {
c.logger.Debug(c.prefix, " read packet from ", destination, " ", buf.EncodeHexString(buffer.Bytes()))
}
return
}
func (c *LogPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
c.logger.Debug(c.prefix, " write packet to ", destination, " ", buf.EncodeHexString(buffer.Bytes()))
return c.NetPacketConn.WritePacket(buffer, destination)
}

View File

@@ -1,19 +0,0 @@
package debugio
import (
"fmt"
"reflect"
"github.com/sagernet/sing/common"
)
func PrintUpstream(obj any) {
for obj != nil {
fmt.Println(reflect.TypeOf(obj))
if u, ok := obj.(common.WithUpstream); !ok {
break
} else {
obj = u.Upstream()
}
}
}

View File

@@ -1,48 +0,0 @@
package debugio
import (
"net"
"sync"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
N "github.com/sagernet/sing/common/network"
)
type RaceConn struct {
N.ExtendedConn
readAccess sync.Mutex
writeAccess sync.Mutex
}
func NewRaceConn(conn net.Conn) N.ExtendedConn {
return &RaceConn{ExtendedConn: bufio.NewExtendedConn(conn)}
}
func (c *RaceConn) Read(p []byte) (n int, err error) {
c.readAccess.Lock()
defer c.readAccess.Unlock()
return c.ExtendedConn.Read(p)
}
func (c *RaceConn) Write(p []byte) (n int, err error) {
c.writeAccess.Lock()
defer c.writeAccess.Unlock()
return c.ExtendedConn.Write(p)
}
func (c *RaceConn) ReadBuffer(buffer *buf.Buffer) error {
c.readAccess.Lock()
defer c.readAccess.Unlock()
return c.ExtendedConn.ReadBuffer(buffer)
}
func (c *RaceConn) WriteBuffer(buffer *buf.Buffer) error {
c.writeAccess.Lock()
defer c.writeAccess.Unlock()
return c.ExtendedConn.WriteBuffer(buffer)
}
func (c *RaceConn) Upstream() any {
return c.ExtendedConn
}

View File

@@ -128,13 +128,6 @@ func (c *slowOpenConn) NeedHandshake() bool {
return c.conn == nil
}
func (c *slowOpenConn) ReadFrom(r io.Reader) (n int64, err error) {
if c.conn != nil {
return bufio.Copy(c.conn, r)
}
return bufio.ReadFrom0(c, r)
}
func (c *slowOpenConn) WriteTo(w io.Writer) (n int64, err error) {
if c.conn == nil {
select {

View File

@@ -15,7 +15,6 @@ import (
"unicode"
"unsafe"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
N "github.com/sagernet/sing/common/network"
@@ -82,9 +81,7 @@ func resolveSocketByNetlink(network string, source netip.AddrPort, destination n
return 0, 0, E.Cause(err, "write netlink request")
}
_buffer := buf.StackNew()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.New()
defer buffer.Release()
n, err := syscall.Read(socket, buffer.FreeBytes())

View File

@@ -26,9 +26,7 @@ func StreamDomainNameQuery(readCtx context.Context, reader io.Reader) (*adapter.
if length == 0 {
return nil, os.ErrInvalid
}
_buffer := buf.StackNewSize(int(length))
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(int(length))
defer buffer.Release()
readCtx, cancel := context.WithTimeout(readCtx, time.Millisecond*100)

View File

@@ -10,6 +10,7 @@ import (
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/x/list"
)
type History struct {
@@ -20,6 +21,7 @@ type History struct {
type HistoryStorage struct {
access sync.RWMutex
delayHistory map[string]*History
callbacks list.List[func()]
}
func NewHistoryStorage() *HistoryStorage {
@@ -28,6 +30,18 @@ func NewHistoryStorage() *HistoryStorage {
}
}
func (s *HistoryStorage) AddListener(listener func()) *list.Element[func()] {
s.access.Lock()
defer s.access.Unlock()
return s.callbacks.PushBack(listener)
}
func (s *HistoryStorage) RemoveListener(element *list.Element[func()]) {
s.access.Lock()
defer s.access.Unlock()
s.callbacks.Remove(element)
}
func (s *HistoryStorage) LoadURLTestHistory(tag string) *History {
if s == nil {
return nil
@@ -39,14 +53,24 @@ func (s *HistoryStorage) LoadURLTestHistory(tag string) *History {
func (s *HistoryStorage) DeleteURLTestHistory(tag string) {
s.access.Lock()
defer s.access.Unlock()
delete(s.delayHistory, tag)
s.access.Unlock()
s.notifyUpdated()
}
func (s *HistoryStorage) StoreURLTestHistory(tag string, history *History) {
s.access.Lock()
defer s.access.Unlock()
s.delayHistory[tag] = history
s.access.Unlock()
s.notifyUpdated()
}
func (s *HistoryStorage) notifyUpdated() {
s.access.RLock()
defer s.access.RUnlock()
for element := s.callbacks.Front(); element != nil; element = element.Next() {
element.Value()
}
}
func URLTest(ctx context.Context, link string, detour N.Dialer) (t uint16, err error) {

View File

@@ -1,3 +1,59 @@
#### 1.3.1-beta.2
* Fix bugs and update dependencies
#### 1.3.1-beta.1
* Fixes and improvements
#### 1.3.0
* Fix bugs and update dependencies
Important changes since 1.2:
* Add [FakeIP](/configuration/dns/fakeip) support **1**
* Improve multiplex **2**
* Add [DNS reverse mapping](/configuration/dns#reverse_mapping) support
* Add `rewrite_ttl` DNS rule action
* Add `store_fakeip` Clash API option
* Add multi-peer support for [WireGuard](/configuration/outbound/wireguard#peers) outbound
* Add loopback detect
* Add Clash.Meta API compatibility for Clash API
* Download Yacd-meta by default if the specified Clash `external_ui` directory is empty
* Add path and headers option for HTTP outbound
* Perform URLTest recheck after network changes
* Fix `system` tun stack for ios
* Fix network monitor for android/ios
* Update VLESS and XUDP protocol
* Make splice work with traffic statistics systems like Clash API
* Significantly reduces memory usage of idle connections
* Improve DNS caching
* Add `independent_cache` [option](/configuration/dns#independent_cache) for DNS
* Reimplemented shadowsocks client
* Add multiplex support for VLESS outbound
* Automatically add Windows firewall rules in order for the system tun stack to work
* Fix TLS 1.2 support for shadow-tls client
* Add `cache_id` [option](/configuration/experimental#cache_id) for Clash cache file
* Fix `local` DNS transport for Android
*1*:
See [FAQ](/faq/fakeip) for more information.
*2*:
Added new `h2mux` multiplex protocol and `padding` multiplex option, see [Multiplex](/configuration/shared/multiplex).
#### 1.3-rc2
* Fix `local` DNS transport for Android
* Fix bugs and update dependencies
#### 1.3-rc1
* Fix bugs and update dependencies
#### 1.3-beta14
* Fixes and improvements

View File

@@ -1,7 +1,9 @@
package cachefile
import (
"net/netip"
"os"
"sync"
"time"
"github.com/sagernet/sing-box/adapter"
@@ -14,8 +16,10 @@ var bucketSelected = []byte("selected")
var _ adapter.ClashCacheFile = (*CacheFile)(nil)
type CacheFile struct {
DB *bbolt.DB
cacheID []byte
DB *bbolt.DB
cacheID []byte
saveAccess sync.RWMutex
saveCache map[netip.Addr]string
}
func Open(path string, cacheID string) (*CacheFile, error) {
@@ -36,7 +40,11 @@ func Open(path string, cacheID string) (*CacheFile, error) {
if cacheID != "" {
cacheIDBytes = append([]byte{0}, []byte(cacheID)...)
}
return &CacheFile{db, cacheIDBytes}, nil
return &CacheFile{
DB: db,
cacheID: cacheIDBytes,
saveCache: make(map[netip.Addr]string),
}, nil
}
func (c *CacheFile) bucket(t *bbolt.Tx, key []byte) *bbolt.Bucket {

View File

@@ -5,6 +5,7 @@ import (
"os"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing/common/logger"
"go.etcd.io/bbolt"
)
@@ -57,7 +58,28 @@ func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {
})
}
func (c *CacheFile) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) {
c.saveAccess.Lock()
c.saveCache[address] = domain
c.saveAccess.Unlock()
go func() {
err := c.FakeIPStore(address, domain)
if err != nil {
logger.Warn("save FakeIP address pair: ", err)
}
c.saveAccess.Lock()
delete(c.saveCache, address)
c.saveAccess.Unlock()
}()
}
func (c *CacheFile) FakeIPLoad(address netip.Addr) (string, bool) {
c.saveAccess.RLock()
cachedDomain, cached := c.saveCache[address]
c.saveAccess.RUnlock()
if cached {
return cachedDomain, true
}
var domain string
_ = c.DB.View(func(tx *bbolt.Tx) error {
bucket := tx.Bucket(bucketFakeIP)

View File

@@ -23,6 +23,7 @@ import (
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/filemanager"
"github.com/sagernet/websocket"
@@ -68,13 +69,16 @@ func NewServer(ctx context.Context, router adapter.Router, logFactory log.Observ
Handler: chiRouter,
},
trafficManager: trafficManager,
urlTestHistory: urltest.NewHistoryStorage(),
mode: strings.ToLower(options.DefaultMode),
storeSelected: options.StoreSelected,
storeFakeIP: options.StoreFakeIP,
externalUIDownloadURL: options.ExternalUIDownloadURL,
externalUIDownloadDetour: options.ExternalUIDownloadDetour,
}
server.urlTestHistory = service.PtrFromContext[urltest.HistoryStorage](ctx)
if server.urlTestHistory == nil {
server.urlTestHistory = urltest.NewHistoryStorage()
}
if server.mode == "" {
server.mode = "rule"
}

View File

@@ -3,7 +3,9 @@ package libbox
const (
CommandLog int32 = iota
CommandStatus
CommandServiceStop
CommandServiceReload
CommandCloseConnections
CommandGroup
CommandSelectOutbound
CommandURLTest
)

View File

@@ -26,6 +26,13 @@ type CommandClientHandler interface {
Disconnected(message string)
WriteLog(message string)
WriteStatus(message *StatusMessage)
WriteGroups(message OutboundGroupIterator)
}
func NewStandaloneCommandClient(sharedDirectory string) *CommandClient {
return &CommandClient{
sharedDirectory: sharedDirectory,
}
}
func NewCommandClient(sharedDirectory string, handler CommandClientHandler, options *CommandClientOptions) *CommandClient {
@@ -36,16 +43,16 @@ func NewCommandClient(sharedDirectory string, handler CommandClientHandler, opti
}
}
func clientConnect(sharedDirectory string) (net.Conn, error) {
func (c *CommandClient) directConnect() (net.Conn, error) {
return net.DialUnix("unix", nil, &net.UnixAddr{
Name: filepath.Join(sharedDirectory, "command.sock"),
Name: filepath.Join(c.sharedDirectory, "command.sock"),
Net: "unix",
})
}
func (c *CommandClient) Connect() error {
common.Close(c.conn)
conn, err := clientConnect(c.sharedDirectory)
conn, err := c.directConnect()
if err != nil {
return err
}
@@ -65,6 +72,13 @@ func (c *CommandClient) Connect() error {
}
c.handler.Connected()
go c.handleStatusConn(conn)
case CommandGroup:
err = binary.Write(conn, binary.BigEndian, c.options.StatusInterval)
if err != nil {
return E.Cause(err, "write interval")
}
c.handler.Connected()
go c.handleGroupConn(conn)
}
return nil
}

View File

@@ -9,8 +9,8 @@ import (
"github.com/sagernet/sing-box/common/dialer/conntrack"
)
func ClientCloseConnections(sharedDirectory string) error {
conn, err := clientConnect(sharedDirectory)
func (c *CommandClient) CloseConnections() error {
conn, err := c.directConnect()
if err != nil {
return err
}

View File

@@ -0,0 +1,228 @@
package libbox
import (
"encoding/binary"
"io"
"net"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-box/outbound"
"github.com/sagernet/sing/common/rw"
"github.com/sagernet/sing/service"
)
type OutboundGroup struct {
Tag string
Type string
Selectable bool
Selected string
items []*OutboundGroupItem
}
func (g *OutboundGroup) GetItems() OutboundGroupItemIterator {
return newIterator(g.items)
}
type OutboundGroupIterator interface {
Next() *OutboundGroup
HasNext() bool
}
type OutboundGroupItem struct {
Tag string
Type string
URLTestTime int64
URLTestDelay int32
}
type OutboundGroupItemIterator interface {
Next() *OutboundGroupItem
HasNext() bool
}
func (c *CommandClient) handleGroupConn(conn net.Conn) {
defer conn.Close()
for {
groups, err := readGroups(conn)
if err != nil {
c.handler.Disconnected(err.Error())
return
}
c.handler.WriteGroups(groups)
}
}
func (s *CommandServer) handleGroupConn(conn net.Conn) error {
defer conn.Close()
ctx := connKeepAlive(conn)
for {
service := s.service
if service != nil {
err := writeGroups(conn, service)
if err != nil {
return err
}
} else {
err := binary.Write(conn, binary.BigEndian, uint16(0))
if err != nil {
return err
}
}
select {
case <-ctx.Done():
return ctx.Err()
case <-s.urlTestUpdate:
}
}
}
func readGroups(reader io.Reader) (OutboundGroupIterator, error) {
var groupLength uint16
err := binary.Read(reader, binary.BigEndian, &groupLength)
if err != nil {
return nil, err
}
groups := make([]*OutboundGroup, 0, groupLength)
for i := 0; i < int(groupLength); i++ {
var group OutboundGroup
group.Tag, err = rw.ReadVString(reader)
if err != nil {
return nil, err
}
group.Type, err = rw.ReadVString(reader)
if err != nil {
return nil, err
}
err = binary.Read(reader, binary.BigEndian, &group.Selectable)
if err != nil {
return nil, err
}
group.Selected, err = rw.ReadVString(reader)
if err != nil {
return nil, err
}
var itemLength uint16
err = binary.Read(reader, binary.BigEndian, &itemLength)
if err != nil {
return nil, err
}
group.items = make([]*OutboundGroupItem, itemLength)
for j := 0; j < int(itemLength); j++ {
var item OutboundGroupItem
item.Tag, err = rw.ReadVString(reader)
if err != nil {
return nil, err
}
item.Type, err = rw.ReadVString(reader)
if err != nil {
return nil, err
}
err = binary.Read(reader, binary.BigEndian, &item.URLTestTime)
if err != nil {
return nil, err
}
err = binary.Read(reader, binary.BigEndian, &item.URLTestDelay)
if err != nil {
return nil, err
}
group.items[j] = &item
}
groups = append(groups, &group)
}
return newIterator(groups), nil
}
func writeGroups(writer io.Writer, boxService *BoxService) error {
historyStorage := service.PtrFromContext[urltest.HistoryStorage](boxService.ctx)
outbounds := boxService.instance.Router().Outbounds()
var iGroups []adapter.OutboundGroup
for _, it := range outbounds {
if group, isGroup := it.(adapter.OutboundGroup); isGroup {
iGroups = append(iGroups, group)
}
}
var groups []OutboundGroup
for _, iGroup := range iGroups {
var group OutboundGroup
group.Tag = iGroup.Tag()
group.Type = iGroup.Type()
_, group.Selectable = iGroup.(*outbound.Selector)
group.Selected = iGroup.Now()
for _, itemTag := range iGroup.All() {
itemOutbound, isLoaded := boxService.instance.Router().Outbound(itemTag)
if !isLoaded {
continue
}
var item OutboundGroupItem
item.Tag = itemTag
item.Type = itemOutbound.Type()
if history := historyStorage.LoadURLTestHistory(adapter.OutboundTag(itemOutbound)); history != nil {
item.URLTestTime = history.Time.Unix()
item.URLTestDelay = int32(history.Delay)
}
group.items = append(group.items, &item)
}
groups = append(groups, group)
}
err := binary.Write(writer, binary.BigEndian, uint16(len(groups)))
if err != nil {
return err
}
for _, group := range groups {
err = rw.WriteVString(writer, group.Tag)
if err != nil {
return err
}
err = rw.WriteVString(writer, group.Type)
if err != nil {
return err
}
err = binary.Write(writer, binary.BigEndian, group.Selectable)
if err != nil {
return err
}
err = rw.WriteVString(writer, group.Selected)
if err != nil {
return err
}
err = binary.Write(writer, binary.BigEndian, uint16(len(group.items)))
if err != nil {
return err
}
for _, item := range group.items {
err = rw.WriteVString(writer, item.Tag)
if err != nil {
return err
}
err = rw.WriteVString(writer, item.Type)
if err != nil {
return err
}
err = binary.Write(writer, binary.BigEndian, item.URLTestTime)
if err != nil {
return err
}
err = binary.Write(writer, binary.BigEndian, item.URLTestDelay)
if err != nil {
return err
}
}
}
return nil
}

View File

@@ -11,7 +11,7 @@ func (s *CommandServer) WriteMessage(message string) {
s.subscriber.Emit(message)
s.access.Lock()
s.savedLines.PushBack(message)
if s.savedLines.Len() > 100 {
if s.savedLines.Len() > s.maxLines {
s.savedLines.Remove(s.savedLines.Front())
}
s.access.Unlock()

View File

@@ -8,8 +8,8 @@ import (
"github.com/sagernet/sing/common/rw"
)
func ClientServiceReload(sharedDirectory string) error {
conn, err := clientConnect(sharedDirectory)
func (c *CommandClient) ServiceReload() error {
conn, err := c.directConnect()
if err != nil {
return err
}

View File

@@ -0,0 +1,59 @@
package libbox
import (
"encoding/binary"
"net"
"github.com/sagernet/sing-box/outbound"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
)
func (c *CommandClient) SelectOutbound(groupTag string, outboundTag string) error {
conn, err := c.directConnect()
if err != nil {
return err
}
defer conn.Close()
err = binary.Write(conn, binary.BigEndian, uint8(CommandSelectOutbound))
if err != nil {
return err
}
err = rw.WriteVString(conn, groupTag)
if err != nil {
return err
}
err = rw.WriteVString(conn, outboundTag)
if err != nil {
return err
}
return readError(conn)
}
func (s *CommandServer) handleSelectOutbound(conn net.Conn) error {
defer conn.Close()
groupTag, err := rw.ReadVString(conn)
if err != nil {
return err
}
outboundTag, err := rw.ReadVString(conn)
if err != nil {
return err
}
service := s.service
if service == nil {
return writeError(conn, E.New("service not ready"))
}
outboundGroup, isLoaded := service.instance.Router().Outbound(groupTag)
if !isLoaded {
return writeError(conn, E.New("selector not found: ", groupTag))
}
selector, isSelector := outboundGroup.(*outbound.Selector)
if !isSelector {
return writeError(conn, E.New("outbound is not a selector: ", groupTag))
}
if !selector.SelectOutbound(outboundTag) {
return writeError(conn, E.New("outbound not found in selector: ", outboundTag))
}
return writeError(conn, nil)
}

View File

@@ -7,12 +7,14 @@ import (
"path/filepath"
"sync"
"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/debug"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/observable"
"github.com/sagernet/sing/common/x/list"
"github.com/sagernet/sing/service"
)
type CommandServer struct {
@@ -22,26 +24,51 @@ type CommandServer struct {
access sync.Mutex
savedLines *list.List[string]
maxLines int
subscriber *observable.Subscriber[string]
observer *observable.Observer[string]
service *BoxService
urlTestListener *list.Element[func()]
urlTestUpdate chan struct{}
}
type CommandServerHandler interface {
ServiceStop() error
ServiceReload() error
}
func NewCommandServer(sharedDirectory string, handler CommandServerHandler) *CommandServer {
func NewCommandServer(sharedDirectory string, handler CommandServerHandler, maxLines int32) *CommandServer {
server := &CommandServer{
sockPath: filepath.Join(sharedDirectory, "command.sock"),
handler: handler,
savedLines: new(list.List[string]),
subscriber: observable.NewSubscriber[string](128),
sockPath: filepath.Join(sharedDirectory, "command.sock"),
handler: handler,
savedLines: new(list.List[string]),
maxLines: int(maxLines),
subscriber: observable.NewSubscriber[string](128),
urlTestUpdate: make(chan struct{}, 1),
}
server.observer = observable.NewObserver[string](server.subscriber, 64)
return server
}
func (s *CommandServer) SetService(newService *BoxService) {
if s.service != nil && s.listener != nil {
service.PtrFromContext[urltest.HistoryStorage](s.service.ctx).RemoveListener(s.urlTestListener)
s.urlTestListener = nil
}
s.service = newService
if newService != nil {
s.urlTestListener = service.PtrFromContext[urltest.HistoryStorage](newService.ctx).AddListener(s.notifyURLTestUpdate)
}
s.notifyURLTestUpdate()
}
func (s *CommandServer) notifyURLTestUpdate() {
select {
case s.urlTestUpdate <- struct{}{}:
default:
}
}
func (s *CommandServer) Start() error {
os.Remove(s.sockPath)
listener, err := net.ListenUnix("unix", &net.UnixAddr{
@@ -92,12 +119,16 @@ func (s *CommandServer) handleConnection(conn net.Conn) error {
return s.handleLogConn(conn)
case CommandStatus:
return s.handleStatusConn(conn)
case CommandServiceStop:
return s.handleServiceStop(conn)
case CommandServiceReload:
return s.handleServiceReload(conn)
case CommandCloseConnections:
return s.handleCloseConnections(conn)
case CommandGroup:
return s.handleGroupConn(conn)
case CommandSelectOutbound:
return s.handleSelectOutbound(conn)
case CommandURLTest:
return s.handleURLTest(conn)
default:
return E.New("unknown command: ", command)
}

View File

@@ -0,0 +1,39 @@
package libbox
import (
"encoding/binary"
"io"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
)
func readError(reader io.Reader) error {
var hasError bool
err := binary.Read(reader, binary.BigEndian, &hasError)
if err != nil {
return err
}
if hasError {
errorMessage, err := rw.ReadVString(reader)
if err != nil {
return err
}
return E.New(errorMessage)
}
return nil
}
func writeError(writer io.Writer, wErr error) error {
err := binary.Write(writer, binary.BigEndian, wErr != nil)
if err != nil {
return err
}
if wErr != nil {
err = rw.WriteVString(writer, wErr.Error())
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,48 +0,0 @@
package libbox
import (
"encoding/binary"
"net"
"runtime/debug"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
)
func ClientServiceStop(sharedDirectory string) error {
conn, err := clientConnect(sharedDirectory)
if err != nil {
return err
}
defer conn.Close()
err = binary.Write(conn, binary.BigEndian, uint8(CommandServiceStop))
if err != nil {
return err
}
var hasError bool
err = binary.Read(conn, binary.BigEndian, &hasError)
if err != nil {
return err
}
if hasError {
errorMessage, err := rw.ReadVString(conn)
if err != nil {
return err
}
return E.New(errorMessage)
}
return nil
}
func (s *CommandServer) handleServiceStop(conn net.Conn) error {
rErr := s.handler.ServiceStop()
err := binary.Write(conn, binary.BigEndian, rErr != nil)
if err != nil {
return err
}
if rErr != nil {
return rw.WriteVString(conn, rErr.Error())
}
debug.FreeOSMemory()
return nil
}

View File

@@ -0,0 +1,95 @@
package libbox
import (
"encoding/binary"
"net"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-box/outbound"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/batch"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
)
func (c *CommandClient) URLTest(groupTag string) error {
conn, err := c.directConnect()
if err != nil {
return err
}
defer conn.Close()
err = binary.Write(conn, binary.BigEndian, uint8(CommandURLTest))
if err != nil {
return err
}
err = rw.WriteVString(conn, groupTag)
if err != nil {
return err
}
return readError(conn)
}
func (s *CommandServer) handleURLTest(conn net.Conn) error {
defer conn.Close()
groupTag, err := rw.ReadVString(conn)
if err != nil {
return err
}
service := s.service
if service == nil {
return nil
}
abstractOutboundGroup, isLoaded := service.instance.Router().Outbound(groupTag)
if !isLoaded {
return writeError(conn, E.New("outbound group not found: ", groupTag))
}
outboundGroup, isOutboundGroup := abstractOutboundGroup.(adapter.OutboundGroup)
if !isOutboundGroup {
return writeError(conn, E.New("outbound is not a group: ", groupTag))
}
urlTest, isURLTest := abstractOutboundGroup.(*outbound.URLTest)
if isURLTest {
go urlTest.CheckOutbounds()
} else {
var historyStorage *urltest.HistoryStorage
if clashServer := service.instance.Router().ClashServer(); clashServer != nil {
historyStorage = clashServer.HistoryStorage()
} else {
return writeError(conn, E.New("Clash API is required for URLTest on non-URLTest group"))
}
outbounds := common.Filter(common.Map(outboundGroup.All(), func(it string) adapter.Outbound {
itOutbound, _ := service.instance.Router().Outbound(it)
return itOutbound
}), func(it adapter.Outbound) bool {
if it == nil {
return false
}
_, isGroup := it.(adapter.OutboundGroup)
if isGroup {
return false
}
return true
})
b, _ := batch.New(service.ctx, batch.WithConcurrencyNum[any](10))
for _, detour := range outbounds {
outboundToTest := detour
outboundTag := outboundToTest.Tag()
b.Go(outboundTag, func() (any, error) {
t, err := urltest.URLTest(service.ctx, "", outboundToTest)
if err != nil {
historyStorage.DeleteURLTestHistory(outboundTag)
} else {
historyStorage.StoreURLTestHistory(outboundTag, &urltest.History{
Time: time.Now(),
Delay: t,
})
}
return nil, nil
})
}
}
return writeError(conn, nil)
}

162
experimental/libbox/dns.go Normal file
View File

@@ -0,0 +1,162 @@
package libbox
import (
"context"
"net/netip"
"strings"
"syscall"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/task"
mDNS "github.com/miekg/dns"
)
type LocalDNSTransport interface {
Raw() bool
Lookup(ctx *ExchangeContext, network string, domain string) error
Exchange(ctx *ExchangeContext, message []byte) error
}
func RegisterLocalDNSTransport(transport LocalDNSTransport) {
if transport == nil {
dns.RegisterTransport([]string{"local"}, dns.CreateLocalTransport)
} else {
dns.RegisterTransport([]string{"local"}, func(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
return &platformLocalDNSTransport{
iif: transport,
}, nil
})
}
}
var _ dns.Transport = (*platformLocalDNSTransport)(nil)
type platformLocalDNSTransport struct {
iif LocalDNSTransport
}
func (p *platformLocalDNSTransport) Name() string {
return "local"
}
func (p *platformLocalDNSTransport) Start() error {
return nil
}
func (p *platformLocalDNSTransport) Close() error {
return nil
}
func (p *platformLocalDNSTransport) Raw() bool {
return p.iif.Raw()
}
func (p *platformLocalDNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
messageBytes, err := message.Pack()
if err != nil {
return nil, err
}
response := &ExchangeContext{
context: ctx,
}
var responseMessage *mDNS.Msg
return responseMessage, task.Run(ctx, func() error {
err = p.iif.Exchange(response, messageBytes)
if err != nil {
return err
}
if response.error != nil {
return response.error
}
responseMessage = &response.message
return nil
})
}
func (p *platformLocalDNSTransport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
var network string
switch strategy {
case dns.DomainStrategyUseIPv4:
network = "ip4"
case dns.DomainStrategyPreferIPv6:
network = "ip6"
default:
network = "ip"
}
response := &ExchangeContext{
context: ctx,
}
var responseAddr []netip.Addr
return responseAddr, task.Run(ctx, func() error {
err := p.iif.Lookup(response, network, domain)
if err != nil {
return err
}
if response.error != nil {
return response.error
}
switch strategy {
case dns.DomainStrategyUseIPv4:
responseAddr = common.Filter(response.addresses, func(it netip.Addr) bool {
return it.Is4()
})
case dns.DomainStrategyPreferIPv6:
responseAddr = common.Filter(response.addresses, func(it netip.Addr) bool {
return it.Is6()
})
default:
responseAddr = response.addresses
}
/*if len(responseAddr) == 0 {
response.error = dns.RCodeSuccess
}*/
return nil
})
}
type Func interface {
Invoke() error
}
type ExchangeContext struct {
context context.Context
message mDNS.Msg
addresses []netip.Addr
error error
}
func (c *ExchangeContext) OnCancel(callback Func) {
go func() {
<-c.context.Done()
callback.Invoke()
}()
}
func (c *ExchangeContext) Success(result string) {
c.addresses = common.Map(common.Filter(strings.Split(result, "\n"), func(it string) bool {
return !common.IsEmpty(it)
}), func(it string) netip.Addr {
return M.ParseSocksaddrHostPort(it, 0).Unwrap().Addr
})
}
func (c *ExchangeContext) RawSuccess(result []byte) {
err := c.message.Unpack(result)
if err != nil {
c.error = E.Cause(err, "parse response")
}
}
func (c *ExchangeContext) ErrorCode(code int32) {
c.error = dns.RCodeError(code)
}
func (c *ExchangeContext) ErrnoCode(code int32) {
c.error = syscall.Errno(code)
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/sagernet/sing-box"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/process"
"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
"github.com/sagernet/sing-box/experimental/libbox/platform"
"github.com/sagernet/sing-box/option"
@@ -16,6 +17,7 @@ import (
"github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/filemanager"
)
@@ -32,6 +34,7 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
}
ctx, cancel := context.WithCancel(context.Background())
ctx = filemanager.WithDefault(ctx, sBasePath, sTempPath, sUserID, sGroupID)
ctx = service.ContextWithPtr(ctx, urltest.NewHistoryStorage())
instance, err := box.New(box.Options{
Context: ctx,
Options: options,

65
go.mod
View File

@@ -4,8 +4,8 @@ go 1.18
require (
berty.tech/go-libtor v1.0.385
github.com/Dreamacro/clash v1.16.0
github.com/caddyserver/certmagic v0.18.0
github.com/Dreamacro/clash v1.17.0
github.com/caddyserver/certmagic v0.18.2
github.com/cretz/bine v0.2.0
github.com/dustin/go-humanize v1.0.1
github.com/fsnotify/fsnotify v1.6.0
@@ -13,26 +13,26 @@ require (
github.com/go-chi/cors v1.2.1
github.com/go-chi/render v1.0.2
github.com/gofrs/uuid/v5 v5.0.0
github.com/insomniacslk/dhcp v0.0.0-20230516061539-49801966e6cb
github.com/insomniacslk/dhcp v0.0.0-20230612134759-b20c9ba983df
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/mholt/acmez v1.1.1
github.com/miekg/dns v1.1.54
github.com/mholt/acmez v1.2.0
github.com/miekg/dns v1.1.55
github.com/ooni/go-libtor v1.1.8
github.com/oschwald/maxminddb-golang v1.10.0
github.com/oschwald/maxminddb-golang v1.11.0
github.com/pires/go-proxyproto v0.7.0
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035
github.com/sagernet/gvisor v0.0.0-20230611140528-4411f7659a08
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
github.com/sagernet/gomobile v0.0.0-20230701084532-493ee2e45182
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2
github.com/sagernet/quic-go v0.0.0-20230615020047-10f05c797c02
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230509053848-d83f8fe1194c
github.com/sagernet/sing-shadowsocks2 v0.0.0-20230608022204-942fbd98f846
github.com/sagernet/sing-shadowtls v0.1.2-0.20230531025805-ebadc7615da3
github.com/sagernet/sing-tun v0.1.5-0.20230611140633-41b2639e1385
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd
github.com/sagernet/sing-vmess v0.1.7-0.20230703132834-48803e0fd8af
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2
@@ -43,26 +43,25 @@ require (
go.etcd.io/bbolt v1.3.7
go.uber.org/zap v1.24.0
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35
golang.org/x/crypto v0.9.0
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
golang.org/x/net v0.10.0
golang.org/x/sys v0.8.0
golang.org/x/crypto v0.11.0
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
golang.org/x/net v0.12.0
golang.org/x/sys v0.10.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
google.golang.org/grpc v1.55.0
google.golang.org/protobuf v1.30.0
google.golang.org/grpc v1.56.2
google.golang.org/protobuf v1.31.0
)
//replace github.com/sagernet/sing => ../sing
require (
github.com/Dreamacro/protobytes v0.0.0-20230324064118-87bc784139cd // indirect
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 // indirect
github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
@@ -70,7 +69,7 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/libdns/libdns v0.2.1 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
@@ -79,8 +78,8 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
@@ -89,12 +88,12 @@ require (
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.8.0 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
golang.org/x/tools v0.10.0 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)

154
go.sum
View File

@@ -1,16 +1,16 @@
berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
github.com/Dreamacro/clash v1.16.0 h1:Ve+8mvtsCv7ySa6f53/GOW6Tho0AFp5RNFsgQZFKcZs=
github.com/Dreamacro/clash v1.16.0/go.mod h1:ZM3UI2gqqUN7UL7L/F9aTHODTByya6sbC/WivQpaoJk=
github.com/Dreamacro/protobytes v0.0.0-20230324064118-87bc784139cd h1:ygk7IF14j4ep4H2ZyeDe3IEoMZF8JdbX851RVVa/4D8=
github.com/Dreamacro/protobytes v0.0.0-20230324064118-87bc784139cd/go.mod h1:QvmEZ/h6KXszPOr2wUFl7Zn3hfFNYdfbXwPVDTyZs6k=
github.com/Dreamacro/clash v1.17.0 h1:LWtp6KcnrCiujY58ufI8pylI+hbCBgSCsLI90EWhpi4=
github.com/Dreamacro/clash v1.17.0/go.mod h1:PtcAft7sdsK325BD6uwm8wvhOkMV3TCeED6dfZ/lnfE=
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 h1:JFnwKplz9hj8ubqYjm8HkgZS1Rvz9yW+u/XCNNTxr0k=
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158/go.mod h1:QvmEZ/h6KXszPOr2wUFl7Zn3hfFNYdfbXwPVDTyZs6k=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/caddyserver/certmagic v0.18.0 h1:L22mJES1WllfLoHUcQUy4wVO7UfOsoL5wtg/Bj7kmIw=
github.com/caddyserver/certmagic v0.18.0/go.mod h1:e0YLTnXIopZ05bBWCLzpIf1Yvk27Q90FGUmGowFRDY8=
github.com/caddyserver/certmagic v0.18.2 h1:Nj2+M+A2Ho9IF6n1wUSbra4mX1X6ALzWpul9HooprHA=
github.com/caddyserver/certmagic v0.18.2/go.mod h1:cLsgYXecH1iVUPjDXw15/1SKjZk/TK+aFfQk5FnugGQ=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -40,7 +40,6 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
@@ -55,16 +54,15 @@ github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbg
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/insomniacslk/dhcp v0.0.0-20230516061539-49801966e6cb h1:6fDKEAXwe3rsfS4khW3EZ8kEqmSiV9szhMPcDrD+Y7Q=
github.com/insomniacslk/dhcp v0.0.0-20230516061539-49801966e6cb/go.mod h1:7474bZ1YNCvarT6WFKie4kEET6J0KYRDC4XJqqXzQW4=
github.com/insomniacslk/dhcp v0.0.0-20230612134759-b20c9ba983df h1:pF1MMIzEJzJ/MyI4bXYXVYyN8CJgoQ2PPKT2z3O/Cl4=
github.com/insomniacslk/dhcp v0.0.0-20230612134759-b20c9ba983df/go.mod h1:7474bZ1YNCvarT6WFKie4kEET6J0KYRDC4XJqqXzQW4=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
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=
@@ -72,10 +70,10 @@ github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/mholt/acmez v1.1.1 h1:sYeeYd/EHVm9cSmLdWey5oW/fXFVAq5pNLjSczN2ZUg=
github.com/mholt/acmez v1.1.1/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
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/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
@@ -83,8 +81,8 @@ github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
github.com/ooni/go-libtor v1.1.8 h1:Wo3V3DVTxl5vZdxtQakqYP+DAHx7pPtAFSl1bnAa08w=
github.com/ooni/go-libtor v1.1.8/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI=
github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg=
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
github.com/oschwald/maxminddb-golang v1.11.0 h1:aSXMqYR/EPNjGE8epgqwDay+P30hCBZIveY0WZbAWh0=
github.com/oschwald/maxminddb-golang v1.11.0/go.mod h1:YmVI+H0zh3ySFR3w+oz8PCfglAFj3PuCmui13+P9zDg=
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
@@ -97,43 +95,43 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 h1:KyhtFFt1Jtp5vW2ohNvstvQffTOQ/s5vENuGXzdA+TM=
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0/go.mod h1:D4SFEOkJK+4W1v86ZhX0jPM0rAL498fyQAChqMtes/I=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035 h1:KttYh6bBhIw8Y6/Ljn7CGwC3CKZn788rzMJmeAKjY+8=
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035/go.mod h1:5YE39YkJkCcMsfq1jMKkjsrM2GfBoF9JVWnvU89hmvU=
github.com/sagernet/gvisor v0.0.0-20230611140528-4411f7659a08 h1:p1z8y0tXLCKSiJ7GbUlaYPhyEbWL8LKLMYFpVxRVsBg=
github.com/sagernet/gvisor v0.0.0-20230611140528-4411f7659a08/go.mod h1:FgbjODax/nj7J2lr7+rqe88vHs0Ts93pC9na5ZiG9wg=
github.com/sagernet/gomobile v0.0.0-20230701084532-493ee2e45182 h1:sD5g92IO15RAX2DvA4Cq3Uc7tcgqNWVi8K3VTCI6sEo=
github.com/sagernet/gomobile v0.0.0-20230701084532-493ee2e45182/go.mod h1:5YE39YkJkCcMsfq1jMKkjsrM2GfBoF9JVWnvU89hmvU=
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTSWt6hdPrARORfoYvuUczynvRLrueo=
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 h1:tztuJB+giOWNRKQEBVY2oI3PsheTooMdh+/yxemYQYY=
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32/go.mod h1:QMCkxXAC3CvBgDZVIJp43NWTuwGBScCzMLVLynjERL8=
github.com/sagernet/quic-go v0.0.0-20230615020047-10f05c797c02 h1:9S+L1n/4hbe1pCLNTZnnddSNseQda8tuSm/+uRy6p8s=
github.com/sagernet/quic-go v0.0.0-20230615020047-10f05c797c02/go.mod h1:rth94YcHJfkC4mG03JTXmv7mJsDc8MOIIqQrCtoaV4U=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab h1:9AVUIqqz/UJCgIrcJBU9mb06JXzfQ/FgEmlgdPgo2dk=
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223 h1:L4eMuM07iSHY3UCknFnuFuHoe5clZuF2Xnf2wwA6Lwc=
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 h1:X3ADfMqeGns1Q1FlXc9kaL9FwW1UM6D6tEQo8jFstpc=
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI=
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230509053848-d83f8fe1194c h1:EiQ+i4gdPpSI8D2YUlOeBZA3R1ZGi0ShSLSXoSd/13A=
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230509053848-d83f8fe1194c/go.mod h1:UJjvQGw0lyYaDGIDvUraL16fwaAEH1WFw1Y6sUcMPog=
github.com/sagernet/sing-shadowsocks2 v0.0.0-20230608022204-942fbd98f846 h1:aiEEbDyPS/IFx0V9RNa1yLdxHHegNP+q7JFpST/8D5I=
github.com/sagernet/sing-shadowsocks2 v0.0.0-20230608022204-942fbd98f846/go.mod h1:i6Eoor37Cy4JKBcelMMFfUVBNjqRYuvcqOBjUI3Zw80=
github.com/sagernet/sing-shadowtls v0.1.2-0.20230531025805-ebadc7615da3 h1:PNwJs1F+3e/iZguYQR7YzxsH8Sm0Eu7vVuHawD89r34=
github.com/sagernet/sing-shadowtls v0.1.2-0.20230531025805-ebadc7615da3/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI=
github.com/sagernet/sing-tun v0.1.5-0.20230611140633-41b2639e1385 h1:iKDIJB05yHyUE57VYlamGhCEauXssIukB/xZsLmP7ic=
github.com/sagernet/sing-tun v0.1.5-0.20230611140633-41b2639e1385/go.mod h1:8amChfsau8s/hkooIVIU4uw7VavgrfHrT0KUbJo4ROc=
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U=
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U=
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7 h1:sKQu4Gc6vMfzleoFK3h8ROfn/TP2U36qQME3/iYaoqA=
github.com/sagernet/sing v0.2.8-0.20230707055657-7c9b4d624da7/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9 h1:35qe74ygIKj5uQkDDD0Xtv+iWOspQsS/Lqhs2XiY0Ak=
github.com/sagernet/sing-dns v0.1.7-0.20230703131656-fd65b6178bf9/go.mod h1:wgmbh0yruJXRO8tmfwPx6hOl6pyReWRoeHdkRehWkmw=
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90 h1:aEe2HrRc9OTS7IZ8RHyh224OhltnwRQs4/y89UsHPo8=
github.com/sagernet/sing-mux v0.1.1-0.20230703132253-2cedde0fbc90/go.mod h1:sm126rB5EUi9HLf4jCSHTqo+XRPbh4BoEVeLbr2WRbE=
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355 h1:XOgNZYnkDrx5qtNS4kqIOHMhjZuc7mJ2pY/x3EyZX8Q=
github.com/sagernet/sing-shadowsocks v0.2.3-0.20230703131347-b044960bd355/go.mod h1:atEATsxqPo8qCPcFt8Rw7TFEJ70egCoMR7PziX4jmjI=
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968 h1:UctXygnZfqsFR+2hZXfpWK3pSYKLbBQMuli9GDE6QU0=
github.com/sagernet/sing-shadowsocks2 v0.1.2-0.20230703131506-ca0c6adde968/go.mod h1:xFxUGbtnqRLxtQftCILFeKf43GE6S83f0I6CsO9BxGE=
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4 h1:ZjLyCkEENqXzGp4PRZbQGk5wPzEq0Rg+/2jK82lmy3Q=
github.com/sagernet/sing-shadowtls v0.1.3-0.20230703132509-93bbad3057e4/go.mod h1:8ZSSHJSNOG7cUCUYJemZNH873EsKdFqABykTypoS/2M=
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd h1:lkJA/P1L2XE5lNDnzA2fygx6DZIks3Sx87GN2OE0jNY=
github.com/sagernet/sing-tun v0.1.9-0.20230703134424-fd850d00e5cd/go.mod h1:XNQoXtvsmeva+dADmo/57KktLNgm5ubOyR67Niahqj8=
github.com/sagernet/sing-vmess v0.1.7-0.20230703132834-48803e0fd8af h1:NS433dd7XSieIAiR5cMK6ArhC8ILbXJul48IMLRxqhI=
github.com/sagernet/sing-vmess v0.1.7-0.20230703132834-48803e0fd8af/go.mod h1:HoYH8kt5m1RejF0KSYn+QkZ9Cg4a8LlHnV9ykaeNJu4=
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE=
@@ -160,7 +158,6 @@ github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gV
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
@@ -172,72 +169,53 @@ go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo=
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI=
google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -245,5 +223,5 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=

View File

@@ -38,9 +38,7 @@ func (a *myInboundAdapter) ListenUDP() (net.PacketConn, error) {
func (a *myInboundAdapter) loopUDPIn() {
defer close(a.packetOutboundClosed)
_buffer := buf.StackNewPacket()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewPacket()
defer buffer.Release()
buffer.IncRef()
defer buffer.DecRef()
@@ -67,9 +65,7 @@ func (a *myInboundAdapter) loopUDPIn() {
func (a *myInboundAdapter) loopUDPOOBIn() {
defer close(a.packetOutboundClosed)
_buffer := buf.StackNewPacket()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewPacket()
defer buffer.Release()
buffer.IncRef()
defer buffer.DecRef()

View File

@@ -35,7 +35,7 @@ type Hysteria struct {
xplusKey []byte
sendBPS uint64
recvBPS uint64
listener quic.Listener
listener *quic.Listener
udpAccess sync.RWMutex
udpSessionId uint32
udpSessions map[uint32]chan *hysteria.UDPMessage
@@ -332,7 +332,7 @@ func (h *Hysteria) Close() error {
h.udpAccess.Unlock()
return common.Close(
&h.myInboundAdapter,
h.listener,
common.PtrOrNil(h.listener),
h.tlsConfig,
)
}

View File

@@ -270,9 +270,7 @@ func (c *naiveH1Conn) read(p []byte) (n int, err error) {
if len(p) >= 3 {
paddingHdr = p[:3]
} else {
_paddingHdr := make([]byte, 3)
defer common.KeepAlive(_paddingHdr)
paddingHdr = common.Dup(_paddingHdr)
paddingHdr = make([]byte, 3)
}
_, err = io.ReadFull(c.Conn, paddingHdr)
if err != nil {
@@ -320,9 +318,7 @@ func (c *naiveH1Conn) write(p []byte) (n int, err error) {
if c.writePadding < kFirstPaddings {
paddingSize := rand.Intn(256)
_buffer := buf.StackNewSize(3 + len(p) + paddingSize)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(3 + len(p) + paddingSize)
defer buffer.Release()
header := buffer.Extend(3)
binary.BigEndian.PutUint16(header, uint16(len(p)))
@@ -449,9 +445,7 @@ func (c *naiveH2Conn) read(p []byte) (n int, err error) {
if len(p) >= 3 {
paddingHdr = p[:3]
} else {
_paddingHdr := make([]byte, 3)
defer common.KeepAlive(_paddingHdr)
paddingHdr = common.Dup(_paddingHdr)
paddingHdr = make([]byte, 3)
}
_, err = io.ReadFull(c.reader, paddingHdr)
if err != nil {
@@ -502,9 +496,7 @@ func (c *naiveH2Conn) write(p []byte) (n int, err error) {
if c.writePadding < kFirstPaddings {
paddingSize := rand.Intn(256)
_buffer := buf.StackNewSize(3 + len(p) + paddingSize)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(3 + len(p) + paddingSize)
defer buffer.Release()
header := buffer.Extend(3)
binary.BigEndian.PutUint16(header, uint16(len(p)))

View File

@@ -24,8 +24,9 @@ func NewFactory(formatter Formatter, writer io.Writer, platformWriter io.Writer)
return &simpleFactory{
formatter: formatter,
platformFormatter: Formatter{
BaseTime: formatter.BaseTime,
DisableColors: C.IsDarwin || C.IsIos,
BaseTime: formatter.BaseTime,
DisableColors: C.IsDarwin || C.IsIos,
DisableLineBreak: true,
},
writer: writer,
platformWriter: platformWriter,

View File

@@ -17,6 +17,7 @@ type Formatter struct {
DisableTimestamp bool
FullTimestamp bool
TimestampFormat string
DisableLineBreak bool
}
func (f Formatter) Format(ctx context.Context, level Level, tag string, message string, timestamp time.Time) string {
@@ -76,8 +77,14 @@ func (f Formatter) Format(ctx context.Context, level Level, tag string, message
default:
message = levelString + "[" + xd(int(timestamp.Sub(f.BaseTime)/time.Second), 4) + "] " + message
}
if message[len(message)-1] != '\n' {
message += "\n"
if f.DisableLineBreak {
if message[len(message)-1] != '\n' {
message = message[:len(message)-1]
}
} else {
if message[len(message)-1] != '\n' {
message += "\n"
}
}
return message
}

View File

@@ -28,8 +28,9 @@ func NewObservableFactory(formatter Formatter, writer io.Writer, platformWriter
factory := &observableFactory{
formatter: formatter,
platformFormatter: Formatter{
BaseTime: formatter.BaseTime,
DisableColors: C.IsDarwin || C.IsIos,
BaseTime: formatter.BaseTime,
DisableColors: C.IsDarwin || C.IsIos,
DisableLineBreak: true,
},
writer: writer,
platformWriter: platformWriter,

View File

@@ -5,7 +5,6 @@ import (
"net"
"net/netip"
"os"
"runtime"
"time"
"github.com/sagernet/sing-box/adapter"
@@ -112,8 +111,7 @@ func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) erro
}
}
if earlyConn, isEarlyConn := common.Cast[N.EarlyConn](serverConn); isEarlyConn && earlyConn.NeedHandshake() {
_payload := buf.StackNew()
payload := common.Dup(_payload)
payload := buf.NewPacket()
err := conn.SetReadDeadline(time.Now().Add(C.ReadPayloadTimeout))
if err != os.ErrInvalid {
if err != nil {
@@ -133,7 +131,6 @@ func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) erro
if err != nil {
return N.HandshakeFailure(conn, err)
}
runtime.KeepAlive(_payload)
payload.Release()
}
return bufio.CopyConn(ctx, conn, serverConn)

View File

@@ -65,9 +65,7 @@ func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adap
if queryLength == 0 {
return dns.RCodeFormatError
}
_buffer := buf.StackNewSize(int(queryLength))
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(int(queryLength))
defer buffer.Release()
_, err = buffer.ReadFullFrom(conn, int(queryLength))
if err != nil {
@@ -84,9 +82,7 @@ func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adap
if err != nil {
return err
}
_responseBuffer := buf.StackNewPacket()
defer common.KeepAlive(_responseBuffer)
responseBuffer := common.Dup(_responseBuffer)
responseBuffer := buf.NewPacket()
defer responseBuffer.Release()
responseBuffer.Resize(2, 0)
n, err := response.PackBuffer(responseBuffer.FreeBytes())

View File

@@ -178,7 +178,7 @@ func (h *Hysteria) offerNew(ctx context.Context) (quic.Connection, error) {
packetConn = hysteria.NewXPlusPacketConn(packetConn, h.xplusKey)
}
packetConn = &hysteria.PacketConnWrapper{PacketConn: packetConn}
quicConn, err := quic.Dial(packetConn, udpConn.RemoteAddr(), h.serverAddr.AddrString(), h.tlsConfig, h.quicConfig)
quicConn, err := quic.Dial(h.ctx, packetConn, udpConn.RemoteAddr(), h.tlsConfig, h.quicConfig)
if err != nil {
packetConn.Close()
return nil, err

View File

@@ -18,6 +18,7 @@ import (
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
)
var (
@@ -74,7 +75,11 @@ func (s *URLTest) Start() error {
outbounds = append(outbounds, detour)
}
s.group = NewURLTestGroup(s.ctx, s.router, s.logger, outbounds, s.link, s.interval, s.tolerance)
go s.group.CheckOutbounds(false)
return nil
}
func (s *URLTest) PostStart() error {
go s.CheckOutbounds()
return nil
}
@@ -96,6 +101,10 @@ func (s *URLTest) URLTest(ctx context.Context, link string) (map[string]uint16,
return s.group.URLTest(ctx, link)
}
func (s *URLTest) CheckOutbounds() {
s.group.CheckOutbounds(true)
}
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
s.group.Start()
outbound := s.group.Select(network)
@@ -157,7 +166,8 @@ func NewURLTestGroup(ctx context.Context, router adapter.Router, logger log.Logg
tolerance = 50
}
var history *urltest.HistoryStorage
if clashServer := router.ClashServer(); clashServer != nil {
if history = service.PtrFromContext[urltest.HistoryStorage](ctx); history != nil {
} else if clashServer := router.ClashServer(); clashServer != nil {
history = clashServer.HistoryStorage()
} else {
history = urltest.NewHistoryStorage()

View File

@@ -252,7 +252,7 @@ func NewRouter(
if fakeIPOptions.Inet6Range != nil {
inet6Range = fakeIPOptions.Inet6Range.Build()
}
router.fakeIPStore = fakeip.NewStore(router, inet4Range, inet6Range)
router.fakeIPStore = fakeip.NewStore(router, router.logger, inet4Range, inet6Range)
}
usePlatformDefaultInterfaceMonitor := platformInterface != nil && platformInterface.UsePlatformDefaultInterfaceMonitor()

View File

@@ -199,9 +199,7 @@ func (t *Transport) fetchServers0(ctx context.Context, iface *net.Interface) err
}
func (t *Transport) fetchServersResponse(iface *net.Interface, packetConn net.PacketConn, transactionID dhcpv4.TransactionID) error {
_buffer := buf.StackNewSize(dhcpv4.MaxMessageSize)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(dhcpv4.MaxMessageSize)
defer buffer.Release()
for {

View File

@@ -5,6 +5,7 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing/common/cache"
"github.com/sagernet/sing/common/logger"
)
var _ adapter.FakeIPStorage = (*MemoryStorage)(nil)
@@ -34,6 +35,10 @@ func (s *MemoryStorage) FakeIPStore(address netip.Addr, domain string) error {
return nil
}
func (s *MemoryStorage) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) {
s.domainCache.Store(address, domain)
}
func (s *MemoryStorage) FakeIPLoad(address netip.Addr) (string, bool) {
return s.domainCache.Load(address)
}

View File

@@ -6,12 +6,14 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-dns"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
)
var _ adapter.FakeIPStore = (*Store)(nil)
type Store struct {
router adapter.Router
logger logger.Logger
inet4Range netip.Prefix
inet6Range netip.Prefix
storage adapter.FakeIPStorage
@@ -19,9 +21,10 @@ type Store struct {
inet6Current netip.Addr
}
func NewStore(router adapter.Router, inet4Range netip.Prefix, inet6Range netip.Prefix) *Store {
func NewStore(router adapter.Router, logger logger.Logger, inet4Range netip.Prefix, inet6Range netip.Prefix) *Store {
return &Store{
router: router,
logger: logger,
inet4Range: inet4Range,
inet6Range: inet6Range,
}
@@ -92,10 +95,7 @@ func (s *Store) Create(domain string, strategy dns.DomainStrategy) (netip.Addr,
s.inet6Current = nextAddress
address = nextAddress
}
err := s.storage.FakeIPStore(address, domain)
if err != nil {
return netip.Addr{}, err
}
s.storage.FakeIPStoreAsync(address, domain, s.logger)
return address, nil
}

View File

@@ -41,9 +41,7 @@ func WriteClientHello(stream io.Writer, hello ClientHello) error {
requestLen += 8 // recvBPS
requestLen += 2 // auth len
requestLen += len(hello.Auth)
_request := buf.StackNewSize(requestLen)
defer common.KeepAlive(_request)
request := common.Dup(_request)
request := buf.NewSize(requestLen)
defer request.Release()
common.Must(
request.WriteByte(Version),
@@ -99,9 +97,7 @@ func ReadServerHello(stream io.Reader) (*ServerHello, error) {
responseLen += 8 // sendBPS
responseLen += 8 // recvBPS
responseLen += 2 // message len
_response := buf.StackNewSize(responseLen)
defer common.KeepAlive(_response)
response := common.Dup(_response)
response := buf.NewSize(responseLen)
defer response.Release()
_, err := response.ReadFullFrom(stream, responseLen)
if err != nil {
@@ -131,9 +127,7 @@ func WriteServerHello(stream io.Writer, hello ServerHello) error {
responseLen += 8 // recvBPS
responseLen += 2 // message len
responseLen += len(hello.Message)
_response := buf.StackNewSize(responseLen)
defer common.KeepAlive(_response)
response := common.Dup(_response)
response := buf.NewSize(responseLen)
defer response.Release()
if hello.OK {
common.Must(response.WriteByte(1))
@@ -185,9 +179,7 @@ func WriteClientRequest(stream io.Writer, request ClientRequest) error {
requestLen += 2 // host len
requestLen += len(request.Host)
requestLen += 2 // port
_buffer := buf.StackNewSize(requestLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(requestLen)
defer buffer.Release()
if request.UDP {
common.Must(buffer.WriteByte(1))
@@ -213,9 +205,7 @@ func ReadServerResponse(stream io.Reader) (*ServerResponse, error) {
responseLen += 1 // ok
responseLen += 4 // udp session id
responseLen += 2 // message len
_response := buf.StackNewSize(responseLen)
defer common.KeepAlive(_response)
response := common.Dup(_response)
response := buf.NewSize(responseLen)
defer response.Release()
_, err := response.ReadFullFrom(stream, responseLen)
if err != nil {
@@ -243,9 +233,7 @@ func WriteServerResponse(stream io.Writer, response ServerResponse) error {
responseLen += 4 // udp session id
responseLen += 2 // message len
responseLen += len(response.Message)
_buffer := buf.StackNewSize(responseLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(responseLen)
defer buffer.Release()
if response.OK {
common.Must(buffer.WriteByte(1))
@@ -338,12 +326,10 @@ func WriteUDPMessage(conn quic.Connection, message UDPMessage) error {
messageLen += 1 // frag count
messageLen += 2 // data len
messageLen += len(message.Data)
_buffer := buf.StackNewSize(messageLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(messageLen)
defer buffer.Release()
err := writeUDPMessage(conn, message, buffer)
if errSize, ok := err.(quic.ErrMessageToLarge); ok {
if errSize, ok := err.(quic.ErrMessageTooLarge); ok {
// need to frag
message.MsgID = uint16(rand.Intn(0xFFFF)) + 1 // msgID must be > 0 when fragCount > 1
fragMsgs := FragUDPMessage(message, int(errSize))

View File

@@ -4,7 +4,6 @@ import (
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"io"
"net"
"os"
@@ -72,17 +71,6 @@ func (c *ClientConn) WriteBuffer(buffer *buf.Buffer) error {
return nil
}
func (c *ClientConn) ReadFrom(r io.Reader) (n int64, err error) {
if !c.headerWritten {
return bufio.ReadFrom0(c, r)
}
return bufio.Copy(c.ExtendedConn, r)
}
func (c *ClientConn) WriteTo(w io.Writer) (n int64, err error) {
return bufio.Copy(w, c.ExtendedConn)
}
func (c *ClientConn) FrontHeadroom() int {
if !c.headerWritten {
return KeyLength + 5 + M.MaxSocksaddrLength
@@ -203,39 +191,18 @@ func ClientHandshakeRaw(conn net.Conn, key [KeyLength]byte, command byte, destin
func ClientHandshake(conn net.Conn, key [KeyLength]byte, destination M.Socksaddr, payload []byte) error {
headerLen := KeyLength + M.SocksaddrSerializer.AddrPortLen(destination) + 5
var header *buf.Buffer
header := buf.NewSize(headerLen + len(payload))
defer header.Release()
var writeHeader bool
if len(payload) > 0 && headerLen+len(payload) < 65535 {
buffer := buf.StackNewSize(headerLen + len(payload))
defer common.KeepAlive(buffer)
header = common.Dup(buffer)
} else {
buffer := buf.StackNewSize(headerLen)
defer common.KeepAlive(buffer)
header = common.Dup(buffer)
writeHeader = true
}
common.Must1(header.Write(key[:]))
common.Must1(header.Write(CRLF))
common.Must(header.WriteByte(CommandTCP))
common.Must(M.SocksaddrSerializer.WriteAddrPort(header, destination))
common.Must1(header.Write(CRLF))
if !writeHeader {
common.Must1(header.Write(payload))
}
common.Must1(header.Write(payload))
_, err := conn.Write(header.Bytes())
if err != nil {
return E.Cause(err, "write request")
}
if writeHeader {
_, err = conn.Write(payload)
if err != nil {
return E.Cause(err, "write payload")
}
}
return nil
}
@@ -258,14 +225,12 @@ func ClientHandshakePacket(conn net.Conn, key [KeyLength]byte, destination M.Soc
headerLen := KeyLength + 2*M.SocksaddrSerializer.AddrPortLen(destination) + 9
payloadLen := payload.Len()
var header *buf.Buffer
defer header.Release()
var writeHeader bool
if payload.Start() >= headerLen {
header = buf.With(payload.ExtendHeader(headerLen))
} else {
buffer := buf.StackNewSize(headerLen)
defer common.KeepAlive(buffer)
header = common.Dup(buffer)
header = buf.NewSize(headerLen)
defer header.Release()
writeHeader = true
}
common.Must1(header.Write(key[:]))
@@ -309,7 +274,7 @@ func ReadPacket(conn net.Conn, buffer *buf.Buffer) (M.Socksaddr, error) {
}
_, err = buffer.ReadFullFrom(conn, int(length))
return destination, err
return destination.Unwrap(), err
}
func WritePacket(conn net.Conn, buffer *buf.Buffer, destination M.Socksaddr) error {

View File

@@ -4,7 +4,6 @@ import (
"context"
"net"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/auth"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
@@ -59,7 +58,7 @@ func (s *Service[K]) UpdateUsers(userList []K, passwordList []string) error {
func (s *Service[K]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
var key [KeyLength]byte
n, err := conn.Read(common.Dup(key[:]))
n, err := conn.Read(key[:])
if err != nil {
return err
} else if n != KeyLength {

View File

@@ -75,7 +75,7 @@ func (c *Client) offerNew() (quic.Connection, error) {
}
var packetConn net.PacketConn
packetConn = bufio.NewUnbindPacketConn(udpConn)
quicConn, err := quic.Dial(packetConn, udpConn.RemoteAddr(), c.serverAddr.AddrString(), c.tlsConfig, c.quicConfig)
quicConn, err := quic.Dial(c.ctx, packetConn, udpConn.RemoteAddr(), c.tlsConfig, c.quicConfig)
if err != nil {
packetConn.Close()
return nil, err

View File

@@ -26,7 +26,7 @@ type Server struct {
handler adapter.V2RayServerTransportHandler
errorHandler E.Handler
udpListener net.PacketConn
quicListener quic.Listener
quicListener *quic.Listener
}
func NewServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig tls.ServerConfig, handler adapter.V2RayServerTransportHandler) (adapter.V2RayServerTransport, error) {
@@ -94,5 +94,5 @@ func (s *Server) streamAcceptLoop(conn quic.Connection) error {
}
func (s *Server) Close() error {
return common.Close(s.udpListener, s.quicListener)
return common.Close(s.udpListener, common.PtrOrNil(s.quicListener))
}

View File

@@ -139,9 +139,7 @@ func WriteRequest(writer io.Writer, request Request, payload []byte) error {
requestLen += vmess.AddressSerializer.AddrPortLen(request.Destination)
}
requestLen += len(payload)
_buffer := buf.StackNewSize(requestLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(requestLen)
defer buffer.Release()
common.Must(
buffer.WriteByte(Version),
@@ -239,9 +237,7 @@ func WritePacketRequest(writer io.Writer, request Request, payload []byte) error
requestLen += 2
requestLen += len(payload)
}
_buffer := buf.StackNewSize(requestLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
buffer := buf.NewSize(requestLen)
defer buffer.Release()
common.Must(
buffer.WriteByte(Version),