mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
Improve read wait interface &
Refactor Authenticator interface to struct & Update smux & Update gVisor to 20231204.0 & Update wireguard-go & Add GSO support for TUN/WireGuard
This commit is contained in:
parent
540f6ded2a
commit
f9f37f83aa
@ -1,233 +0,0 @@
|
|||||||
//go:build go1.20 && !go1.21
|
|
||||||
|
|
||||||
package badtls
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/log"
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
aTLS "github.com/sagernet/sing/common/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Conn struct {
|
|
||||||
*tls.Conn
|
|
||||||
writer N.ExtendedWriter
|
|
||||||
isHandshakeComplete *atomic.Bool
|
|
||||||
activeCall *atomic.Int32
|
|
||||||
closeNotifySent *bool
|
|
||||||
version *uint16
|
|
||||||
rand io.Reader
|
|
||||||
halfAccess *sync.Mutex
|
|
||||||
halfError *error
|
|
||||||
cipher cipher.AEAD
|
|
||||||
explicitNonceLen int
|
|
||||||
halfPtr uintptr
|
|
||||||
halfSeq []byte
|
|
||||||
halfScratchBuf []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func TryCreate(conn aTLS.Conn) aTLS.Conn {
|
|
||||||
tlsConn, ok := conn.(*tls.Conn)
|
|
||||||
if !ok {
|
|
||||||
return conn
|
|
||||||
}
|
|
||||||
badConn, err := Create(tlsConn)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("initialize badtls: ", err)
|
|
||||||
return conn
|
|
||||||
}
|
|
||||||
return badConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func Create(conn *tls.Conn) (aTLS.Conn, error) {
|
|
||||||
rawConn := reflect.Indirect(reflect.ValueOf(conn))
|
|
||||||
rawIsHandshakeComplete := rawConn.FieldByName("isHandshakeComplete")
|
|
||||||
if !rawIsHandshakeComplete.IsValid() || rawIsHandshakeComplete.Kind() != reflect.Struct {
|
|
||||||
return nil, E.New("badtls: invalid isHandshakeComplete")
|
|
||||||
}
|
|
||||||
isHandshakeComplete := (*atomic.Bool)(unsafe.Pointer(rawIsHandshakeComplete.UnsafeAddr()))
|
|
||||||
if !isHandshakeComplete.Load() {
|
|
||||||
return nil, E.New("handshake not finished")
|
|
||||||
}
|
|
||||||
rawActiveCall := rawConn.FieldByName("activeCall")
|
|
||||||
if !rawActiveCall.IsValid() || rawActiveCall.Kind() != reflect.Struct {
|
|
||||||
return nil, E.New("badtls: invalid active call")
|
|
||||||
}
|
|
||||||
activeCall := (*atomic.Int32)(unsafe.Pointer(rawActiveCall.UnsafeAddr()))
|
|
||||||
rawHalfConn := rawConn.FieldByName("out")
|
|
||||||
if !rawHalfConn.IsValid() || rawHalfConn.Kind() != reflect.Struct {
|
|
||||||
return nil, E.New("badtls: invalid half conn")
|
|
||||||
}
|
|
||||||
rawVersion := rawConn.FieldByName("vers")
|
|
||||||
if !rawVersion.IsValid() || rawVersion.Kind() != reflect.Uint16 {
|
|
||||||
return nil, E.New("badtls: invalid version")
|
|
||||||
}
|
|
||||||
version := (*uint16)(unsafe.Pointer(rawVersion.UnsafeAddr()))
|
|
||||||
rawCloseNotifySent := rawConn.FieldByName("closeNotifySent")
|
|
||||||
if !rawCloseNotifySent.IsValid() || rawCloseNotifySent.Kind() != reflect.Bool {
|
|
||||||
return nil, E.New("badtls: invalid notify")
|
|
||||||
}
|
|
||||||
closeNotifySent := (*bool)(unsafe.Pointer(rawCloseNotifySent.UnsafeAddr()))
|
|
||||||
rawConfig := reflect.Indirect(rawConn.FieldByName("config"))
|
|
||||||
if !rawConfig.IsValid() || rawConfig.Kind() != reflect.Struct {
|
|
||||||
return nil, E.New("badtls: bad config")
|
|
||||||
}
|
|
||||||
config := (*tls.Config)(unsafe.Pointer(rawConfig.UnsafeAddr()))
|
|
||||||
randReader := config.Rand
|
|
||||||
if randReader == nil {
|
|
||||||
randReader = rand.Reader
|
|
||||||
}
|
|
||||||
rawHalfMutex := rawHalfConn.FieldByName("Mutex")
|
|
||||||
if !rawHalfMutex.IsValid() || rawHalfMutex.Kind() != reflect.Struct {
|
|
||||||
return nil, E.New("badtls: invalid half mutex")
|
|
||||||
}
|
|
||||||
halfAccess := (*sync.Mutex)(unsafe.Pointer(rawHalfMutex.UnsafeAddr()))
|
|
||||||
rawHalfError := rawHalfConn.FieldByName("err")
|
|
||||||
if !rawHalfError.IsValid() || rawHalfError.Kind() != reflect.Interface {
|
|
||||||
return nil, E.New("badtls: invalid half error")
|
|
||||||
}
|
|
||||||
halfError := (*error)(unsafe.Pointer(rawHalfError.UnsafeAddr()))
|
|
||||||
rawHalfCipherInterface := rawHalfConn.FieldByName("cipher")
|
|
||||||
if !rawHalfCipherInterface.IsValid() || rawHalfCipherInterface.Kind() != reflect.Interface {
|
|
||||||
return nil, E.New("badtls: invalid cipher interface")
|
|
||||||
}
|
|
||||||
rawHalfCipher := rawHalfCipherInterface.Elem()
|
|
||||||
aeadCipher, loaded := valueInterface(rawHalfCipher, false).(cipher.AEAD)
|
|
||||||
if !loaded {
|
|
||||||
return nil, E.New("badtls: invalid AEAD cipher")
|
|
||||||
}
|
|
||||||
var explicitNonceLen int
|
|
||||||
switch cipherName := reflect.Indirect(rawHalfCipher).Type().String(); cipherName {
|
|
||||||
case "tls.prefixNonceAEAD":
|
|
||||||
explicitNonceLen = aeadCipher.NonceSize()
|
|
||||||
case "tls.xorNonceAEAD":
|
|
||||||
default:
|
|
||||||
return nil, E.New("badtls: unknown cipher type: ", cipherName)
|
|
||||||
}
|
|
||||||
rawHalfSeq := rawHalfConn.FieldByName("seq")
|
|
||||||
if !rawHalfSeq.IsValid() || rawHalfSeq.Kind() != reflect.Array {
|
|
||||||
return nil, E.New("badtls: invalid seq")
|
|
||||||
}
|
|
||||||
halfSeq := rawHalfSeq.Bytes()
|
|
||||||
rawHalfScratchBuf := rawHalfConn.FieldByName("scratchBuf")
|
|
||||||
if !rawHalfScratchBuf.IsValid() || rawHalfScratchBuf.Kind() != reflect.Array {
|
|
||||||
return nil, E.New("badtls: invalid scratchBuf")
|
|
||||||
}
|
|
||||||
halfScratchBuf := rawHalfScratchBuf.Bytes()
|
|
||||||
return &Conn{
|
|
||||||
Conn: conn,
|
|
||||||
writer: bufio.NewExtendedWriter(conn.NetConn()),
|
|
||||||
isHandshakeComplete: isHandshakeComplete,
|
|
||||||
activeCall: activeCall,
|
|
||||||
closeNotifySent: closeNotifySent,
|
|
||||||
version: version,
|
|
||||||
halfAccess: halfAccess,
|
|
||||||
halfError: halfError,
|
|
||||||
cipher: aeadCipher,
|
|
||||||
explicitNonceLen: explicitNonceLen,
|
|
||||||
rand: randReader,
|
|
||||||
halfPtr: rawHalfConn.UnsafeAddr(),
|
|
||||||
halfSeq: halfSeq,
|
|
||||||
halfScratchBuf: halfScratchBuf,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) WriteBuffer(buffer *buf.Buffer) error {
|
|
||||||
if buffer.Len() > maxPlaintext {
|
|
||||||
defer buffer.Release()
|
|
||||||
return common.Error(c.Write(buffer.Bytes()))
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
x := c.activeCall.Load()
|
|
||||||
if x&1 != 0 {
|
|
||||||
return net.ErrClosed
|
|
||||||
}
|
|
||||||
if c.activeCall.CompareAndSwap(x, x+2) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer c.activeCall.Add(-2)
|
|
||||||
c.halfAccess.Lock()
|
|
||||||
defer c.halfAccess.Unlock()
|
|
||||||
if err := *c.halfError; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if *c.closeNotifySent {
|
|
||||||
return errShutdown
|
|
||||||
}
|
|
||||||
dataLen := buffer.Len()
|
|
||||||
dataBytes := buffer.Bytes()
|
|
||||||
outBuf := buffer.ExtendHeader(recordHeaderLen + c.explicitNonceLen)
|
|
||||||
outBuf[0] = 23
|
|
||||||
version := *c.version
|
|
||||||
if version == 0 {
|
|
||||||
version = tls.VersionTLS10
|
|
||||||
} else if version == tls.VersionTLS13 {
|
|
||||||
version = tls.VersionTLS12
|
|
||||||
}
|
|
||||||
binary.BigEndian.PutUint16(outBuf[1:], version)
|
|
||||||
var nonce []byte
|
|
||||||
if c.explicitNonceLen > 0 {
|
|
||||||
nonce = outBuf[5 : 5+c.explicitNonceLen]
|
|
||||||
if c.explicitNonceLen < 16 {
|
|
||||||
copy(nonce, c.halfSeq)
|
|
||||||
} else {
|
|
||||||
if _, err := io.ReadFull(c.rand, nonce); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(nonce) == 0 {
|
|
||||||
nonce = c.halfSeq
|
|
||||||
}
|
|
||||||
if *c.version == tls.VersionTLS13 {
|
|
||||||
buffer.FreeBytes()[0] = 23
|
|
||||||
binary.BigEndian.PutUint16(outBuf[3:], uint16(dataLen+1+c.cipher.Overhead()))
|
|
||||||
c.cipher.Seal(outBuf, nonce, outBuf[recordHeaderLen:recordHeaderLen+c.explicitNonceLen+dataLen+1], outBuf[:recordHeaderLen])
|
|
||||||
buffer.Extend(1 + c.cipher.Overhead())
|
|
||||||
} else {
|
|
||||||
binary.BigEndian.PutUint16(outBuf[3:], uint16(dataLen))
|
|
||||||
additionalData := append(c.halfScratchBuf[:0], c.halfSeq...)
|
|
||||||
additionalData = append(additionalData, outBuf[:recordHeaderLen]...)
|
|
||||||
c.cipher.Seal(outBuf, nonce, dataBytes, additionalData)
|
|
||||||
buffer.Extend(c.cipher.Overhead())
|
|
||||||
binary.BigEndian.PutUint16(outBuf[3:], uint16(dataLen+c.explicitNonceLen+c.cipher.Overhead()))
|
|
||||||
}
|
|
||||||
incSeq(c.halfPtr)
|
|
||||||
log.Trace("badtls write ", buffer.Len())
|
|
||||||
return c.writer.WriteBuffer(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) FrontHeadroom() int {
|
|
||||||
return recordHeaderLen + c.explicitNonceLen
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) RearHeadroom() int {
|
|
||||||
return 1 + c.cipher.Overhead()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) WriterMTU() int {
|
|
||||||
return maxPlaintext
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) Upstream() any {
|
|
||||||
return c.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) UpstreamWriter() any {
|
|
||||||
return c.NetConn()
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
//go:build !go1.19 || go1.21
|
|
||||||
|
|
||||||
package badtls
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
aTLS "github.com/sagernet/sing/common/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Create(conn *tls.Conn) (aTLS.Conn, error) {
|
|
||||||
return nil, os.ErrInvalid
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
//go:build go1.20 && !go.1.21
|
|
||||||
|
|
||||||
package badtls
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
_ "unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
maxPlaintext = 16384 // maximum plaintext payload length
|
|
||||||
recordHeaderLen = 5 // record header length
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:linkname errShutdown crypto/tls.errShutdown
|
|
||||||
var errShutdown error
|
|
||||||
|
|
||||||
//go:linkname incSeq crypto/tls.(*halfConn).incSeq
|
|
||||||
func incSeq(conn uintptr)
|
|
||||||
|
|
||||||
//go:linkname valueInterface reflect.valueInterface
|
|
||||||
func valueInterface(v reflect.Value, safe bool) any
|
|
115
common/badtls/read_wait.go
Normal file
115
common/badtls/read_wait.go
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
//go:build go1.21 && !without_badtls
|
||||||
|
|
||||||
|
package badtls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/common/tls"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ N.ReadWaiter = (*ReadWaitConn)(nil)
|
||||||
|
|
||||||
|
type ReadWaitConn struct {
|
||||||
|
*tls.STDConn
|
||||||
|
halfAccess *sync.Mutex
|
||||||
|
rawInput *bytes.Buffer
|
||||||
|
input *bytes.Reader
|
||||||
|
hand *bytes.Buffer
|
||||||
|
readWaitOptions N.ReadWaitOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReadWaitConn(conn tls.Conn) (tls.Conn, error) {
|
||||||
|
stdConn, isSTDConn := conn.(*tls.STDConn)
|
||||||
|
if !isSTDConn {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
rawConn := reflect.Indirect(reflect.ValueOf(stdConn))
|
||||||
|
rawHalfConn := rawConn.FieldByName("in")
|
||||||
|
if !rawHalfConn.IsValid() || rawHalfConn.Kind() != reflect.Struct {
|
||||||
|
return nil, E.New("badtls: invalid half conn")
|
||||||
|
}
|
||||||
|
rawHalfMutex := rawHalfConn.FieldByName("Mutex")
|
||||||
|
if !rawHalfMutex.IsValid() || rawHalfMutex.Kind() != reflect.Struct {
|
||||||
|
return nil, E.New("badtls: invalid half mutex")
|
||||||
|
}
|
||||||
|
halfAccess := (*sync.Mutex)(unsafe.Pointer(rawHalfMutex.UnsafeAddr()))
|
||||||
|
rawRawInput := rawConn.FieldByName("rawInput")
|
||||||
|
if !rawRawInput.IsValid() || rawRawInput.Kind() != reflect.Struct {
|
||||||
|
return nil, E.New("badtls: invalid raw input")
|
||||||
|
}
|
||||||
|
rawInput := (*bytes.Buffer)(unsafe.Pointer(rawRawInput.UnsafeAddr()))
|
||||||
|
rawInput0 := rawConn.FieldByName("input")
|
||||||
|
if !rawInput0.IsValid() || rawInput0.Kind() != reflect.Struct {
|
||||||
|
return nil, E.New("badtls: invalid input")
|
||||||
|
}
|
||||||
|
input := (*bytes.Reader)(unsafe.Pointer(rawInput0.UnsafeAddr()))
|
||||||
|
rawHand := rawConn.FieldByName("hand")
|
||||||
|
if !rawHand.IsValid() || rawHand.Kind() != reflect.Struct {
|
||||||
|
return nil, E.New("badtls: invalid hand")
|
||||||
|
}
|
||||||
|
hand := (*bytes.Buffer)(unsafe.Pointer(rawHand.UnsafeAddr()))
|
||||||
|
return &ReadWaitConn{
|
||||||
|
STDConn: stdConn,
|
||||||
|
halfAccess: halfAccess,
|
||||||
|
rawInput: rawInput,
|
||||||
|
input: input,
|
||||||
|
hand: hand,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ReadWaitConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
||||||
|
c.readWaitOptions = options
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ReadWaitConn) WaitReadBuffer() (buffer *buf.Buffer, err error) {
|
||||||
|
err = c.Handshake()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.halfAccess.Lock()
|
||||||
|
defer c.halfAccess.Unlock()
|
||||||
|
for c.input.Len() == 0 {
|
||||||
|
err = tlsReadRecord(c.STDConn)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for c.hand.Len() > 0 {
|
||||||
|
err = tlsHandlePostHandshakeMessage(c.STDConn)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer = c.readWaitOptions.NewBuffer()
|
||||||
|
n, err := c.input.Read(buffer.FreeBytes())
|
||||||
|
if err != nil {
|
||||||
|
buffer.Release()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buffer.Truncate(n)
|
||||||
|
|
||||||
|
if n != 0 && c.input.Len() == 0 && c.rawInput.Len() > 0 &&
|
||||||
|
// recordType(c.rawInput.Bytes()[0]) == recordTypeAlert {
|
||||||
|
c.rawInput.Bytes()[0] == 21 {
|
||||||
|
_ = tlsReadRecord(c.STDConn)
|
||||||
|
// return n, err // will be io.EOF on closeNotify
|
||||||
|
}
|
||||||
|
|
||||||
|
c.readWaitOptions.PostReturn(buffer)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname tlsReadRecord crypto/tls.(*Conn).readRecord
|
||||||
|
func tlsReadRecord(c *tls.STDConn) error
|
||||||
|
|
||||||
|
//go:linkname tlsHandlePostHandshakeMessage crypto/tls.(*Conn).handlePostHandshakeMessage
|
||||||
|
func tlsHandlePostHandshakeMessage(c *tls.STDConn) error
|
13
common/badtls/read_wait_stub.go
Normal file
13
common/badtls/read_wait_stub.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//go:build !go1.21 || without_badtls
|
||||||
|
|
||||||
|
package badtls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/tls"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewReadWaitConn(conn tls.Conn) (tls.Conn, error) {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/badtls"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
@ -42,7 +43,17 @@ func NewClient(ctx context.Context, serverAddress string, options option.Outboun
|
|||||||
func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, error) {
|
func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return aTLS.ClientHandshake(ctx, conn, config)
|
tlsConn, err := aTLS.ClientHandshake(ctx, conn, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
readWaitConn, err := badtls.NewReadWaitConn(tlsConn)
|
||||||
|
if err == nil {
|
||||||
|
return readWaitConn, nil
|
||||||
|
} else if err != os.ErrInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tlsConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Dialer struct {
|
type Dialer struct {
|
||||||
|
@ -3,7 +3,9 @@ package tls
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/common/badtls"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
@ -26,5 +28,15 @@ func NewServer(ctx context.Context, logger log.Logger, options option.InboundTLS
|
|||||||
func ServerHandshake(ctx context.Context, conn net.Conn, config ServerConfig) (Conn, error) {
|
func ServerHandshake(ctx context.Context, conn net.Conn, config ServerConfig) (Conn, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return aTLS.ServerHandshake(ctx, conn, config)
|
tlsConn, err := aTLS.ServerHandshake(ctx, conn, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
readWaitConn, err := badtls.NewReadWaitConn(tlsConn)
|
||||||
|
if err == nil {
|
||||||
|
return readWaitConn, nil
|
||||||
|
} else if err != os.ErrInvalid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tlsConn, nil
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ SFA provides an unprivileged TUN implementation through Android VpnService.
|
|||||||
| `inet4_address` | :material-check: | / |
|
| `inet4_address` | :material-check: | / |
|
||||||
| `inet6_address` | :material-check: | / |
|
| `inet6_address` | :material-check: | / |
|
||||||
| `mtu` | :material-check: | / |
|
| `mtu` | :material-check: | / |
|
||||||
|
| `gso` | :material-close: | No permission |
|
||||||
|
| `gso_max_size` | :material-close: | No permission |
|
||||||
| `auto_route` | :material-check: | / |
|
| `auto_route` | :material-check: | / |
|
||||||
| `strict_route` | :material-close: | Not implemented |
|
| `strict_route` | :material-close: | Not implemented |
|
||||||
| `inet4_route_address` | :material-check: | / |
|
| `inet4_route_address` | :material-check: | / |
|
||||||
|
@ -14,28 +14,30 @@ SFI/SFM/SFT allows you to run sing-box through NetworkExtension with Application
|
|||||||
|
|
||||||
SFI/SFM/SFT provides an unprivileged TUN implementation through NetworkExtension.
|
SFI/SFM/SFT provides an unprivileged TUN implementation through NetworkExtension.
|
||||||
|
|
||||||
| TUN inbound option | Available | Note |
|
| TUN inbound option | Available | Note |
|
||||||
|-------------------------------|-----------|-------------------|
|
|-------------------------------|-------------------|-------------------|
|
||||||
| `interface_name` | ✖️ | Managed by Darwin |
|
| `interface_name` | :material-close:️ | Managed by Darwin |
|
||||||
| `inet4_address` | ✔️ | / |
|
| `inet4_address` | :material-check: | / |
|
||||||
| `inet6_address` | ✔️ | / |
|
| `inet6_address` | :material-check: | / |
|
||||||
| `mtu` | ✔️ | / |
|
| `mtu` | :material-check: | / |
|
||||||
| `auto_route` | ✔️ | / |
|
| `gso` | :material-close: | Not implemented |
|
||||||
| `strict_route` | ✖️ | Not implemented |
|
| `gso_max_size` | :material-close: | Not implemented |
|
||||||
| `inet4_route_address` | ✔️ | / |
|
| `auto_route` | :material-check: | / |
|
||||||
| `inet6_route_address` | ✔️ | / |
|
| `strict_route` | :material-close:️ | Not implemented |
|
||||||
| `inet4_route_exclude_address` | ✔️ | / |
|
| `inet4_route_address` | :material-check: | / |
|
||||||
| `inet6_route_exclude_address` | ✔️ | / |
|
| `inet6_route_address` | :material-check: | / |
|
||||||
| `endpoint_independent_nat` | ✔️ | / |
|
| `inet4_route_exclude_address` | :material-check: | / |
|
||||||
| `stack` | ✔️ | / |
|
| `inet6_route_exclude_address` | :material-check: | / |
|
||||||
| `include_interface` | ✖️ | Not implemented |
|
| `endpoint_independent_nat` | :material-check: | / |
|
||||||
| `exclude_interface` | ✖️ | Not implemented |
|
| `stack` | :material-check: | / |
|
||||||
| `include_uid` | ✖️ | Not implemented |
|
| `include_interface` | :material-close:️ | Not implemented |
|
||||||
| `exclude_uid` | ✖️ | Not implemented |
|
| `exclude_interface` | :material-close:️ | Not implemented |
|
||||||
| `include_android_user` | ✖️ | Not implemented |
|
| `include_uid` | :material-close:️ | Not implemented |
|
||||||
| `include_package` | ✖️ | Not implemented |
|
| `exclude_uid` | :material-close:️ | Not implemented |
|
||||||
| `exclude_package` | ✖️ | Not implemented |
|
| `include_android_user` | :material-close:️ | Not implemented |
|
||||||
| `platform` | ✔️ | / |
|
| `include_package` | :material-close:️ | Not implemented |
|
||||||
|
| `exclude_package` | :material-close:️ | Not implemented |
|
||||||
|
| `platform` | :material-check: | / |
|
||||||
|
|
||||||
| Route/DNS rule option | Available | Note |
|
| Route/DNS rule option | Available | Note |
|
||||||
|-----------------------|------------------|-----------------------|
|
|-----------------------|------------------|-----------------------|
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
---
|
||||||
|
icon: material/alert-decagram
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.8.0"
|
||||||
|
|
||||||
|
:material-plus: [gso](#gso)
|
||||||
|
:material-plus: [gso_max_size](#gso_max_size)
|
||||||
|
:material-alert-decagram: [stack](#stack)
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|
||||||
Only supported on Linux, Windows and macOS.
|
Only supported on Linux, Windows and macOS.
|
||||||
@ -12,6 +22,8 @@
|
|||||||
"inet4_address": "172.19.0.1/30",
|
"inet4_address": "172.19.0.1/30",
|
||||||
"inet6_address": "fdfe:dcba:9876::1/126",
|
"inet6_address": "fdfe:dcba:9876::1/126",
|
||||||
"mtu": 9000,
|
"mtu": 9000,
|
||||||
|
"gso": false,
|
||||||
|
"gso_max_size": 65536,
|
||||||
"auto_route": true,
|
"auto_route": true,
|
||||||
"strict_route": true,
|
"strict_route": true,
|
||||||
"inet4_route_address": [
|
"inet4_route_address": [
|
||||||
@ -98,6 +110,28 @@ IPv6 prefix for the tun interface.
|
|||||||
|
|
||||||
The maximum transmission unit.
|
The maximum transmission unit.
|
||||||
|
|
||||||
|
#### gso
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.8.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux.
|
||||||
|
|
||||||
|
Enable generic segmentation offload.
|
||||||
|
|
||||||
|
#### gso_max_size
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.8.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux.
|
||||||
|
|
||||||
|
Maximum GSO packet size.
|
||||||
|
|
||||||
|
`65536` is used by default.
|
||||||
|
|
||||||
#### auto_route
|
#### auto_route
|
||||||
|
|
||||||
Set the default route to the Tun.
|
Set the default route to the Tun.
|
||||||
@ -160,18 +194,19 @@ UDP NAT expiration time in seconds, default is 300 (5 minutes).
|
|||||||
|
|
||||||
#### stack
|
#### stack
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.8.0"
|
||||||
|
|
||||||
|
:material-delete-alert: The legacy LWIP stack has been deprecated and removed.
|
||||||
|
|
||||||
TCP/IP stack.
|
TCP/IP stack.
|
||||||
|
|
||||||
| Stack | Description | Status |
|
| Stack | Description |
|
||||||
|--------|----------------------------------------------------------------------------------|-------------------|
|
|----------|-------------------------------------------------------------------------------------------------------|
|
||||||
| system | Sometimes better performance | recommended |
|
| `system` | Perform L3 to L4 translation using the system network stack |
|
||||||
| gVisor | Better compatibility, based on [google/gvisor](https://github.com/google/gvisor) | recommended |
|
| `gvisor` | Perform L3 to L4 translation using [gVisor](https://github.com/google/gvisor)'s virtual network stack |
|
||||||
| mixed | Mixed `system` TCP stack and `gVisor` UDP stack | recommended |
|
| `mixed` | Mixed `system` TCP stack and `gvisor` UDP stack |
|
||||||
| LWIP | Based on [eycorsican/go-tun2socks](https://github.com/eycorsican/go-tun2socks) | upstream archived |
|
|
||||||
|
|
||||||
!!! warning ""
|
Defaults to the `mixed` stack if the gVisor build tag is enabled, otherwise defaults to the `system` stack.
|
||||||
|
|
||||||
LWIP stacks is not included by default, see [Installation](/installation/build-from-source/#build-tags).
|
|
||||||
|
|
||||||
#### include_interface
|
#### include_interface
|
||||||
|
|
||||||
@ -217,10 +252,10 @@ Exclude users in route, but in range.
|
|||||||
|
|
||||||
Limit android users in route.
|
Limit android users in route.
|
||||||
|
|
||||||
| Common user | ID |
|
| Common user | ID |
|
||||||
|--------------|-----|
|
|--------------|----|
|
||||||
| Main | 0 |
|
| Main | 0 |
|
||||||
| Work Profile | 10 |
|
| Work Profile | 10 |
|
||||||
|
|
||||||
#### include_package
|
#### include_package
|
||||||
|
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
---
|
||||||
|
icon: material/alert-decagram
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.8.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: [gso](#gso)
|
||||||
|
:material-plus: [gso_max_size](#gso_max_size)
|
||||||
|
:material-alert-decagram: [stack](#stack)
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|
||||||
仅支持 Linux、Windows 和 macOS。
|
仅支持 Linux、Windows 和 macOS。
|
||||||
@ -12,6 +22,8 @@
|
|||||||
"inet4_address": "172.19.0.1/30",
|
"inet4_address": "172.19.0.1/30",
|
||||||
"inet6_address": "fdfe:dcba:9876::1/126",
|
"inet6_address": "fdfe:dcba:9876::1/126",
|
||||||
"mtu": 9000,
|
"mtu": 9000,
|
||||||
|
"gso": false,
|
||||||
|
"gso_max_size": 65536,
|
||||||
"auto_route": true,
|
"auto_route": true,
|
||||||
"strict_route": true,
|
"strict_route": true,
|
||||||
"inet4_route_address": [
|
"inet4_route_address": [
|
||||||
@ -98,6 +110,28 @@ tun 接口的 IPv6 前缀。
|
|||||||
|
|
||||||
最大传输单元。
|
最大传输单元。
|
||||||
|
|
||||||
|
#### gso
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.8.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux。
|
||||||
|
|
||||||
|
启用通用分段卸载。
|
||||||
|
|
||||||
|
#### gso_max_size
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.8.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux。
|
||||||
|
|
||||||
|
通用分段卸载包的最大大小。
|
||||||
|
|
||||||
|
默认使用 `65536`。
|
||||||
|
|
||||||
#### auto_route
|
#### auto_route
|
||||||
|
|
||||||
设置到 Tun 的默认路由。
|
设置到 Tun 的默认路由。
|
||||||
@ -157,17 +191,19 @@ UDP NAT 过期时间,以秒为单位,默认为 300(5 分钟)。
|
|||||||
|
|
||||||
#### stack
|
#### stack
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.8.0 中的更改"
|
||||||
|
|
||||||
|
:material-delete-alert: 旧的 LWIP 栈已被弃用并移除。
|
||||||
|
|
||||||
TCP/IP 栈。
|
TCP/IP 栈。
|
||||||
|
|
||||||
| 栈 | 描述 | 状态 |
|
| 栈 | 描述 |
|
||||||
|-------------|--------------------------------------------------------------------------|-------|
|
|--------|------------------------------------------------------------------|
|
||||||
| system (默认) | 有时性能更好 | 推荐 |
|
| system | 基于系统网络栈执行 L3 到 L4 转换 |
|
||||||
| gVisor | 兼容性较好,基于 [google/gvisor](https://github.com/google/gvisor) | 推荐 |
|
| gVisor | 基于 [gVisor](https://github.com/google/gvisor) 虚拟网络栈执行 L3 到 L4 转换 |
|
||||||
| LWIP | 基于 [eycorsican/go-tun2socks](https://github.com/eycorsican/go-tun2socks) | 上游已存档 |
|
| mixed | 混合 `system` TCP 栈与 `gvisor` UDP 栈 |
|
||||||
|
|
||||||
!!! warning ""
|
默认使用 `mixed` 栈如果 gVisor 构建标记已启用,否则默认使用 `system` 栈。
|
||||||
|
|
||||||
默认安装不包含 LWIP 栈,参阅 [安装](/zh/installation/build-from-source/#_5)。
|
|
||||||
|
|
||||||
#### include_interface
|
#### include_interface
|
||||||
|
|
||||||
@ -214,8 +250,8 @@ TCP/IP 栈。
|
|||||||
限制被路由的 Android 用户。
|
限制被路由的 Android 用户。
|
||||||
|
|
||||||
| 常用用户 | ID |
|
| 常用用户 | ID |
|
||||||
|--|-----|
|
|------|----|
|
||||||
| 您 | 0 |
|
| 您 | 0 |
|
||||||
| 工作资料 | 10 |
|
| 工作资料 | 10 |
|
||||||
|
|
||||||
#### include_package
|
#### include_package
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.8.0"
|
||||||
|
|
||||||
|
:material-plus: [gso](#gso)
|
||||||
|
:material-plus: [gso_max_size](#gso_max_size)
|
||||||
|
|
||||||
### Structure
|
### Structure
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -8,6 +17,8 @@
|
|||||||
"server": "127.0.0.1",
|
"server": "127.0.0.1",
|
||||||
"server_port": 1080,
|
"server_port": 1080,
|
||||||
"system_interface": false,
|
"system_interface": false,
|
||||||
|
"gso": false,
|
||||||
|
"gso_max_size": 65536,
|
||||||
"interface_name": "wg0",
|
"interface_name": "wg0",
|
||||||
"local_address": [
|
"local_address": [
|
||||||
"10.0.0.2/32"
|
"10.0.0.2/32"
|
||||||
@ -52,15 +63,37 @@ The server port.
|
|||||||
|
|
||||||
#### system_interface
|
#### system_interface
|
||||||
|
|
||||||
Use system tun support.
|
Use system interface.
|
||||||
|
|
||||||
Requires privilege and cannot conflict with system interfaces.
|
Requires privilege and cannot conflict with exists system interfaces.
|
||||||
|
|
||||||
Forced if gVisor not included in the build.
|
Forced if gVisor not included in the build.
|
||||||
|
|
||||||
#### interface_name
|
#### interface_name
|
||||||
|
|
||||||
Custom device name when `system_interface` enabled.
|
Custom interface name for system interface.
|
||||||
|
|
||||||
|
#### gso
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.8.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux.
|
||||||
|
|
||||||
|
Enable generic segmentation offload for system interface.
|
||||||
|
|
||||||
|
#### gso_max_size
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.8.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux.
|
||||||
|
|
||||||
|
Maximum GSO packet size.
|
||||||
|
|
||||||
|
`65536` is used by default.
|
||||||
|
|
||||||
#### local_address
|
#### local_address
|
||||||
|
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.8.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: [gso](#gso)
|
||||||
|
:material-plus: [gso_max_size](#gso_max_size)
|
||||||
|
|
||||||
### 结构
|
### 结构
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -8,6 +17,8 @@
|
|||||||
"server": "127.0.0.1",
|
"server": "127.0.0.1",
|
||||||
"server_port": 1080,
|
"server_port": 1080,
|
||||||
"system_interface": false,
|
"system_interface": false,
|
||||||
|
"gso": false,
|
||||||
|
"gso_max_size": 65536,
|
||||||
"interface_name": "wg0",
|
"interface_name": "wg0",
|
||||||
"local_address": [
|
"local_address": [
|
||||||
"10.0.0.2/32"
|
"10.0.0.2/32"
|
||||||
@ -40,15 +51,37 @@
|
|||||||
|
|
||||||
#### system_interface
|
#### system_interface
|
||||||
|
|
||||||
使用系统 tun 支持。
|
使用系统设备。
|
||||||
|
|
||||||
需要特权且不能与系统接口冲突。
|
需要特权且不能与已有系统接口冲突。
|
||||||
|
|
||||||
如果 gVisor 未包含在构建中,则强制执行。
|
如果 gVisor 未包含在构建中,则强制执行。
|
||||||
|
|
||||||
#### interface_name
|
#### interface_name
|
||||||
|
|
||||||
启用 `system_interface` 时的自定义设备名称。
|
为系统接口自定义设备名称。
|
||||||
|
|
||||||
|
#### gso
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.8.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux。
|
||||||
|
|
||||||
|
为系统接口启用通用分段卸载。
|
||||||
|
|
||||||
|
#### gso_max_size
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.8.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux。
|
||||||
|
|
||||||
|
通用分段卸载包的最大大小。
|
||||||
|
|
||||||
|
默认使用 `65536`。
|
||||||
|
|
||||||
#### local_address
|
#### local_address
|
||||||
|
|
||||||
|
@ -45,19 +45,18 @@ go build -tags "tag_a tag_b" ./cmd/sing-box
|
|||||||
|
|
||||||
| Build Tag | Enabled by default | Description |
|
| Build Tag | Enabled by default | Description |
|
||||||
|------------------------------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------------------------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `with_quic` | ✔ | Build with QUIC support, see [QUIC and HTTP3 DNS transports](/configuration/dns/server), [Naive inbound](/configuration/inbound/naive), [Hysteria Inbound](/configuration/inbound/hysteria), [Hysteria Outbound](/configuration/outbound/hysteria) and [V2Ray Transport#QUIC](/configuration/shared/v2ray-transport#quic). |
|
| `with_quic` | :material-check: | Build with QUIC support, see [QUIC and HTTP3 DNS transports](/configuration/dns/server), [Naive inbound](/configuration/inbound/naive), [Hysteria Inbound](/configuration/inbound/hysteria), [Hysteria Outbound](/configuration/outbound/hysteria) and [V2Ray Transport#QUIC](/configuration/shared/v2ray-transport#quic). |
|
||||||
| `with_grpc` | ✖️ | Build with standard gRPC support, see [V2Ray Transport#gRPC](/configuration/shared/v2ray-transport#grpc). |
|
| `with_grpc` | :material-close:️ | Build with standard gRPC support, see [V2Ray Transport#gRPC](/configuration/shared/v2ray-transport#grpc). |
|
||||||
| `with_dhcp` | ✔ | Build with DHCP support, see [DHCP DNS transport](/configuration/dns/server). |
|
| `with_dhcp` | :material-check: | Build with DHCP support, see [DHCP DNS transport](/configuration/dns/server). |
|
||||||
| `with_wireguard` | ✔ | Build with WireGuard support, see [WireGuard outbound](/configuration/outbound/wireguard). |
|
| `with_wireguard` | :material-check: | Build with WireGuard support, see [WireGuard outbound](/configuration/outbound/wireguard). |
|
||||||
| `with_ech` | ✔ | Build with TLS ECH extension support for TLS outbound, see [TLS](/configuration/shared/tls#ech). |
|
| `with_ech` | :material-check: | Build with TLS ECH extension support for TLS outbound, see [TLS](/configuration/shared/tls#ech). |
|
||||||
| `with_utls` | ✔ | Build with [uTLS](https://github.com/refraction-networking/utls) support for TLS outbound, see [TLS](/configuration/shared/tls#utls). |
|
| `with_utls` | :material-check: | Build with [uTLS](https://github.com/refraction-networking/utls) support for TLS outbound, see [TLS](/configuration/shared/tls#utls). |
|
||||||
| `with_reality_server` | ✔ | Build with reality TLS server support, see [TLS](/configuration/shared/tls). |
|
| `with_reality_server` | :material-check: | Build with reality TLS server support, see [TLS](/configuration/shared/tls). |
|
||||||
| `with_acme` | ✔ | Build with ACME TLS certificate issuer support, see [TLS](/configuration/shared/tls). |
|
| `with_acme` | :material-check: | Build with ACME TLS certificate issuer support, see [TLS](/configuration/shared/tls). |
|
||||||
| `with_clash_api` | ✔ | Build with Clash API support, see [Experimental](/configuration/experimental#clash-api-fields). |
|
| `with_clash_api` | :material-check: | Build with Clash API support, see [Experimental](/configuration/experimental#clash-api-fields). |
|
||||||
| `with_v2ray_api` | ✖️ | Build with V2Ray API support, see [Experimental](/configuration/experimental#v2ray-api-fields). |
|
| `with_v2ray_api` | :material-close:️ | Build with V2Ray API support, see [Experimental](/configuration/experimental#v2ray-api-fields). |
|
||||||
| `with_gvisor` | ✔ | Build with gVisor support, see [Tun inbound](/configuration/inbound/tun#stack) and [WireGuard outbound](/configuration/outbound/wireguard#system_interface). |
|
| `with_gvisor` | :material-check: | Build with gVisor support, see [Tun inbound](/configuration/inbound/tun#stack) and [WireGuard outbound](/configuration/outbound/wireguard#system_interface). |
|
||||||
| `with_embedded_tor` (CGO required) | ✖️ | Build with embedded Tor support, see [Tor outbound](/configuration/outbound/tor). |
|
| `with_embedded_tor` (CGO required) | :material-close:️ | Build with embedded Tor support, see [Tor outbound](/configuration/outbound/tor). |
|
||||||
| `with_lwip` (CGO required) | ✖️ | Build with LWIP Tun stack support, see [Tun inbound](/configuration/inbound/tun#stack). |
|
|
||||||
|
|
||||||
|
|
||||||
It is not recommended to change the default build tag list unless you really know what you are adding.
|
It is not recommended to change the default build tag list unless you really know what you are adding.
|
||||||
|
@ -43,21 +43,19 @@ go build -tags "tag_a tag_b" ./cmd/sing-box
|
|||||||
|
|
||||||
## :material-folder-settings: 构建标记
|
## :material-folder-settings: 构建标记
|
||||||
|
|
||||||
| 构建标记 | 默认启动 | 说明 |
|
| 构建标记 | 默认启动 | 说明 |
|
||||||
|------------------------------------|------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------------------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `with_quic` | ✔ | Build with QUIC support, see [QUIC and HTTP3 DNS transports](/configuration/dns/server), [Naive inbound](/configuration/inbound/naive), [Hysteria Inbound](/configuration/inbound/hysteria), [Hysteria Outbound](/configuration/outbound/hysteria) and [V2Ray Transport#QUIC](/configuration/shared/v2ray-transport#quic). |
|
| `with_quic` | :material-check: | Build with QUIC support, see [QUIC and HTTP3 DNS transports](/configuration/dns/server), [Naive inbound](/configuration/inbound/naive), [Hysteria Inbound](/configuration/inbound/hysteria), [Hysteria Outbound](/configuration/outbound/hysteria) and [V2Ray Transport#QUIC](/configuration/shared/v2ray-transport#quic). |
|
||||||
| `with_grpc` | ✖️ | Build with standard gRPC support, see [V2Ray Transport#gRPC](/configuration/shared/v2ray-transport#grpc). |
|
| `with_grpc` | :material-close:️ | Build with standard gRPC support, see [V2Ray Transport#gRPC](/configuration/shared/v2ray-transport#grpc). |
|
||||||
| `with_dhcp` | ✔ | Build with DHCP support, see [DHCP DNS transport](/configuration/dns/server). |
|
| `with_dhcp` | :material-check: | Build with DHCP support, see [DHCP DNS transport](/configuration/dns/server). |
|
||||||
| `with_wireguard` | ✔ | Build with WireGuard support, see [WireGuard outbound](/configuration/outbound/wireguard). |
|
| `with_wireguard` | :material-check: | Build with WireGuard support, see [WireGuard outbound](/configuration/outbound/wireguard). |
|
||||||
| `with_ech` | ✔ | Build with TLS ECH extension support for TLS outbound, see [TLS](/configuration/shared/tls#ech). |
|
| `with_ech` | :material-check: | Build with TLS ECH extension support for TLS outbound, see [TLS](/configuration/shared/tls#ech). |
|
||||||
| `with_utls` | ✔ | Build with [uTLS](https://github.com/refraction-networking/utls) support for TLS outbound, see [TLS](/configuration/shared/tls#utls). |
|
| `with_utls` | :material-check: | Build with [uTLS](https://github.com/refraction-networking/utls) support for TLS outbound, see [TLS](/configuration/shared/tls#utls). |
|
||||||
| `with_reality_server` | ✔ | Build with reality TLS server support, see [TLS](/configuration/shared/tls). |
|
| `with_reality_server` | :material-check: | Build with reality TLS server support, see [TLS](/configuration/shared/tls). |
|
||||||
| `with_acme` | ✔ | Build with ACME TLS certificate issuer support, see [TLS](/configuration/shared/tls). |
|
| `with_acme` | :material-check: | Build with ACME TLS certificate issuer support, see [TLS](/configuration/shared/tls). |
|
||||||
| `with_clash_api` | ✔ | Build with Clash API support, see [Experimental](/configuration/experimental#clash-api-fields). |
|
| `with_clash_api` | :material-check: | Build with Clash API support, see [Experimental](/configuration/experimental#clash-api-fields). |
|
||||||
| `with_v2ray_api` | ✖️ | Build with V2Ray API support, see [Experimental](/configuration/experimental#v2ray-api-fields). |
|
| `with_v2ray_api` | :material-close:️ | Build with V2Ray API support, see [Experimental](/configuration/experimental#v2ray-api-fields). |
|
||||||
| `with_gvisor` | ✔ | Build with gVisor support, see [Tun inbound](/configuration/inbound/tun#stack) and [WireGuard outbound](/configuration/outbound/wireguard#system_interface). |
|
| `with_gvisor` | :material-check: | Build with gVisor support, see [Tun inbound](/configuration/inbound/tun#stack) and [WireGuard outbound](/configuration/outbound/wireguard#system_interface). |
|
||||||
| `with_embedded_tor` (CGO required) | ✖️ | Build with embedded Tor support, see [Tor outbound](/configuration/outbound/tor). |
|
| `with_embedded_tor` (CGO required) | :material-close:️ | Build with embedded Tor support, see [Tor outbound](/configuration/outbound/tor). |
|
||||||
| `with_lwip` (CGO required) | ✖️ | Build with LWIP Tun stack support, see [Tun inbound](/configuration/inbound/tun#stack). |
|
|
||||||
|
|
||||||
|
|
||||||
除非您确实知道您正在启用什么,否则不建议更改默认构建标签列表。
|
除非您确实知道您正在启用什么,否则不建议更改默认构建标签列表。
|
||||||
|
17
go.mod
17
go.mod
@ -23,19 +23,19 @@ require (
|
|||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a
|
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a
|
||||||
github.com/sagernet/gomobile v0.0.0-20230915142329-c6740b6d2950
|
github.com/sagernet/gomobile v0.0.0-20230915142329-c6740b6d2950
|
||||||
github.com/sagernet/gvisor v0.0.0-20231119034329-07cfb6aaf930
|
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e
|
||||||
github.com/sagernet/quic-go v0.40.0
|
github.com/sagernet/quic-go v0.40.0
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.2.20-0.20231208065534-70794cb91cc5
|
github.com/sagernet/sing v0.2.20-0.20231212123824-8836b6754226
|
||||||
github.com/sagernet/sing-dns v0.1.11
|
github.com/sagernet/sing-dns v0.1.11
|
||||||
github.com/sagernet/sing-mux v0.1.5
|
github.com/sagernet/sing-mux v0.1.6-0.20231208180947-9053c29513a2
|
||||||
github.com/sagernet/sing-quic v0.1.5
|
github.com/sagernet/sing-quic v0.1.6-0.20231207143711-eb3cbf9ed054
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6
|
github.com/sagernet/sing-shadowsocks v0.2.6
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.5
|
github.com/sagernet/sing-shadowsocks2 v0.1.6-0.20231207143709-50439739601a
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4
|
github.com/sagernet/sing-shadowtls v0.1.4
|
||||||
github.com/sagernet/sing-tun v0.1.24-0.20231212055255-69c3b72eec62
|
github.com/sagernet/sing-tun v0.1.24-0.20231212060935-6a1419aeae11
|
||||||
github.com/sagernet/sing-vmess v0.1.8
|
github.com/sagernet/sing-vmess v0.1.8
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6
|
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f
|
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f
|
||||||
@ -78,7 +78,6 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/quic-go/qpack v0.4.0 // indirect
|
github.com/quic-go/qpack v0.4.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
github.com/quic-go/qtls-go1-20 v0.4.1 // 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/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||||
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
|
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
@ -89,7 +88,7 @@ require (
|
|||||||
golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect
|
golang.org/x/exp v0.0.0-20231127185646-65229373498e // indirect
|
||||||
golang.org/x/mod v0.14.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/time v0.4.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.16.0 // indirect
|
golang.org/x/tools v0.16.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
|
39
go.sum
39
go.sum
@ -96,40 +96,37 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk
|
|||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a h1:wZHruBxZCsQLXHAozWpnJBL3wJ/XufDpz0qKtgpSnA4=
|
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a h1:wZHruBxZCsQLXHAozWpnJBL3wJ/XufDpz0qKtgpSnA4=
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI=
|
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI=
|
||||||
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-20230915142329-c6740b6d2950 h1:hUz/2mJLgi7l2H36JGpDY+jou9FmI6kAm0ZkU+xPpgE=
|
github.com/sagernet/gomobile v0.0.0-20230915142329-c6740b6d2950 h1:hUz/2mJLgi7l2H36JGpDY+jou9FmI6kAm0ZkU+xPpgE=
|
||||||
github.com/sagernet/gomobile v0.0.0-20230915142329-c6740b6d2950/go.mod h1:5YE39YkJkCcMsfq1jMKkjsrM2GfBoF9JVWnvU89hmvU=
|
github.com/sagernet/gomobile v0.0.0-20230915142329-c6740b6d2950/go.mod h1:5YE39YkJkCcMsfq1jMKkjsrM2GfBoF9JVWnvU89hmvU=
|
||||||
github.com/sagernet/gvisor v0.0.0-20231119034329-07cfb6aaf930 h1:dSPgjIw0CT6ISLeEh8Q20dZMBMFCcEceo23+LncRcNQ=
|
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e h1:DOkjByVeAR56dkszjnMZke4wr7yM/1xHaJF3G9olkEE=
|
||||||
github.com/sagernet/gvisor v0.0.0-20231119034329-07cfb6aaf930/go.mod h1:JpKHkOYgh4wLwrX2BhH3ZIvCvazCkTnPeEcmigZJfHY=
|
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
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/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/quic-go v0.40.0 h1:DvQNPb72lzvNQDe9tcUyHTw8eRv6PLtM2mNYmdlzUMo=
|
github.com/sagernet/quic-go v0.40.0 h1:DvQNPb72lzvNQDe9tcUyHTw8eRv6PLtM2mNYmdlzUMo=
|
||||||
github.com/sagernet/quic-go v0.40.0/go.mod h1:VqtdhlbkeeG5Okhb3eDMb/9o0EoglReHunNT9ukrJAI=
|
github.com/sagernet/quic-go v0.40.0/go.mod h1:VqtdhlbkeeG5Okhb3eDMb/9o0EoglReHunNT9ukrJAI=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
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/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.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.2.20-0.20231212123824-8836b6754226 h1:rcII71ho6F/7Nyx7n2kESLcnvNMdcU4i8ZUGF2Fi7yA=
|
||||||
github.com/sagernet/sing v0.2.20-0.20231208065534-70794cb91cc5 h1:rDt9HgEcIjiSv/o2OBN/SyqFiMhx16qAlHPFkEpvcq8=
|
github.com/sagernet/sing v0.2.20-0.20231212123824-8836b6754226/go.mod h1:Ce5LNojQOgOiWhiD8pPD6E9H7e2KgtOe3Zxx4Ou5u80=
|
||||||
github.com/sagernet/sing v0.2.20-0.20231208065534-70794cb91cc5/go.mod h1:Ce5LNojQOgOiWhiD8pPD6E9H7e2KgtOe3Zxx4Ou5u80=
|
|
||||||
github.com/sagernet/sing-dns v0.1.11 h1:PPrMCVVrAeR3f5X23I+cmvacXJ+kzuyAsBiWyUKhGSE=
|
github.com/sagernet/sing-dns v0.1.11 h1:PPrMCVVrAeR3f5X23I+cmvacXJ+kzuyAsBiWyUKhGSE=
|
||||||
github.com/sagernet/sing-dns v0.1.11/go.mod h1:zJ/YjnYB61SYE+ubMcMqVdpaSvsyQ2iShQGO3vuLvvE=
|
github.com/sagernet/sing-dns v0.1.11/go.mod h1:zJ/YjnYB61SYE+ubMcMqVdpaSvsyQ2iShQGO3vuLvvE=
|
||||||
github.com/sagernet/sing-mux v0.1.5 h1:jUbYth9QQd1wsDmU8Ush+fKce7lNo9TMv2dp8PJtSOY=
|
github.com/sagernet/sing-mux v0.1.6-0.20231208180947-9053c29513a2 h1:rRlYQPbMKmzKX+43XC04gEQvxc45/AxfteRWfcl2/rw=
|
||||||
github.com/sagernet/sing-mux v0.1.5/go.mod h1:MoH6Soz1R+CYZcCeIXZWx6fkZa6hQc9o3HZu9G6CDTw=
|
github.com/sagernet/sing-mux v0.1.6-0.20231208180947-9053c29513a2/go.mod h1:IdSrwwqBeJTrjLZJRFXE+F8mYXNI/rPAjzlgTFuEVmo=
|
||||||
github.com/sagernet/sing-quic v0.1.5 h1:PIQzE4cGrry+JkkMEJH/EH3wRkv/QgD48+ScNr/2oig=
|
github.com/sagernet/sing-quic v0.1.6-0.20231207143711-eb3cbf9ed054 h1:Ed7FskwQcep5oQ+QahgVK0F6jPPSV8Nqwjr9MwGatMU=
|
||||||
github.com/sagernet/sing-quic v0.1.5/go.mod h1:n2mXukpubasyV4SlWyyW0+LCdAn7DZ8/brAkUxZujrw=
|
github.com/sagernet/sing-quic v0.1.6-0.20231207143711-eb3cbf9ed054/go.mod h1:u758WWv3G1OITG365CYblL0NfAruFL1PpLD9DUVTv1o=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
|
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.5 h1:JDeAJ4ZWlYZ7F6qEVdDKPhQEangxKw/JtmU+i/YfCYE=
|
github.com/sagernet/sing-shadowsocks2 v0.1.6-0.20231207143709-50439739601a h1:uYIKfpE1/EJpa+1Bja7b006VixeRuVduOpeuesMk2lU=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.5/go.mod h1:KF65y8lI5PGHyMgRZGYXYsH9ilgRc/yr+NYbSNGuBm4=
|
github.com/sagernet/sing-shadowsocks2 v0.1.6-0.20231207143709-50439739601a/go.mod h1:pjeylQ4ApvpEH7B4PUBrdyJf4xmQkg8BaIzT5fI2fR0=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||||
github.com/sagernet/sing-tun v0.1.24-0.20231212055255-69c3b72eec62 h1:2UxHpIewr/cakD7qspPtQUI1UzLS8V9HvAYezE8JiVA=
|
github.com/sagernet/sing-tun v0.1.24-0.20231212060935-6a1419aeae11 h1:crTOVPJGOGWOW+Q2a0FQiiS/G2+W6uCLKtOofFMisQc=
|
||||||
github.com/sagernet/sing-tun v0.1.24-0.20231212055255-69c3b72eec62/go.mod h1:Mnd7+8iGNb9uGnMAh3bp0ZA+nPFBZNaMHZPMEGdAQJM=
|
github.com/sagernet/sing-tun v0.1.24-0.20231212060935-6a1419aeae11/go.mod h1:DgXPnBqtqWrZj37Mun/W61dW0Q56eLqTZYhcuNLaCtY=
|
||||||
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
||||||
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 h1:Px+hN4Vzgx+iCGVnWH5A8eR7JhNnIV3rGQmBxA7cw6Q=
|
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 h1:Px+hN4Vzgx+iCGVnWH5A8eR7JhNnIV3rGQmBxA7cw6Q=
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6/go.mod h1:zovq6vTvEM6ECiqE3Eeb9rpIylPpamPcmrJ9tv0Bt0M=
|
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6/go.mod h1:zovq6vTvEM6ECiqE3Eeb9rpIylPpamPcmrJ9tv0Bt0M=
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4=
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4=
|
||||||
@ -185,10 +182,10 @@ golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/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-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
@ -197,8 +194,8 @@ 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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
|
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
|
||||||
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
||||||
|
@ -26,7 +26,7 @@ var (
|
|||||||
|
|
||||||
type HTTP struct {
|
type HTTP struct {
|
||||||
myInboundAdapter
|
myInboundAdapter
|
||||||
authenticator auth.Authenticator
|
authenticator *auth.Authenticator
|
||||||
tlsConfig tls.ServerConfig
|
tlsConfig tls.ServerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ var (
|
|||||||
|
|
||||||
type Mixed struct {
|
type Mixed struct {
|
||||||
myInboundAdapter
|
myInboundAdapter
|
||||||
authenticator auth.Authenticator
|
authenticator *auth.Authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMixed(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPMixedInboundOptions) *Mixed {
|
func NewMixed(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPMixedInboundOptions) *Mixed {
|
||||||
|
@ -32,7 +32,7 @@ var _ adapter.Inbound = (*Naive)(nil)
|
|||||||
|
|
||||||
type Naive struct {
|
type Naive struct {
|
||||||
myInboundAdapter
|
myInboundAdapter
|
||||||
authenticator auth.Authenticator
|
authenticator *auth.Authenticator
|
||||||
tlsConfig tls.ServerConfig
|
tlsConfig tls.ServerConfig
|
||||||
httpServer *http.Server
|
httpServer *http.Server
|
||||||
h3Server any
|
h3Server any
|
||||||
|
@ -22,7 +22,7 @@ var (
|
|||||||
|
|
||||||
type Socks struct {
|
type Socks struct {
|
||||||
myInboundAdapter
|
myInboundAdapter
|
||||||
authenticator auth.Authenticator
|
authenticator *auth.Authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSocks(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.SocksInboundOptions) *Socks {
|
func NewSocks(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.SocksInboundOptions) *Socks {
|
||||||
|
@ -43,6 +43,10 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
|||||||
if tunMTU == 0 {
|
if tunMTU == 0 {
|
||||||
tunMTU = 9000
|
tunMTU = 9000
|
||||||
}
|
}
|
||||||
|
gsoMaxSize := options.GSOMaxSize
|
||||||
|
if gsoMaxSize == 0 {
|
||||||
|
gsoMaxSize = 65536
|
||||||
|
}
|
||||||
var udpTimeout int64
|
var udpTimeout int64
|
||||||
if options.UDPTimeout != 0 {
|
if options.UDPTimeout != 0 {
|
||||||
udpTimeout = options.UDPTimeout
|
udpTimeout = options.UDPTimeout
|
||||||
@ -74,6 +78,8 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
|||||||
tunOptions: tun.Options{
|
tunOptions: tun.Options{
|
||||||
Name: options.InterfaceName,
|
Name: options.InterfaceName,
|
||||||
MTU: tunMTU,
|
MTU: tunMTU,
|
||||||
|
GSO: options.GSO,
|
||||||
|
GSOMaxSize: gsoMaxSize,
|
||||||
Inet4Address: options.Inet4Address,
|
Inet4Address: options.Inet4Address,
|
||||||
Inet6Address: options.Inet6Address,
|
Inet6Address: options.Inet6Address,
|
||||||
AutoRoute: options.AutoRoute,
|
AutoRoute: options.AutoRoute,
|
||||||
@ -167,10 +173,7 @@ func (t *Tun) Start() error {
|
|||||||
t.tunStack, err = tun.NewStack(t.stack, tun.StackOptions{
|
t.tunStack, err = tun.NewStack(t.stack, tun.StackOptions{
|
||||||
Context: t.ctx,
|
Context: t.ctx,
|
||||||
Tun: tunInterface,
|
Tun: tunInterface,
|
||||||
MTU: t.tunOptions.MTU,
|
TunOptions: t.tunOptions,
|
||||||
Name: t.tunOptions.Name,
|
|
||||||
Inet4Address: t.tunOptions.Inet4Address,
|
|
||||||
Inet6Address: t.tunOptions.Inet6Address,
|
|
||||||
EndpointIndependentNat: t.endpointIndependentNat,
|
EndpointIndependentNat: t.endpointIndependentNat,
|
||||||
UDPTimeout: t.udpTimeout,
|
UDPTimeout: t.udpTimeout,
|
||||||
Handler: t,
|
Handler: t,
|
||||||
|
@ -5,6 +5,8 @@ import "net/netip"
|
|||||||
type TunInboundOptions struct {
|
type TunInboundOptions struct {
|
||||||
InterfaceName string `json:"interface_name,omitempty"`
|
InterfaceName string `json:"interface_name,omitempty"`
|
||||||
MTU uint32 `json:"mtu,omitempty"`
|
MTU uint32 `json:"mtu,omitempty"`
|
||||||
|
GSO bool `json:"gso,omitempty"`
|
||||||
|
GSOMaxSize uint32 `json:"gso_max_size,omitempty"`
|
||||||
Inet4Address Listable[netip.Prefix] `json:"inet4_address,omitempty"`
|
Inet4Address Listable[netip.Prefix] `json:"inet4_address,omitempty"`
|
||||||
Inet6Address Listable[netip.Prefix] `json:"inet6_address,omitempty"`
|
Inet6Address Listable[netip.Prefix] `json:"inet6_address,omitempty"`
|
||||||
AutoRoute bool `json:"auto_route,omitempty"`
|
AutoRoute bool `json:"auto_route,omitempty"`
|
||||||
|
@ -5,6 +5,8 @@ import "net/netip"
|
|||||||
type WireGuardOutboundOptions struct {
|
type WireGuardOutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
SystemInterface bool `json:"system_interface,omitempty"`
|
SystemInterface bool `json:"system_interface,omitempty"`
|
||||||
|
GSO bool `json:"gso,omitempty"`
|
||||||
|
GSOMaxSize uint32 `json:"gso_max_size,omitempty"`
|
||||||
InterfaceName string `json:"interface_name,omitempty"`
|
InterfaceName string `json:"interface_name,omitempty"`
|
||||||
LocalAddress Listable[netip.Prefix] `json:"local_address"`
|
LocalAddress Listable[netip.Prefix] `json:"local_address"`
|
||||||
PrivateKey string `json:"private_key"`
|
PrivateKey string `json:"private_key"`
|
||||||
|
@ -111,6 +111,9 @@ func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metada
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if readWaiter, created := bufio.CreatePacketReadWaiter(reader); created {
|
if readWaiter, created := bufio.CreatePacketReadWaiter(reader); created {
|
||||||
|
readWaiter.InitializeReadWaiter(N.ReadWaitOptions{
|
||||||
|
MTU: dns.FixedPacketSize,
|
||||||
|
})
|
||||||
return d.newPacketConnection(ctx, conn, readWaiter, counters, cachedPackets, metadata)
|
return d.newPacketConnection(ctx, conn, readWaiter, counters, cachedPackets, metadata)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@ -193,15 +196,13 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
|
|||||||
timeout := canceler.New(fastClose, cancel, C.DNSTimeout)
|
timeout := canceler.New(fastClose, cancel, C.DNSTimeout)
|
||||||
var group task.Group
|
var group task.Group
|
||||||
group.Append0(func(ctx context.Context) error {
|
group.Append0(func(ctx context.Context) error {
|
||||||
var buffer *buf.Buffer
|
|
||||||
readWaiter.InitializeReadWaiter(func() *buf.Buffer {
|
|
||||||
return buf.NewSize(dns.FixedPacketSize)
|
|
||||||
})
|
|
||||||
defer readWaiter.InitializeReadWaiter(nil)
|
|
||||||
for {
|
for {
|
||||||
var message mDNS.Msg
|
var (
|
||||||
var destination M.Socksaddr
|
message mDNS.Msg
|
||||||
var err error
|
destination M.Socksaddr
|
||||||
|
err error
|
||||||
|
buffer *buf.Buffer
|
||||||
|
)
|
||||||
if len(cached) > 0 {
|
if len(cached) > 0 {
|
||||||
packet := cached[0]
|
packet := cached[0]
|
||||||
cached = cached[1:]
|
cached = cached[1:]
|
||||||
@ -216,9 +217,8 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
|
|||||||
}
|
}
|
||||||
destination = packet.Destination
|
destination = packet.Destination
|
||||||
} else {
|
} else {
|
||||||
destination, err = readWaiter.WaitReadPacket()
|
buffer, destination, err = readWaiter.WaitReadPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
buffer.Release()
|
|
||||||
cancel(err)
|
cancel(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ type ProxyListener struct {
|
|||||||
tcpListener *net.TCPListener
|
tcpListener *net.TCPListener
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
authenticator auth.Authenticator
|
authenticator *auth.Authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProxyListener(ctx context.Context, logger log.ContextLogger, dialer N.Dialer) *ProxyListener {
|
func NewProxyListener(ctx context.Context, logger log.ContextLogger, dialer N.Dialer) *ProxyListener {
|
||||||
|
@ -163,7 +163,7 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
|
|||||||
if !options.SystemInterface && tun.WithGVisor {
|
if !options.SystemInterface && tun.WithGVisor {
|
||||||
wireTunDevice, err = wireguard.NewStackDevice(options.LocalAddress, mtu)
|
wireTunDevice, err = wireguard.NewStackDevice(options.LocalAddress, mtu)
|
||||||
} else {
|
} else {
|
||||||
wireTunDevice, err = wireguard.NewSystemDevice(router, options.InterfaceName, options.LocalAddress, mtu)
|
wireTunDevice, err = wireguard.NewSystemDevice(router, options.InterfaceName, options.LocalAddress, mtu, options.GSO, options.GSOMaxSize)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "create WireGuard device")
|
return nil, E.Cause(err, "create WireGuard device")
|
||||||
|
@ -126,7 +126,7 @@ func (s *RemoteRuleSet) loadBytes(content []byte) error {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
switch s.options.Format {
|
switch s.options.Format {
|
||||||
case C.RuleSetFormatSource, "":
|
case C.RuleSetFormatSource:
|
||||||
var compat option.PlainRuleSetCompat
|
var compat option.PlainRuleSetCompat
|
||||||
decoder := json.NewDecoder(json.NewCommentFilter(bytes.NewReader(content)))
|
decoder := json.NewDecoder(json.NewCommentFilter(bytes.NewReader(content)))
|
||||||
decoder.DisallowUnknownFields()
|
decoder.DisallowUnknownFields()
|
||||||
|
@ -17,16 +17,16 @@ func (c *NATPacketConn) CreatePacketReadWaiter() (N.PacketReadWaiter, bool) {
|
|||||||
|
|
||||||
type waitNATPacketConn struct {
|
type waitNATPacketConn struct {
|
||||||
*NATPacketConn
|
*NATPacketConn
|
||||||
waiter N.PacketReadWaiter
|
readWaiter N.PacketReadWaiter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *waitNATPacketConn) InitializeReadWaiter(newBuffer func() *buf.Buffer) {
|
func (c *waitNATPacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
||||||
c.waiter.InitializeReadWaiter(newBuffer)
|
return c.readWaiter.InitializeReadWaiter(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *waitNATPacketConn) WaitReadPacket() (destination M.Socksaddr, err error) {
|
func (c *waitNATPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
||||||
destination, err = c.waiter.WaitReadPacket()
|
buffer, destination, err = c.readWaiter.WaitReadPacket()
|
||||||
if socksaddrWithoutPort(destination) == c.origin {
|
if err == nil && socksaddrWithoutPort(destination) == c.origin {
|
||||||
destination = M.Socksaddr{
|
destination = M.Socksaddr{
|
||||||
Addr: c.destination.Addr,
|
Addr: c.destination.Addr,
|
||||||
Fqdn: c.destination.Fqdn,
|
Fqdn: c.destination.Fqdn,
|
||||||
|
@ -53,7 +53,7 @@ func newMuxConnection0(ctx context.Context, stream net.Conn, metadata M.Metadata
|
|||||||
case CommandTCP:
|
case CommandTCP:
|
||||||
return handler.NewConnection(ctx, stream, metadata)
|
return handler.NewConnection(ctx, stream, metadata)
|
||||||
case CommandUDP:
|
case CommandUDP:
|
||||||
return handler.NewPacketConnection(ctx, &PacketConn{stream}, metadata)
|
return handler.NewPacketConnection(ctx, &PacketConn{Conn: stream}, metadata)
|
||||||
default:
|
default:
|
||||||
return E.New("unknown command ", command)
|
return E.New("unknown command ", command)
|
||||||
}
|
}
|
||||||
|
@ -85,9 +85,10 @@ func (c *ClientConn) Upstream() any {
|
|||||||
|
|
||||||
type ClientPacketConn struct {
|
type ClientPacketConn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
key [KeyLength]byte
|
key [KeyLength]byte
|
||||||
headerWritten bool
|
headerWritten bool
|
||||||
|
readWaitOptions N.ReadWaitOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientPacketConn(conn net.Conn, key [KeyLength]byte) *ClientPacketConn {
|
func NewClientPacketConn(conn net.Conn, key [KeyLength]byte) *ClientPacketConn {
|
||||||
|
45
transport/trojan/protocol_wait.go
Normal file
45
transport/trojan/protocol_wait.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package trojan
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
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/common/rw"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ N.PacketReadWaiter = (*ClientPacketConn)(nil)
|
||||||
|
|
||||||
|
func (c *ClientPacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
||||||
|
c.readWaitOptions = options
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
||||||
|
destination, err = M.SocksaddrSerializer.ReadAddrPort(c.Conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, M.Socksaddr{}, E.Cause(err, "read destination")
|
||||||
|
}
|
||||||
|
|
||||||
|
var length uint16
|
||||||
|
err = binary.Read(c.Conn, binary.BigEndian, &length)
|
||||||
|
if err != nil {
|
||||||
|
return nil, M.Socksaddr{}, E.Cause(err, "read chunk length")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rw.SkipN(c.Conn, 2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, M.Socksaddr{}, E.Cause(err, "skip crlf")
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = c.readWaitOptions.NewPacketBuffer()
|
||||||
|
_, err = buffer.ReadFullFrom(c.Conn, int(length))
|
||||||
|
if err != nil {
|
||||||
|
buffer.Release()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.readWaitOptions.PostReturn(buffer)
|
||||||
|
return
|
||||||
|
}
|
@ -105,7 +105,7 @@ func (s *Service[K]) NewConnection(ctx context.Context, conn net.Conn, metadata
|
|||||||
case CommandTCP:
|
case CommandTCP:
|
||||||
return s.handler.NewConnection(ctx, conn, metadata)
|
return s.handler.NewConnection(ctx, conn, metadata)
|
||||||
case CommandUDP:
|
case CommandUDP:
|
||||||
return s.handler.NewPacketConnection(ctx, &PacketConn{conn}, metadata)
|
return s.handler.NewPacketConnection(ctx, &PacketConn{Conn: conn}, metadata)
|
||||||
// case CommandMux:
|
// case CommandMux:
|
||||||
default:
|
default:
|
||||||
return HandleMuxConnection(ctx, conn, metadata, s.handler)
|
return HandleMuxConnection(ctx, conn, metadata, s.handler)
|
||||||
@ -122,6 +122,7 @@ func (s *Service[K]) fallback(ctx context.Context, conn net.Conn, metadata M.Met
|
|||||||
|
|
||||||
type PacketConn struct {
|
type PacketConn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
|
readWaitOptions N.ReadWaitOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
func (c *PacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
||||||
|
45
transport/trojan/service_wait.go
Normal file
45
transport/trojan/service_wait.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package trojan
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
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/common/rw"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ N.PacketReadWaiter = (*PacketConn)(nil)
|
||||||
|
|
||||||
|
func (c *PacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
||||||
|
c.readWaitOptions = options
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
||||||
|
destination, err = M.SocksaddrSerializer.ReadAddrPort(c.Conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, M.Socksaddr{}, E.Cause(err, "read destination")
|
||||||
|
}
|
||||||
|
|
||||||
|
var length uint16
|
||||||
|
err = binary.Read(c.Conn, binary.BigEndian, &length)
|
||||||
|
if err != nil {
|
||||||
|
return nil, M.Socksaddr{}, E.Cause(err, "read chunk length")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rw.SkipN(c.Conn, 2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, M.Socksaddr{}, E.Cause(err, "skip crlf")
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = c.readWaitOptions.NewPacketBuffer()
|
||||||
|
_, err = buffer.ReadFullFrom(c.Conn, int(length))
|
||||||
|
if err != nil {
|
||||||
|
buffer.Release()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.readWaitOptions.PostReturn(buffer)
|
||||||
|
return
|
||||||
|
}
|
@ -76,11 +76,8 @@ func (c *ClientBind) connect() (*wireConn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c.conn = &wireConn{
|
c.conn = &wireConn{
|
||||||
PacketConn: &bufio.UnbindPacketConn{
|
PacketConn: bufio.NewUnbindPacketConn(udpConn),
|
||||||
ExtendedConn: bufio.NewExtendedConn(udpConn),
|
done: make(chan struct{}),
|
||||||
Addr: c.connectAddr,
|
|
||||||
},
|
|
||||||
done: make(chan struct{}),
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
udpConn, err := c.dialer.ListenPacket(c.ctx, M.Socksaddr{Addr: netip.IPv4Unspecified()})
|
udpConn, err := c.dialer.ListenPacket(c.ctx, M.Socksaddr{Addr: netip.IPv4Unspecified()})
|
||||||
|
@ -2,6 +2,7 @@ package wireguard
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
@ -19,16 +20,17 @@ import (
|
|||||||
var _ Device = (*SystemDevice)(nil)
|
var _ Device = (*SystemDevice)(nil)
|
||||||
|
|
||||||
type SystemDevice struct {
|
type SystemDevice struct {
|
||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
device tun.Tun
|
device tun.Tun
|
||||||
name string
|
frontHeadroom int
|
||||||
mtu int
|
name string
|
||||||
events chan wgTun.Event
|
mtu int
|
||||||
addr4 netip.Addr
|
events chan wgTun.Event
|
||||||
addr6 netip.Addr
|
addr4 netip.Addr
|
||||||
|
addr6 netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32) (*SystemDevice, error) {
|
func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32, gso bool, gsoMaxsize uint32) (*SystemDevice, error) {
|
||||||
var inet4Addresses []netip.Prefix
|
var inet4Addresses []netip.Prefix
|
||||||
var inet6Addresses []netip.Prefix
|
var inet6Addresses []netip.Prefix
|
||||||
for _, prefixes := range localPrefixes {
|
for _, prefixes := range localPrefixes {
|
||||||
@ -41,11 +43,16 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
|
|||||||
if interfaceName == "" {
|
if interfaceName == "" {
|
||||||
interfaceName = tun.CalculateInterfaceName("wg")
|
interfaceName = tun.CalculateInterfaceName("wg")
|
||||||
}
|
}
|
||||||
|
if gsoMaxsize == 0 {
|
||||||
|
gsoMaxsize = 65536
|
||||||
|
}
|
||||||
tunInterface, err := tun.New(tun.Options{
|
tunInterface, err := tun.New(tun.Options{
|
||||||
Name: interfaceName,
|
Name: interfaceName,
|
||||||
Inet4Address: inet4Addresses,
|
Inet4Address: inet4Addresses,
|
||||||
Inet6Address: inet6Addresses,
|
Inet6Address: inet6Addresses,
|
||||||
MTU: mtu,
|
MTU: mtu,
|
||||||
|
GSO: gso,
|
||||||
|
GSOMaxSize: gsoMaxsize,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -62,12 +69,13 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
|
|||||||
dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{
|
dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{
|
||||||
BindInterface: interfaceName,
|
BindInterface: interfaceName,
|
||||||
})),
|
})),
|
||||||
device: tunInterface,
|
device: tunInterface,
|
||||||
name: interfaceName,
|
frontHeadroom: tunInterface.FrontHeadroom(),
|
||||||
mtu: int(mtu),
|
name: interfaceName,
|
||||||
events: make(chan wgTun.Event),
|
mtu: int(mtu),
|
||||||
addr4: inet4Address,
|
events: make(chan wgTun.Event),
|
||||||
addr6: inet6Address,
|
addr4: inet4Address,
|
||||||
|
addr6: inet6Address,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,16 +105,18 @@ func (w *SystemDevice) File() *os.File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *SystemDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
|
func (w *SystemDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
|
||||||
sizes[0], err = w.device.Read(bufs[0][offset-tun.PacketOffset:])
|
sizes[0], err = w.device.Read(bufs[0][offset-w.frontHeadroom:])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
count = 1
|
count = 1
|
||||||
|
} else if errors.Is(err, tun.ErrTooManySegments) {
|
||||||
|
err = wgTun.ErrTooManySegments
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SystemDevice) Write(bufs [][]byte, offset int) (count int, err error) {
|
func (w *SystemDevice) Write(bufs [][]byte, offset int) (count int, err error) {
|
||||||
for _, b := range bufs {
|
for _, b := range bufs {
|
||||||
_, err = w.device.Write(b[offset:])
|
_, err = w.device.Write(b[offset-w.frontHeadroom:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user