Compare commits

..

22 Commits

Author SHA1 Message Date
renovate[bot]
5e96b57825
[dependencies] Update github-actions 2025-09-08 03:48:52 +00:00
世界
12e8d43925
Add support for kTLS
Reference: https://gitlab.com/go-extension/tls
2025-09-08 11:48:26 +08:00
世界
f13327f4d2
documentation: Bump version 2025-09-08 09:13:10 +08:00
世界
e1f54d429a
Add proxy support for ICMP echo request 2025-09-08 09:13:10 +08:00
世界
19f9af5945
Fix resolve using resolved 2025-09-08 09:13:10 +08:00
世界
b0fc436a16
documentation: Update behavior of local DNS server on darwin 2025-09-08 09:13:10 +08:00
世界
53bb549809
Stop using DHCP on iOS and tvOS
We do not have the `com.apple.developer.networking.multicast` entitlement and are unable to obtain it for non-technical reasons.
2025-09-08 09:13:10 +08:00
世界
e7de4f5a88
Remove use of ldflags -checklinkname=0 on darwin 2025-09-08 09:13:10 +08:00
世界
8583c6e509
Fix local DNS server on darwin
We mistakenly believed that `libresolv`'s `search` function worked correctly in NetworkExtension, but it seems only `getaddrinfo` does.

This commit changes the behavior of the `local` DNS server in NetworkExtension to prefer DHCP, falling back to `getaddrinfo` if DHCP servers are unavailable.

It's worth noting that `prefer_go` does not disable DHCP since it respects Dial Fields, but `getaddrinfo` does the opposite. The new behavior only applies to NetworkExtension, not to all scenarios (primarily command-line binaries) as it did previously.

In addition, this commit also improves the DHCP DNS server to use the same robust query logic as `local`.
2025-09-08 09:13:09 +08:00
世界
a67f3d8be2
Fix legacy DNS config 2025-09-08 09:13:09 +08:00
世界
87ed5f86d8
Fix rule-set format 2025-09-08 09:13:09 +08:00
世界
e53122d255
documentation: Remove outdated icons 2025-09-08 09:13:08 +08:00
世界
5982358407
documentation: Improve local DNS server 2025-09-08 09:13:08 +08:00
世界
490daad0a7
Use libresolv in local DNS server on darwin 2025-09-08 09:13:08 +08:00
世界
b1ea333bd4
Use resolved in local DNS server if available 2025-09-08 09:13:08 +08:00
xchacha20-poly1305
e69b61747f
Fix rule set version 2025-09-08 09:13:07 +08:00
世界
16d8f108ca
documentation: Add preferred_by route rule item 2025-09-08 09:13:07 +08:00
世界
ffdfb3237c
Add preferred_by route rule item 2025-09-08 09:13:07 +08:00
世界
92b6cc4904
documentation: Add interface address rule items 2025-09-08 09:13:07 +08:00
世界
c630819ee9
Add interface address rule items 2025-09-08 09:13:07 +08:00
neletor
e9f519aafc
Add support for ech retry configs 2025-09-08 09:13:07 +08:00
Zephyruso
84279243ce
Add /dns/flush-clash meta api 2025-09-08 09:13:06 +08:00
20 changed files with 108 additions and 335 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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.01.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.01.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"

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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