mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-09-10 13:24:08 +08:00
Compare commits
22 Commits
c4207d86d0
...
5e96b57825
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5e96b57825 | ||
![]() |
12e8d43925 | ||
![]() |
f13327f4d2 | ||
![]() |
e1f54d429a | ||
![]() |
19f9af5945 | ||
![]() |
b0fc436a16 | ||
![]() |
53bb549809 | ||
![]() |
e7de4f5a88 | ||
![]() |
8583c6e509 | ||
![]() |
a67f3d8be2 | ||
![]() |
87ed5f86d8 | ||
![]() |
e53122d255 | ||
![]() |
5982358407 | ||
![]() |
490daad0a7 | ||
![]() |
b1ea333bd4 | ||
![]() |
e69b61747f | ||
![]() |
16d8f108ca | ||
![]() |
ffdfb3237c | ||
![]() |
92b6cc4904 | ||
![]() |
c630819ee9 | ||
![]() |
e9f519aafc | ||
![]() |
84279243ce |
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.0
|
||||
- name: Check input version
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |-
|
||||
@ -110,7 +110,7 @@ jobs:
|
||||
if: ${{ ! (matrix.legacy_go123 || matrix.legacy_go124) }}
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.0
|
||||
- name: Setup Go 1.24
|
||||
if: matrix.legacy_go124
|
||||
uses: actions/setup-go@v6
|
||||
@ -300,7 +300,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.0
|
||||
- name: Setup Android NDK
|
||||
id: setup-ndk
|
||||
uses: nttld/setup-ndk@v1
|
||||
@ -380,7 +380,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.0
|
||||
- name: Setup Android NDK
|
||||
id: setup-ndk
|
||||
uses: nttld/setup-ndk@v1
|
||||
@ -478,7 +478,7 @@ jobs:
|
||||
if: matrix.if
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.0
|
||||
- name: Setup Xcode stable
|
||||
if: matrix.if && github.ref == 'refs/heads/main-next'
|
||||
run: |-
|
||||
|
4
.github/workflows/linux.yml
vendored
4
.github/workflows/linux.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.0
|
||||
- name: Check input version
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |-
|
||||
@ -71,7 +71,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ^1.25.1
|
||||
go-version: ^1.25.0
|
||||
- name: Setup Android NDK
|
||||
if: matrix.os == 'android'
|
||||
uses: nttld/setup-ndk@v1
|
||||
|
@ -5,8 +5,6 @@ import (
|
||||
"strings"
|
||||
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
type Version struct {
|
||||
@ -18,19 +16,7 @@ type Version struct {
|
||||
PreReleaseVersion int
|
||||
}
|
||||
|
||||
func (v Version) LessThan(anotherVersion Version) bool {
|
||||
return !v.GreaterThanOrEqual(anotherVersion)
|
||||
}
|
||||
|
||||
func (v Version) LessThanOrEqual(anotherVersion Version) bool {
|
||||
return v == anotherVersion || anotherVersion.GreaterThan(v)
|
||||
}
|
||||
|
||||
func (v Version) GreaterThanOrEqual(anotherVersion Version) bool {
|
||||
return v == anotherVersion || v.GreaterThan(anotherVersion)
|
||||
}
|
||||
|
||||
func (v Version) GreaterThan(anotherVersion Version) bool {
|
||||
func (v Version) After(anotherVersion Version) bool {
|
||||
if v.Major > anotherVersion.Major {
|
||||
return true
|
||||
} else if v.Major < anotherVersion.Major {
|
||||
@ -58,27 +44,21 @@ func (v Version) GreaterThan(anotherVersion Version) bool {
|
||||
} else if v.PreReleaseVersion < anotherVersion.PreReleaseVersion {
|
||||
return false
|
||||
}
|
||||
}
|
||||
preReleaseIdentifier := parsePreReleaseIdentifier(v.PreReleaseIdentifier)
|
||||
anotherPreReleaseIdentifier := parsePreReleaseIdentifier(anotherVersion.PreReleaseIdentifier)
|
||||
if preReleaseIdentifier < anotherPreReleaseIdentifier {
|
||||
} else if v.PreReleaseIdentifier == "rc" && anotherVersion.PreReleaseIdentifier == "beta" {
|
||||
return true
|
||||
} else if preReleaseIdentifier > anotherPreReleaseIdentifier {
|
||||
} else if v.PreReleaseIdentifier == "beta" && anotherVersion.PreReleaseIdentifier == "rc" {
|
||||
return false
|
||||
} else if v.PreReleaseIdentifier == "beta" && anotherVersion.PreReleaseIdentifier == "alpha" {
|
||||
return true
|
||||
} else if v.PreReleaseIdentifier == "alpha" && anotherVersion.PreReleaseIdentifier == "beta" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parsePreReleaseIdentifier(identifier string) int {
|
||||
if strings.HasPrefix(identifier, "rc") {
|
||||
return 1
|
||||
} else if strings.HasPrefix(identifier, "beta") {
|
||||
return 2
|
||||
} else if strings.HasPrefix(identifier, "alpha") {
|
||||
return 3
|
||||
}
|
||||
return 0
|
||||
func (v Version) VersionString() string {
|
||||
return F.ToString(v.Major, ".", v.Minor, ".", v.Patch)
|
||||
}
|
||||
|
||||
func (v Version) String() string {
|
||||
@ -103,10 +83,6 @@ func (v Version) BadString() string {
|
||||
return version
|
||||
}
|
||||
|
||||
func IsValid(versionName string) bool {
|
||||
return semver.IsValid("v" + versionName)
|
||||
}
|
||||
|
||||
func Parse(versionName string) (version Version) {
|
||||
if strings.HasPrefix(versionName, "v") {
|
||||
versionName = versionName[1:]
|
||||
|
@ -10,9 +10,9 @@ func TestCompareVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
require.Equal(t, "1.3.0-beta.1", Parse("v1.3.0-beta1").String())
|
||||
require.Equal(t, "1.3-beta1", Parse("v1.3.0-beta.1").BadString())
|
||||
require.True(t, Parse("1.3.0").GreaterThan(Parse("1.3-beta1")))
|
||||
require.True(t, Parse("1.3.0").GreaterThan(Parse("1.3.0-beta1")))
|
||||
require.True(t, Parse("1.3.0-beta1").GreaterThan(Parse("1.3.0-alpha1")))
|
||||
require.True(t, Parse("1.3.1").GreaterThan(Parse("1.3.0")))
|
||||
require.True(t, Parse("1.4").GreaterThan(Parse("1.3")))
|
||||
require.True(t, Parse("1.3.0").After(Parse("1.3-beta1")))
|
||||
require.True(t, Parse("1.3.0").After(Parse("1.3.0-beta1")))
|
||||
require.True(t, Parse("1.3.0-beta1").After(Parse("1.3.0-alpha1")))
|
||||
require.True(t, Parse("1.3.1").After(Parse("1.3.0")))
|
||||
require.True(t, Parse("1.4").After(Parse("1.3")))
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/sagernet/sing-box/common/badtls"
|
||||
// C "github.com/sagernet/sing-box/constant"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
@ -28,6 +29,8 @@ type Conn struct {
|
||||
readWaitOptions N.ReadWaitOptions
|
||||
kernelTx bool
|
||||
kernelRx bool
|
||||
kernelDidRead bool
|
||||
kernelDidWrite bool
|
||||
}
|
||||
|
||||
func NewConn(ctx context.Context, logger logger.ContextLogger, conn aTLS.Conn, txOffload, rxOffload bool) (aTLS.Conn, error) {
|
||||
@ -61,7 +64,7 @@ func NewConn(ctx context.Context, logger logger.ContextLogger, conn aTLS.Conn, t
|
||||
for rawConn.Hand.Len() > 0 {
|
||||
err = rawConn.HandlePostHandshakeMessage()
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "handle post-handshake messages")
|
||||
return nil, E.Cause(err, "ktls: failed to handle post-handshake messages")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,15 +85,36 @@ func NewConn(ctx context.Context, logger logger.ContextLogger, conn aTLS.Conn, t
|
||||
}
|
||||
|
||||
func (c *Conn) Upstream() any {
|
||||
return c.Conn
|
||||
return c.conn
|
||||
}
|
||||
|
||||
func (c *Conn) ReaderReplaceable() bool {
|
||||
if !c.kernelRx {
|
||||
return true
|
||||
}
|
||||
c.rawConn.In.Lock()
|
||||
defer c.rawConn.In.Unlock()
|
||||
return !c.kernelDidRead
|
||||
}
|
||||
|
||||
func (c *Conn) WriterReplaceable() bool {
|
||||
if !c.kernelTx {
|
||||
return true
|
||||
}
|
||||
/*c.rawConn.Out.Lock()
|
||||
defer c.rawConn.Out.Unlock()
|
||||
return !c.kernelDidWrite*/
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Conn) SyscallConnForRead() syscall.Conn {
|
||||
if !c.kernelRx {
|
||||
return nil
|
||||
}
|
||||
if !*c.rawConn.IsClient {
|
||||
c.logger.WarnContext(c.ctx, "ktls: RX splice is unavailable on the server size, since it will cause an unknown failure")
|
||||
c.rawConn.In.Lock()
|
||||
defer c.rawConn.In.Unlock()
|
||||
if c.kernelDidRead {
|
||||
c.logger.DebugContext(c.ctx, "ktls: RX splice not possible, since did read from user space")
|
||||
return nil
|
||||
}
|
||||
c.logger.DebugContext(c.ctx, "ktls: RX splice requested")
|
||||
@ -101,6 +125,13 @@ func (c *Conn) SyscallConnForWrite() syscall.Conn {
|
||||
if !c.kernelTx {
|
||||
return nil
|
||||
}
|
||||
/*c.rawConn.Out.Lock()
|
||||
defer c.rawConn.Out.Unlock()
|
||||
if c.kernelDidWrite {
|
||||
c.logger.DebugContext(c.ctx, "ktls: TX splice not possible, since did write from user space")
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
c.logger.DebugContext(c.ctx, "ktls: TX splice requested")
|
||||
return c.syscallConn
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/sagernet/sing-box/common/badversion"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/shell"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -55,42 +55,46 @@ var KernelSupport = sync.OnceValues(func() (*Support, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kernelVersion := badversion.Parse(strings.Trim(string(uname.Release[:]), "\x00"))
|
||||
kernelVersion, err := semver.Parse(strings.Trim(string(uname.Release[:]), "\x00"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kernelVersion.Pre = nil
|
||||
kernelVersion.Build = nil
|
||||
|
||||
var support Support
|
||||
|
||||
switch {
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 6, Minor: 14}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 6, Minor: 14}):
|
||||
support.TLS_Version13_KeyUpdate = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 6, Minor: 1}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 6, Minor: 1}):
|
||||
support.TLS_ARIA_GCM = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 6}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 6}):
|
||||
support.TLS_Version13_RX = true
|
||||
support.TLS_RX_NOPADDING = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 5, Minor: 19}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 5, Minor: 19}):
|
||||
support.TLS_TX_ZEROCOPY = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 5, Minor: 16}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 5, Minor: 16}):
|
||||
support.TLS_SM4 = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 5, Minor: 11}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 5, Minor: 11}):
|
||||
support.TLS_CHACHA20_POLY1305 = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 5, Minor: 2}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 5, Minor: 2}):
|
||||
support.TLS_AES_128_CCM = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 5, Minor: 1}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 5, Minor: 1}):
|
||||
support.TLS_AES_256_GCM = true
|
||||
support.TLS_Version13 = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 4, Minor: 17}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 4, Minor: 17}):
|
||||
support.TLS_RX = true
|
||||
fallthrough
|
||||
case kernelVersion.GreaterThanOrEqual(badversion.Version{Major: 4, Minor: 13}):
|
||||
case kernelVersion.GTE(semver.Version{Major: 4, Minor: 13}):
|
||||
support.TLS = true
|
||||
}
|
||||
|
||||
@ -114,7 +118,7 @@ var KernelSupport = sync.OnceValues(func() (*Support, error) {
|
||||
func Load() error {
|
||||
support, err := KernelSupport()
|
||||
if err != nil {
|
||||
return E.Cause(err, "ktls: check availability")
|
||||
return err
|
||||
}
|
||||
if !support.TLS || !support.TLS_Version13 {
|
||||
return E.New("ktls: kernel does not support TLS 1.3")
|
||||
@ -128,10 +132,10 @@ func (c *Conn) setupKernel(txOffload, rxOffload bool) error {
|
||||
}
|
||||
support, err := KernelSupport()
|
||||
if err != nil {
|
||||
return E.Cause(err, "check availability")
|
||||
return err
|
||||
}
|
||||
if !support.TLS || !support.TLS_Version13 {
|
||||
return E.New("kernel does not support TLS 1.3")
|
||||
return E.New("ktls: kernel does not support TLS 1.3")
|
||||
}
|
||||
c.rawConn.Out.Lock()
|
||||
defer c.rawConn.Out.Unlock()
|
||||
@ -139,13 +143,13 @@ func (c *Conn) setupKernel(txOffload, rxOffload bool) error {
|
||||
return syscall.SetsockoptString(int(fd), unix.SOL_TCP, unix.TCP_ULP, "tls")
|
||||
})
|
||||
if err != nil {
|
||||
return os.NewSyscallError("setsockopt", err)
|
||||
return E.Cause(err, "initialize kernel TLS")
|
||||
}
|
||||
|
||||
if txOffload {
|
||||
txCrypto := kernelCipher(support, c.rawConn.Out, *c.rawConn.CipherSuite, false)
|
||||
if txCrypto == nil {
|
||||
return E.New("unsupported cipher suite")
|
||||
return E.New("kTLS: unsupported cipher suite")
|
||||
}
|
||||
err = control.Raw(c.rawSyscallConn, func(fd uintptr) error {
|
||||
return syscall.SetsockoptString(int(fd), unix.SOL_TLS, TLS_TX, txCrypto.String())
|
||||
@ -168,7 +172,7 @@ func (c *Conn) setupKernel(txOffload, rxOffload bool) error {
|
||||
if rxOffload {
|
||||
rxCrypto := kernelCipher(support, c.rawConn.In, *c.rawConn.CipherSuite, true)
|
||||
if rxCrypto == nil {
|
||||
return E.New("unsupported cipher suite")
|
||||
return E.New("kTLS: unsupported cipher suite")
|
||||
}
|
||||
err = control.Raw(c.rawSyscallConn, func(fd uintptr) error {
|
||||
return syscall.SetsockoptString(int(fd), unix.SOL_TLS, TLS_RX, rxCrypto.String())
|
||||
@ -274,6 +278,7 @@ func (c *Conn) readKernelRecord() (uint8, []byte, error) {
|
||||
default:
|
||||
return 0, nil, err
|
||||
}
|
||||
c.kernelDidRead = true
|
||||
|
||||
if n <= 0 {
|
||||
return 0, nil, io.EOF
|
||||
@ -319,6 +324,7 @@ func (c *Conn) writeKernelRecord(typ uint16, data []byte) (int, error) {
|
||||
if ew != nil {
|
||||
return 0, ew
|
||||
}
|
||||
c.kernelDidWrite = true
|
||||
return n, err
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,7 @@ func NewDialerFromOptions(ctx context.Context, logger logger.ContextLogger, dial
|
||||
if !options.Enabled {
|
||||
return dialer, nil
|
||||
}
|
||||
config, err := NewClientWithOptions(ClientOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
ServerAddress: serverAddress,
|
||||
Options: options,
|
||||
})
|
||||
config, err := NewClient(ctx, logger, serverAddress, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -33,40 +28,15 @@ func NewDialerFromOptions(ctx context.Context, logger logger.ContextLogger, dial
|
||||
}
|
||||
|
||||
func NewClient(ctx context.Context, logger logger.ContextLogger, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
||||
return NewClientWithOptions(ClientOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
ServerAddress: serverAddress,
|
||||
Options: options,
|
||||
})
|
||||
}
|
||||
|
||||
type ClientOptions struct {
|
||||
Context context.Context
|
||||
Logger logger.ContextLogger
|
||||
ServerAddress string
|
||||
Options option.OutboundTLSOptions
|
||||
KTLSCompatible bool
|
||||
}
|
||||
|
||||
func NewClientWithOptions(options ClientOptions) (Config, error) {
|
||||
if !options.Options.Enabled {
|
||||
if !options.Enabled {
|
||||
return nil, nil
|
||||
}
|
||||
if !options.KTLSCompatible {
|
||||
if options.Options.KernelTx {
|
||||
options.Logger.Warn("enabling kTLS TX in current scenarios will definitely reduce performance, please checkout https://sing-box.sagernet.org/configuration/shared/tls/#kernel_tx")
|
||||
if options.Reality != nil && options.Reality.Enabled {
|
||||
return NewRealityClient(ctx, logger, serverAddress, options)
|
||||
} else if options.UTLS != nil && options.UTLS.Enabled {
|
||||
return NewUTLSClient(ctx, logger, serverAddress, options)
|
||||
}
|
||||
}
|
||||
if options.Options.KernelRx {
|
||||
options.Logger.Warn("enabling kTLS RX will definitely reduce performance, please checkout https://sing-box.sagernet.org/configuration/shared/tls/#kernel_rx")
|
||||
}
|
||||
if options.Options.Reality != nil && options.Options.Reality.Enabled {
|
||||
return NewRealityClient(options.Context, options.Logger, options.ServerAddress, options.Options)
|
||||
} else if options.Options.UTLS != nil && options.Options.UTLS.Enabled {
|
||||
return NewUTLSClient(options.Context, options.Logger, options.ServerAddress, options.Options)
|
||||
}
|
||||
return NewSTDClient(options.Context, options.Logger, options.ServerAddress, options.Options)
|
||||
return NewSTDClient(ctx, logger, serverAddress, options)
|
||||
}
|
||||
|
||||
func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, error) {
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing-box/common/ktls"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
aTLS "github.com/sagernet/sing/common/tls"
|
||||
)
|
||||
@ -21,12 +20,7 @@ func (w *KTLSClientConfig) ClientHandshake(ctx context.Context, conn net.Conn) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kConn, err := ktls.NewConn(ctx, w.logger, tlsConn, w.kernelTx, w.kernelRx)
|
||||
if err != nil {
|
||||
tlsConn.Close()
|
||||
return nil, E.Cause(err, "initialize kernel TLS")
|
||||
}
|
||||
return kConn, nil
|
||||
return ktls.NewConn(ctx, w.logger, tlsConn, w.kernelTx, w.kernelRx)
|
||||
}
|
||||
|
||||
func (w *KTLSClientConfig) Clone() Config {
|
||||
@ -49,12 +43,7 @@ func (w *KTlSServerConfig) ServerHandshake(ctx context.Context, conn net.Conn) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kConn, err := ktls.NewConn(ctx, w.logger, tlsConn, w.kernelTx, w.kernelRx)
|
||||
if err != nil {
|
||||
tlsConn.Close()
|
||||
return nil, E.Cause(err, "initialize kernel TLS")
|
||||
}
|
||||
return kConn, nil
|
||||
return ktls.NewConn(ctx, w.logger, tlsConn, w.kernelTx, w.kernelRx)
|
||||
}
|
||||
|
||||
func (w *KTlSServerConfig) Clone() Config {
|
||||
|
@ -12,37 +12,14 @@ import (
|
||||
aTLS "github.com/sagernet/sing/common/tls"
|
||||
)
|
||||
|
||||
type ServerOptions struct {
|
||||
Context context.Context
|
||||
Logger log.ContextLogger
|
||||
Options option.InboundTLSOptions
|
||||
KTLSCompatible bool
|
||||
}
|
||||
|
||||
func NewServer(ctx context.Context, logger log.ContextLogger, options option.InboundTLSOptions) (ServerConfig, error) {
|
||||
return NewServerWithOptions(ServerOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
Options: options,
|
||||
})
|
||||
}
|
||||
|
||||
func NewServerWithOptions(options ServerOptions) (ServerConfig, error) {
|
||||
if !options.Options.Enabled {
|
||||
if !options.Enabled {
|
||||
return nil, nil
|
||||
}
|
||||
if !options.KTLSCompatible {
|
||||
if options.Options.KernelTx {
|
||||
options.Logger.Warn("enabling kTLS TX in current scenarios will definitely reduce performance, please checkout https://sing-box.sagernet.org/configuration/shared/tls/#kernel_tx")
|
||||
if options.Reality != nil && options.Reality.Enabled {
|
||||
return NewRealityServer(ctx, logger, options)
|
||||
}
|
||||
}
|
||||
if options.Options.KernelRx {
|
||||
options.Logger.Warn("enabling kTLS RX will definitely reduce performance, please checkout https://sing-box.sagernet.org/configuration/shared/tls/#kernel_rx")
|
||||
}
|
||||
if options.Options.Reality != nil && options.Options.Reality.Enabled {
|
||||
return NewRealityServer(options.Context, options.Logger, options.Options)
|
||||
}
|
||||
return NewSTDServer(options.Context, options.Logger, options.Options)
|
||||
return NewSTDServer(ctx, logger, options)
|
||||
}
|
||||
|
||||
func ServerHandshake(ctx context.Context, conn net.Conn, config ServerConfig) (Conn, error) {
|
||||
|
@ -4,13 +4,8 @@ icon: material/alert-decagram
|
||||
|
||||
#### 1.13.0-alpha.9
|
||||
|
||||
* Add kTLS support **1**
|
||||
* Fixes and improvements
|
||||
|
||||
**1**:
|
||||
|
||||
See [TLS](/configuration/shared/tls/).
|
||||
|
||||
#### 1.12.4
|
||||
|
||||
* Fixes and improvements
|
||||
|
@ -1,12 +1,7 @@
|
||||
---
|
||||
icon: material/new-box
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
!!! quote "Changes in sing-box 1.13.0"
|
||||
|
||||
:material-plus: [kernel_tx](#kernel_tx)
|
||||
:material-plus: [kernel_rx](#kernel_rx)
|
||||
|
||||
!!! quote "Changes in sing-box 1.12.0"
|
||||
|
||||
:material-plus: [fragment](#fragment)
|
||||
@ -33,8 +28,6 @@ icon: material/new-box
|
||||
"certificate_path": "",
|
||||
"key": [],
|
||||
"key_path": "",
|
||||
"kernel_tx": false,
|
||||
"kernel_rx": false,
|
||||
"acme": {
|
||||
"domain": [],
|
||||
"data_directory": "",
|
||||
@ -195,8 +188,7 @@ By default, the maximum version is currently TLS 1.3.
|
||||
|
||||
#### cipher_suites
|
||||
|
||||
A list of enabled TLS 1.0–1.2 cipher suites. The order of the list is ignored.
|
||||
Note that TLS 1.3 cipher suites are not configurable.
|
||||
A list of enabled TLS 1.0–1.2 cipher suites. The order of the list is ignored. Note that TLS 1.3 cipher suites are not configurable.
|
||||
|
||||
If empty, a safe default list is used. The default cipher suites might change over time.
|
||||
|
||||
@ -228,50 +220,6 @@ The server private key line array, in PEM format.
|
||||
|
||||
The path to the server private key, in PEM format.
|
||||
|
||||
#### kernel_tx
|
||||
|
||||
!!! question "Since sing-box 1.13.0"
|
||||
|
||||
!!! quote ""
|
||||
|
||||
Only supported on Linux 5.1+, use a newer kernel if possible.
|
||||
|
||||
!!! quote ""
|
||||
|
||||
Only TLS 1.3 is supported.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
uTLS is compatible, but not other custom TLS.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
kTLS TX may only improve performance when `splice(2)` is available (both ends must be TCP or TLS without additional protocols after handshake); otherwise, it will definitely degrade performance.
|
||||
|
||||
Enable kernel TLS transmit support.
|
||||
|
||||
#### kernel_rx
|
||||
|
||||
!!! question "Since sing-box 1.13.0"
|
||||
|
||||
!!! quote ""
|
||||
|
||||
Only supported on Linux 5.1+, use a newer kernel if possible.
|
||||
|
||||
!!! quote ""
|
||||
|
||||
Only TLS 1.3 is supported.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
uTLS is compatible, but not other custom TLS.
|
||||
|
||||
!!! failure ""
|
||||
|
||||
kTLS RX will definitely degrade performance even if `splice(2)` is in use, so enabling it is not recommended.
|
||||
|
||||
Enable kernel TLS receive support.
|
||||
|
||||
## Custom TLS support
|
||||
|
||||
!!! info "QUIC support"
|
||||
|
@ -2,11 +2,6 @@
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
!!! quote "sing-box 1.13.0 中的更改"
|
||||
|
||||
:material-plus: [kernel_tx](#kernel_tx)
|
||||
:material-plus: [kernel_rx](#kernel_rx)
|
||||
|
||||
!!! quote "sing-box 1.12.0 中的更改"
|
||||
|
||||
:material-plus: [tls_fragment](#tls_fragment)
|
||||
@ -33,8 +28,6 @@ icon: material/alert-decagram
|
||||
"certificate_path": "",
|
||||
"key": [],
|
||||
"key_path": "",
|
||||
"kernel_tx": false,
|
||||
"kernel_rx": false,
|
||||
"acme": {
|
||||
"domain": [],
|
||||
"data_directory": "",
|
||||
@ -223,56 +216,6 @@ TLS 版本值:
|
||||
|
||||
服务器 PEM 私钥路径。
|
||||
|
||||
#### kernel_tx
|
||||
|
||||
!!! question "自 sing-box 1.13.0 起"
|
||||
|
||||
!!! quote ""
|
||||
|
||||
仅支持 Linux 5.1+,如果可能,使用较新的内核。
|
||||
|
||||
!!! quote ""
|
||||
|
||||
仅支持 TLS 1.3。
|
||||
|
||||
!!! warning ""
|
||||
|
||||
兼容 uTLS,但不兼容其他自定义 TLS。
|
||||
|
||||
!!! warning ""
|
||||
|
||||
kTLS TX 仅当 `splice(2)` 可用时(两端经过握手后必须为没有附加协议的 TCP 或 TLS)才能提高性能;否则肯定会降低性能。
|
||||
|
||||
启用内核 TLS 发送支持。
|
||||
|
||||
#### kernel_rx
|
||||
|
||||
!!! question "自 sing-box 1.13.0 起"
|
||||
|
||||
!!! quote ""
|
||||
|
||||
仅支持 Linux 5.1+,如果可能,使用较新的内核。
|
||||
|
||||
!!! quote ""
|
||||
|
||||
仅支持 TLS 1.3。
|
||||
|
||||
!!! warning ""
|
||||
|
||||
兼容 uTLS,但不兼容其他自定义 TLS。
|
||||
|
||||
!!! failure ""
|
||||
|
||||
即使使用 `splice(2)`,kTLS RX 也肯定会降低性能,因此不建议启用。
|
||||
|
||||
启用内核 TLS 接收支持。
|
||||
|
||||
## 自定义 TLS 支持
|
||||
|
||||
!!! info "QUIC 支持"
|
||||
|
||||
只有 ECH 在 QUIC 中被支持.
|
||||
|
||||
#### utls
|
||||
|
||||
==仅客户端==
|
||||
|
3
go.mod
3
go.mod
@ -4,6 +4,7 @@ go 1.23.1
|
||||
|
||||
require (
|
||||
github.com/anytls/sing-anytls v0.0.8
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
github.com/caddyserver/certmagic v0.23.0
|
||||
github.com/coder/websocket v1.8.13
|
||||
github.com/cretz/bine v0.2.0
|
||||
@ -27,7 +28,7 @@ require (
|
||||
github.com/sagernet/gomobile v0.1.8
|
||||
github.com/sagernet/gvisor v0.0.0-20250822052253-5558536cf237
|
||||
github.com/sagernet/quic-go v0.52.0-beta.1
|
||||
github.com/sagernet/sing v0.7.8-0.20250908063931-beb351e61b89
|
||||
github.com/sagernet/sing v0.7.8-0.20250908034727-1ceb6b183d75
|
||||
github.com/sagernet/sing-mux v0.3.3
|
||||
github.com/sagernet/sing-quic v0.5.2-0.20250908021228-186e280a524e
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
|
6
go.sum
6
go.sum
@ -12,6 +12,8 @@ github.com/anytls/sing-anytls v0.0.8 h1:1u/fnH1HoeeMV5mX7/eUOjLBvPdkd1UJRmXiRi6V
|
||||
github.com/anytls/sing-anytls v0.0.8/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8=
|
||||
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
|
||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU=
|
||||
github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4=
|
||||
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||
@ -167,8 +169,8 @@ github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/l
|
||||
github.com/sagernet/quic-go v0.52.0-beta.1 h1:hWkojLg64zjV+MJOvJU/kOeWndm3tiEfBLx5foisszs=
|
||||
github.com/sagernet/quic-go v0.52.0-beta.1/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4=
|
||||
github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing v0.7.8-0.20250908063931-beb351e61b89 h1:Of7kq85JItQmR4Y8m3L/DFFxaxyjK9rJvLMpmXPQ7g0=
|
||||
github.com/sagernet/sing v0.7.8-0.20250908063931-beb351e61b89/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing v0.7.8-0.20250908034727-1ceb6b183d75 h1:jc7lqbvND3htLpTeu6xPlhcVz01z7dEmikCZ46LmvxU=
|
||||
github.com/sagernet/sing v0.7.8-0.20250908034727-1ceb6b183d75/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-mux v0.3.3 h1:YFgt9plMWzH994BMZLmyKL37PdIVaIilwP0Jg+EcLfw=
|
||||
github.com/sagernet/sing-mux v0.3.3/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
|
||||
github.com/sagernet/sing-quic v0.5.2-0.20250908021228-186e280a524e h1:l+DICzp1OecGSDoiHE0Ebviaz3zqSp7XM27UcRbGkBM=
|
||||
|
@ -43,12 +43,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
authenticator: auth.NewAuthenticator(options.Users),
|
||||
}
|
||||
if options.TLS != nil {
|
||||
tlsConfig, err := tls.NewServerWithOptions(tls.ServerOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
Options: common.PtrValueOrDefault(options.TLS),
|
||||
KTLSCompatible: true,
|
||||
})
|
||||
tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -8,12 +8,10 @@ import (
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/adapter/inbound"
|
||||
"github.com/sagernet/sing-box/common/listener"
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
"github.com/sagernet/sing-box/common/uot"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/auth"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
@ -35,7 +33,6 @@ type Inbound struct {
|
||||
logger log.ContextLogger
|
||||
listener *listener.Listener
|
||||
authenticator *auth.Authenticator
|
||||
tlsConfig tls.ServerConfig
|
||||
}
|
||||
|
||||
func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HTTPMixedInboundOptions) (adapter.Inbound, error) {
|
||||
@ -45,18 +42,6 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
logger: logger,
|
||||
authenticator: auth.NewAuthenticator(options.Users),
|
||||
}
|
||||
if options.TLS != nil {
|
||||
tlsConfig, err := tls.NewServerWithOptions(tls.ServerOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
Options: common.PtrValueOrDefault(options.TLS),
|
||||
KTLSCompatible: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inbound.tlsConfig = tlsConfig
|
||||
}
|
||||
inbound.listener = listener.New(listener.Options{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
@ -73,21 +58,13 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
|
||||
if stage != adapter.StartStateStart {
|
||||
return nil
|
||||
}
|
||||
if h.tlsConfig != nil {
|
||||
err := h.tlsConfig.Start()
|
||||
if err != nil {
|
||||
return E.Cause(err, "create TLS config")
|
||||
}
|
||||
}
|
||||
return h.listener.Start()
|
||||
}
|
||||
|
||||
func (h *Inbound) Close() error {
|
||||
return common.Close(
|
||||
h.listener,
|
||||
h.tlsConfig,
|
||||
)
|
||||
return h.listener.Close()
|
||||
}
|
||||
|
||||
func (h *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
err := h.newConnection(ctx, conn, metadata, onClose)
|
||||
N.CloseOnHandshakeFailure(conn, onClose, err)
|
||||
@ -101,13 +78,6 @@ func (h *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata a
|
||||
}
|
||||
|
||||
func (h *Inbound) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
|
||||
if h.tlsConfig != nil {
|
||||
tlsConn, err := tls.ServerHandshake(ctx, conn, h.tlsConfig)
|
||||
if err != nil {
|
||||
return E.Cause(err, "TLS handshake")
|
||||
}
|
||||
conn = tlsConn
|
||||
}
|
||||
reader := std_bufio.NewReader(conn)
|
||||
headerBytes, err := reader.Peek(1)
|
||||
if err != nil {
|
||||
|
@ -50,13 +50,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
users: options.Users,
|
||||
}
|
||||
if options.TLS != nil {
|
||||
tlsConfig, err := tls.NewServerWithOptions(tls.ServerOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
Options: common.PtrValueOrDefault(options.TLS),
|
||||
KTLSCompatible: common.PtrValueOrDefault(options.Transport).Type == "" &&
|
||||
!common.PtrValueOrDefault(options.Multiplex).Enabled,
|
||||
})
|
||||
tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -51,14 +51,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
key: trojan.Key(options.Password),
|
||||
}
|
||||
if options.TLS != nil {
|
||||
outbound.tlsConfig, err = tls.NewClientWithOptions(tls.ClientOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
ServerAddress: options.Server,
|
||||
Options: common.PtrValueOrDefault(options.TLS),
|
||||
KTLSCompatible: common.PtrValueOrDefault(options.Transport).Type == "" &&
|
||||
!common.PtrValueOrDefault(options.Multiplex).Enabled,
|
||||
})
|
||||
outbound.tlsConfig, err = tls.NewClient(ctx, logger, options.Server, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -68,16 +68,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
}))
|
||||
inbound.service = service
|
||||
if options.TLS != nil {
|
||||
inbound.tlsConfig, err = tls.NewServerWithOptions(tls.ServerOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
Options: common.PtrValueOrDefault(options.TLS),
|
||||
KTLSCompatible: common.PtrValueOrDefault(options.Transport).Type == "" &&
|
||||
!common.PtrValueOrDefault(options.Multiplex).Enabled &&
|
||||
common.All(options.Users, func(it option.VLESSUser) bool {
|
||||
return it.Flow == ""
|
||||
}),
|
||||
})
|
||||
inbound.tlsConfig, err = tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -53,15 +53,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
serverAddr: options.ServerOptions.Build(),
|
||||
}
|
||||
if options.TLS != nil {
|
||||
outbound.tlsConfig, err = tls.NewClientWithOptions(tls.ClientOptions{
|
||||
Context: ctx,
|
||||
Logger: logger,
|
||||
ServerAddress: options.Server,
|
||||
Options: common.PtrValueOrDefault(options.TLS),
|
||||
KTLSCompatible: common.PtrValueOrDefault(options.Transport).Type == "" &&
|
||||
!common.PtrValueOrDefault(options.Multiplex).Enabled &&
|
||||
options.Flow == "",
|
||||
})
|
||||
outbound.tlsConfig, err = tls.NewClient(ctx, logger, options.Server, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user