mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-07-23 22:44:07 +08:00
Compare commits
7 Commits
8ec5593805
...
4acd65bba3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4acd65bba3 | ||
![]() |
9d0509b2c6 | ||
![]() |
534cccce91 | ||
![]() |
72dbcd3ad4 | ||
![]() |
5533094984 | ||
![]() |
ae2ecd6002 | ||
![]() |
0098a2adc5 |
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24.5
|
||||||
- name: Check input version
|
- name: Check input version
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
run: |-
|
run: |-
|
||||||
@ -109,7 +109,7 @@ jobs:
|
|||||||
if: ${{ ! matrix.legacy_go }}
|
if: ${{ ! matrix.legacy_go }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24.5
|
||||||
- name: Cache Legacy Go
|
- name: Cache Legacy Go
|
||||||
if: matrix.require_legacy_go
|
if: matrix.require_legacy_go
|
||||||
id: cache-legacy-go
|
id: cache-legacy-go
|
||||||
@ -294,7 +294,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24.5
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@ -374,7 +374,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24.5
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@ -472,7 +472,7 @@ jobs:
|
|||||||
if: matrix.if
|
if: matrix.if
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24.5
|
||||||
- name: Setup Xcode stable
|
- name: Setup Xcode stable
|
||||||
if: matrix.if && github.ref == 'refs/heads/main-next'
|
if: matrix.if && github.ref == 'refs/heads/main-next'
|
||||||
run: |-
|
run: |-
|
||||||
|
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24.5
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v6
|
uses: golangci/golangci-lint-action@v6
|
||||||
with:
|
with:
|
||||||
|
4
.github/workflows/linux.yml
vendored
4
.github/workflows/linux.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24.5
|
||||||
- name: Check input version
|
- name: Check input version
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
run: |-
|
run: |-
|
||||||
@ -66,7 +66,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24
|
go-version: ^1.24.5
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
if: matrix.os == 'android'
|
if: matrix.os == 'android'
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
|
286
cmd/internal/tun_bench/main.go
Normal file
286
cmd/internal/tun_bench/main.go
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/netip"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/include"
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/json"
|
||||||
|
"github.com/sagernet/sing/common/shell"
|
||||||
|
)
|
||||||
|
|
||||||
|
var iperf3Path string
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := main0()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main0() error {
|
||||||
|
err := shell.Exec("sudo", "ls").Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
results, err := runTests()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encoder := json.NewEncoder(os.Stdout)
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
return encoder.Encode(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTests() ([]TestResult, error) {
|
||||||
|
boxPaths := []string{
|
||||||
|
//"/Users/sekai/Downloads/sing-box-1.11.15-darwin-arm64/sing-box",
|
||||||
|
//"/Users/sekai/Downloads/sing-box-1.11.15-linux-arm64/sing-box",
|
||||||
|
"./sing-box",
|
||||||
|
}
|
||||||
|
stacks := []string{
|
||||||
|
"gvisor",
|
||||||
|
"system",
|
||||||
|
}
|
||||||
|
mtus := []int{
|
||||||
|
// 1500,
|
||||||
|
// 4064,
|
||||||
|
// 16384,
|
||||||
|
32768,
|
||||||
|
49152,
|
||||||
|
65535,
|
||||||
|
}
|
||||||
|
flagList := [][]string{
|
||||||
|
{},
|
||||||
|
}
|
||||||
|
var results []TestResult
|
||||||
|
for _, boxPath := range boxPaths {
|
||||||
|
for _, stack := range stacks {
|
||||||
|
for _, mtu := range mtus {
|
||||||
|
if strings.HasPrefix(boxPath, ".") {
|
||||||
|
for _, flags := range flagList {
|
||||||
|
result, err := testOnce(boxPath, stack, mtu, false, flags)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
results = append(results, *result)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result, err := testOnce(boxPath, stack, mtu, false, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
results = append(results, *result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestResult struct {
|
||||||
|
BoxPath string `json:"box_path"`
|
||||||
|
Stack string `json:"stack"`
|
||||||
|
MTU int `json:"mtu"`
|
||||||
|
Flags []string `json:"flags"`
|
||||||
|
MultiThread bool `json:"multi_thread"`
|
||||||
|
UploadSpeed string `json:"upload_speed"`
|
||||||
|
DownloadSpeed string `json:"download_speed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func testOnce(boxPath string, stackName string, mtu int, multiThread bool, flags []string) (result *TestResult, err error) {
|
||||||
|
testAddress := netip.MustParseAddr("1.1.1.1")
|
||||||
|
testConfig := option.Options{
|
||||||
|
Inbounds: []option.Inbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeTun,
|
||||||
|
Options: &option.TunInboundOptions{
|
||||||
|
Address: []netip.Prefix{netip.MustParsePrefix("172.18.0.1/30")},
|
||||||
|
AutoRoute: true,
|
||||||
|
MTU: uint32(mtu),
|
||||||
|
Stack: stackName,
|
||||||
|
RouteAddress: []netip.Prefix{netip.PrefixFrom(testAddress, testAddress.BitLen())},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Route: &option.RouteOptions{
|
||||||
|
Rules: []option.Rule{
|
||||||
|
{
|
||||||
|
Type: C.RuleTypeDefault,
|
||||||
|
DefaultOptions: option.DefaultRule{
|
||||||
|
RawDefaultRule: option.RawDefaultRule{
|
||||||
|
IPCIDR: []string{testAddress.String()},
|
||||||
|
},
|
||||||
|
RuleAction: option.RuleAction{
|
||||||
|
Action: C.RuleActionTypeRouteOptions,
|
||||||
|
RouteOptionsOptions: option.RouteOptionsActionOptions{
|
||||||
|
OverrideAddress: "127.0.0.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AutoDetectInterface: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx := include.Context(context.Background())
|
||||||
|
tempConfig, err := os.CreateTemp("", "tun-bench-*.json")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.Remove(tempConfig.Name())
|
||||||
|
encoder := json.NewEncoderContext(ctx, tempConfig)
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
err = encoder.Encode(testConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "encode test config")
|
||||||
|
}
|
||||||
|
tempConfig.Close()
|
||||||
|
var sudoArgs []string
|
||||||
|
if len(flags) > 0 {
|
||||||
|
sudoArgs = append(sudoArgs, "env")
|
||||||
|
for _, flag := range flags {
|
||||||
|
sudoArgs = append(sudoArgs, flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sudoArgs = append(sudoArgs, boxPath, "run", "-c", tempConfig.Name())
|
||||||
|
boxProcess := shell.Exec("sudo", sudoArgs...)
|
||||||
|
boxProcess.Stdout = &stderrWriter{}
|
||||||
|
boxProcess.Stderr = io.Discard
|
||||||
|
err = boxProcess.Start()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if C.IsDarwin {
|
||||||
|
iperf3Path, err = exec.LookPath("iperf3-darwin")
|
||||||
|
} else {
|
||||||
|
iperf3Path, err = exec.LookPath("iperf3")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
serverProcess := shell.Exec(iperf3Path, "-s")
|
||||||
|
serverProcess.Stdout = io.Discard
|
||||||
|
serverProcess.Stderr = io.Discard
|
||||||
|
err = serverProcess.Start()
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "start iperf3 server")
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
args := []string{"-c", testAddress.String(), "-t", "5"}
|
||||||
|
if multiThread {
|
||||||
|
args = append(args, "-P", "10")
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadProcess := shell.Exec(iperf3Path, args...)
|
||||||
|
output, err := uploadProcess.Read()
|
||||||
|
if err != nil {
|
||||||
|
boxProcess.Process.Signal(syscall.SIGKILL)
|
||||||
|
serverProcess.Process.Signal(syscall.SIGKILL)
|
||||||
|
println(output)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadResult := common.SubstringBeforeLast(output, "iperf Done.")
|
||||||
|
uploadResult = common.SubstringBeforeLast(uploadResult, "sender")
|
||||||
|
uploadResult = common.SubstringBeforeLast(uploadResult, "bits/sec")
|
||||||
|
uploadResult = common.SubstringAfterLast(uploadResult, "Bytes")
|
||||||
|
uploadResult = strings.ReplaceAll(uploadResult, " ", "")
|
||||||
|
|
||||||
|
result = &TestResult{
|
||||||
|
BoxPath: boxPath,
|
||||||
|
Stack: stackName,
|
||||||
|
MTU: mtu,
|
||||||
|
Flags: flags,
|
||||||
|
MultiThread: multiThread,
|
||||||
|
UploadSpeed: uploadResult,
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadProcess := shell.Exec(iperf3Path, append(args, "-R")...)
|
||||||
|
output, err = downloadProcess.Read()
|
||||||
|
if err != nil {
|
||||||
|
boxProcess.Process.Signal(syscall.SIGKILL)
|
||||||
|
serverProcess.Process.Signal(syscall.SIGKILL)
|
||||||
|
println(output)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadResult := common.SubstringBeforeLast(output, "iperf Done.")
|
||||||
|
downloadResult = common.SubstringBeforeLast(downloadResult, "receiver")
|
||||||
|
downloadResult = common.SubstringBeforeLast(downloadResult, "bits/sec")
|
||||||
|
downloadResult = common.SubstringAfterLast(downloadResult, "Bytes")
|
||||||
|
downloadResult = strings.ReplaceAll(downloadResult, " ", "")
|
||||||
|
|
||||||
|
result.DownloadSpeed = downloadResult
|
||||||
|
|
||||||
|
printArgs := []any{boxPath, stackName, mtu, "upload", uploadResult, "download", downloadResult}
|
||||||
|
if len(flags) > 0 {
|
||||||
|
printArgs = append(printArgs, "flags", strings.Join(flags, " "))
|
||||||
|
}
|
||||||
|
if multiThread {
|
||||||
|
printArgs = append(printArgs, "(-P 10)")
|
||||||
|
}
|
||||||
|
fmt.Println(printArgs...)
|
||||||
|
err = boxProcess.Process.Signal(syscall.SIGTERM)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = serverProcess.Process.Signal(syscall.SIGTERM)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
boxDone := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
boxProcess.Cmd.Wait()
|
||||||
|
close(boxDone)
|
||||||
|
}()
|
||||||
|
|
||||||
|
serverDone := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
serverProcess.Process.Wait()
|
||||||
|
close(serverDone)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-boxDone:
|
||||||
|
case <-time.After(2 * time.Second):
|
||||||
|
boxProcess.Process.Kill()
|
||||||
|
case <-time.After(4 * time.Second):
|
||||||
|
println("box process did not close!")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-serverDone:
|
||||||
|
case <-time.After(2 * time.Second):
|
||||||
|
serverProcess.Process.Kill()
|
||||||
|
case <-time.After(4 * time.Second):
|
||||||
|
println("server process did not close!")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type stderrWriter struct{}
|
||||||
|
|
||||||
|
func (w *stderrWriter) Write(p []byte) (n int, err error) {
|
||||||
|
return os.Stderr.Write(p)
|
||||||
|
}
|
@ -60,7 +60,7 @@ func NewUDPRaw(logger logger.ContextLogger, adapter dns.TransportAdapter, dialer
|
|||||||
logger: logger,
|
logger: logger,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
serverAddr: serverAddr,
|
serverAddr: serverAddr,
|
||||||
udpSize: 512,
|
udpSize: 2048,
|
||||||
tcpTransport: &TCPTransport{
|
tcpTransport: &TCPTransport{
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
serverAddr: serverAddr,
|
serverAddr: serverAddr,
|
||||||
@ -97,15 +97,19 @@ func (t *UDPTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPTransport) exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
func (t *UDPTransport) exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||||
conn, err := t.open(ctx)
|
t.access.Lock()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if edns0Opt := message.IsEdns0(); edns0Opt != nil {
|
if edns0Opt := message.IsEdns0(); edns0Opt != nil {
|
||||||
if udpSize := int(edns0Opt.UDPSize()); udpSize > t.udpSize {
|
if udpSize := int(edns0Opt.UDPSize()); udpSize > t.udpSize {
|
||||||
t.udpSize = udpSize
|
t.udpSize = udpSize
|
||||||
|
close(t.done)
|
||||||
|
t.done = make(chan struct{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
t.access.Unlock()
|
||||||
|
conn, err := t.open(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
buffer := buf.NewSize(1 + message.Len())
|
buffer := buf.NewSize(1 + message.Len())
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
exMessage := *message
|
exMessage := *message
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
#### 1.12.0-beta.34
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
### 1.11.15
|
### 1.11.15
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -9,6 +13,15 @@ icon: material/alert-decagram
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-beta.32
|
||||||
|
|
||||||
|
* Improve tun performance on Apple platforms **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
We have significantly improved the performance of tun inbound on Apple platforms, especially in the gVisor stack.
|
||||||
|
|
||||||
### 1.11.14
|
### 1.11.14
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -16,6 +29,49 @@ violated the rules (TestFlight users are not affected)._
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-beta.24
|
||||||
|
|
||||||
|
* Allow `tls_fragment` and `tls_record_fragment` to be enabled together **1**
|
||||||
|
* Also add fragment options for TLS client configuration **2**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
For debugging only, it is recommended to disable if record fragmentation works.
|
||||||
|
|
||||||
|
See [Route Action](/configuration/route/rule_action/#tls_fragment).
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
See [TLS](/configuration/shared/tls/).
|
||||||
|
|
||||||
|
#### 1.12.0-beta.23
|
||||||
|
|
||||||
|
* Add loopback address support for tun **1**
|
||||||
|
* Add cache support for ssm-api **2**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
TUN now implements SideStore's StosVPN.
|
||||||
|
|
||||||
|
See [Tun](/configuration/inbound/tun/#loopback_address).
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
See [SSM API Service](/configuration/service/ssm-api/#cache_path).
|
||||||
|
|
||||||
|
#### 1.12.0-beta.21
|
||||||
|
|
||||||
|
* Fix missing `home` option for DERP service **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
You can now choose what the DERP home page shows, just like with derper's `-home` flag.
|
||||||
|
|
||||||
|
See [DERP](/configuration/service/derp/#home).
|
||||||
|
|
||||||
### 1.11.13
|
### 1.11.13
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -23,6 +79,37 @@ violated the rules (TestFlight users are not affected)._
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-beta.17
|
||||||
|
|
||||||
|
* Update quic-go to v0.52.0
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.12.0-beta.15
|
||||||
|
|
||||||
|
* Add DERP service **1**
|
||||||
|
* Add Resolved service and DNS server **2**
|
||||||
|
* Add SSM API service **3**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
DERP service is a Tailscale DERP server, similar to [derper](https://pkg.go.dev/tailscale.com/cmd/derper).
|
||||||
|
|
||||||
|
See [DERP Service](/configuration/service/derp/).
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
Resolved service is a fake systemd-resolved DBUS service to receive DNS settings from other programs
|
||||||
|
(e.g. NetworkManager) and provide DNS resolution.
|
||||||
|
|
||||||
|
See [Resolved Service](/configuration/service/resolved/) and [Resolved DNS Server](/configuration/dns/server/resolved/).
|
||||||
|
|
||||||
|
**3**:
|
||||||
|
|
||||||
|
SSM API service is a RESTful API server for managing Shadowsocks servers.
|
||||||
|
|
||||||
|
See [SSM API Service](/configuration/service/ssm-api/).
|
||||||
|
|
||||||
### 1.11.11
|
### 1.11.11
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -30,6 +117,31 @@ violated the rules (TestFlight users are not affected)._
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-beta.13
|
||||||
|
|
||||||
|
* Add TLS record fragment route options **1**
|
||||||
|
* Add missing `accept_routes` option for Tailscale **2**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
See [Route Action](/configuration/route/rule_action/#tls_record_fragment).
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
See [Tailscale](/configuration/endpoint/tailscale/#accept_routes).
|
||||||
|
|
||||||
|
#### 1.12.0-beta.10
|
||||||
|
|
||||||
|
* Add control options for listeners **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
You can now set `bind_interface`, `routing_mark` and `reuse_addr` in Listen Fields.
|
||||||
|
|
||||||
|
See [Listen Fields](/configuration/shared/listen/).
|
||||||
|
|
||||||
### 1.11.10
|
### 1.11.10
|
||||||
|
|
||||||
* Undeprecate the `block` outbound **1**
|
* Undeprecate the `block` outbound **1**
|
||||||
@ -43,6 +155,11 @@ we decided to temporarily undeprecate the `block` outbound until a replacement i
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-beta.9
|
||||||
|
|
||||||
|
* Update quic-go to v0.51.0
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
### 1.11.9
|
### 1.11.9
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -50,6 +167,10 @@ violated the rules (TestFlight users are not affected)._
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-beta.5
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
### 1.11.8
|
### 1.11.8
|
||||||
|
|
||||||
* Improve `auto_redirect` **1**
|
* Improve `auto_redirect` **1**
|
||||||
@ -63,6 +184,10 @@ see [Tun](/configuration/inbound/tun/#auto_redirect).
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-beta.3
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
### 1.11.7
|
### 1.11.7
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -70,6 +195,15 @@ violated the rules (TestFlight users are not affected)._
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-beta.1
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
Now `auto_redirect` fixes compatibility issues between tun and Docker bridge networks,
|
||||||
|
see [Tun](/configuration/inbound/tun/#auto_redirect).
|
||||||
|
|
||||||
### 1.11.6
|
### 1.11.6
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -77,6 +211,40 @@ violated the rules (TestFlight users are not affected)._
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.19
|
||||||
|
|
||||||
|
* Update gVisor to 20250319.0
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.18
|
||||||
|
|
||||||
|
* Add wildcard SNI support for ShadowTLS inbound **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
See [ShadowTLS](/configuration/inbound/shadowtls/#wildcard_sni).
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.17
|
||||||
|
|
||||||
|
* Add NTP sniffer **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
See [Protocol Sniff](/configuration/route/sniff/).
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.16
|
||||||
|
|
||||||
|
* Update `domain_resolver` behavior **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
`route.default_domain_resolver` or `outbound.domain_resolver` is now optional when only one DNS server is configured.
|
||||||
|
|
||||||
|
See [Dial Fields](/configuration/shared/dial/#domain_resolver).
|
||||||
|
|
||||||
### 1.11.5
|
### 1.11.5
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -84,10 +252,71 @@ violated the rules (TestFlight users are not affected)._
|
|||||||
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
_We are temporarily unable to update sing-box apps on the App Store because the reviewer mistakenly found that we
|
||||||
violated the rules (TestFlight users are not affected)._
|
violated the rules (TestFlight users are not affected)._
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.13
|
||||||
|
|
||||||
|
* Move `predefined` DNS server to DNS rule action **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
See [DNS Rule Action](/configuration/dns/rule_action/#predefined).
|
||||||
|
|
||||||
### 1.11.4
|
### 1.11.4
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.11
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.10
|
||||||
|
|
||||||
|
* Add AnyTLS protocol **1**
|
||||||
|
* Improve `resolve` route action **2**
|
||||||
|
* Migrate to stdlib ECH implementation **3**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
The new AnyTLS protocol claims to mitigate TLS proxy traffic characteristics and comes with a new multiplexing scheme.
|
||||||
|
|
||||||
|
See [AnyTLS Inbound](/configuration/inbound/anytls/) and [AnyTLS Outbound](/configuration/outbound/anytls/).
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
`resolve` route action now accepts `disable_cache` and other options like in DNS route actions, see [Route Action](/configuration/route/rule_action).
|
||||||
|
|
||||||
|
**3**:
|
||||||
|
|
||||||
|
See [TLS](/configuration/shared/tls).
|
||||||
|
|
||||||
|
The build tag `with_ech` is no longer needed and has been removed.
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.7
|
||||||
|
|
||||||
|
* Add Tailscale DNS server **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
See [Tailscale](/configuration/dns/server/tailscale/).
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.6
|
||||||
|
|
||||||
|
* Add Tailscale endpoint **1**
|
||||||
|
* Drop support for go1.22 **2**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
See [Tailscale](/configuration/endpoint/tailscale/).
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
Due to maintenance difficulties, sing-box 1.12.0 requires at least Go 1.23 to compile.
|
||||||
|
|
||||||
|
For Windows 7 users, legacy binaries now continue to compile with Go 1.23 and patches from [MetaCubeX/go](https://github.com/MetaCubeX/go).
|
||||||
|
|
||||||
### 1.11.3
|
### 1.11.3
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
@ -95,10 +324,69 @@ violated the rules (TestFlight users are not affected)._
|
|||||||
_This version overwrites 1.11.2, as incorrect binaries were released due to a bug in the continuous integration
|
_This version overwrites 1.11.2, as incorrect binaries were released due to a bug in the continuous integration
|
||||||
process._
|
process._
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.5
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
### 1.11.1
|
### 1.11.1
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.2
|
||||||
|
|
||||||
|
* Update quic-go to v0.49.0
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
#### 1.12.0-alpha.1
|
||||||
|
|
||||||
|
* Refactor DNS servers **1**
|
||||||
|
* Add domain resolver options**2**
|
||||||
|
* Add TLS fragment route options **3**
|
||||||
|
* Add certificate options **4**
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
DNS servers are refactored for better performance and scalability.
|
||||||
|
|
||||||
|
See [DNS server](/configuration/dns/server/).
|
||||||
|
|
||||||
|
For migration, see [Migrate to new DNS server formats](/migration/#migrate-to-new-dns-servers).
|
||||||
|
|
||||||
|
Compatibility for old formats will be removed in sing-box 1.14.0.
|
||||||
|
|
||||||
|
**2**:
|
||||||
|
|
||||||
|
Legacy `outbound` DNS rules are deprecated
|
||||||
|
and can be replaced by the new `domain_resolver` option.
|
||||||
|
|
||||||
|
See [Dial Fields](/configuration/shared/dial/#domain_resolver) and
|
||||||
|
[Route](/configuration/route/#default_domain_resolver).
|
||||||
|
|
||||||
|
For migration,
|
||||||
|
see [Migrate outbound DNS rule items to domain resolver](/migration/#migrate-outbound-dns-rule-items-to-domain-resolver).
|
||||||
|
|
||||||
|
**3**:
|
||||||
|
|
||||||
|
The new TLS fragment route options allow you to fragment TLS handshakes to bypass firewalls.
|
||||||
|
|
||||||
|
This feature is intended to circumvent simple firewalls based on **plaintext packet matching**, and should not be used
|
||||||
|
to circumvent real censorship.
|
||||||
|
|
||||||
|
Since it is not designed for performance, it should not be applied to all connections, but only to server names that are
|
||||||
|
known to be blocked.
|
||||||
|
|
||||||
|
See [Route Action](/configuration/route/rule_action/#tls_fragment).
|
||||||
|
|
||||||
|
**4**:
|
||||||
|
|
||||||
|
New certificate options allow you to manage the default list of trusted X509 CA certificates.
|
||||||
|
|
||||||
|
For the system certificate list, fixed Go not reading Android trusted certificates correctly.
|
||||||
|
|
||||||
|
You can also use the Mozilla Included List instead, or add trusted certificates yourself.
|
||||||
|
|
||||||
|
See [Certificate](/configuration/certificate/).
|
||||||
|
|
||||||
### 1.11.0
|
### 1.11.0
|
||||||
|
|
||||||
Important changes since 1.10:
|
Important changes since 1.10:
|
||||||
|
4
go.mod
4
go.mod
@ -28,13 +28,13 @@ require (
|
|||||||
github.com/sagernet/gomobile v0.1.7
|
github.com/sagernet/gomobile v0.1.7
|
||||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
|
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
|
||||||
github.com/sagernet/quic-go v0.52.0-beta.1
|
github.com/sagernet/quic-go v0.52.0-beta.1
|
||||||
github.com/sagernet/sing v0.6.12-0.20250704043954-da981379f151
|
github.com/sagernet/sing v0.6.12-0.20250718132236-21daaa465e88
|
||||||
github.com/sagernet/sing-mux v0.3.2
|
github.com/sagernet/sing-mux v0.3.2
|
||||||
github.com/sagernet/sing-quic v0.5.0-beta.3
|
github.com/sagernet/sing-quic v0.5.0-beta.3
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
||||||
github.com/sagernet/sing-tun v0.6.10-0.20250703121732-a0881ada3251
|
github.com/sagernet/sing-tun v0.6.10-0.20250718030019-3af7305b853e
|
||||||
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88
|
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88
|
||||||
github.com/sagernet/smux v1.5.34-mod.2
|
github.com/sagernet/smux v1.5.34-mod.2
|
||||||
github.com/sagernet/tailscale v1.80.3-mod.5
|
github.com/sagernet/tailscale v1.80.3-mod.5
|
||||||
|
8
go.sum
8
go.sum
@ -168,8 +168,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 h1:hWkojLg64zjV+MJOvJU/kOeWndm3tiEfBLx5foisszs=
|
||||||
github.com/sagernet/quic-go v0.52.0-beta.1/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4=
|
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.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
github.com/sagernet/sing v0.6.12-0.20250704043954-da981379f151 h1:UCiQ1d/t5Y9uKAL9ir3i06+ClqS93OGGG8oqB82RMCE=
|
github.com/sagernet/sing v0.6.12-0.20250718132236-21daaa465e88 h1:Wu6hu+JsZ2gsFRJMqGzaZJ4ctGnmNrLGm9ckmotBFOs=
|
||||||
github.com/sagernet/sing v0.6.12-0.20250704043954-da981379f151/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
github.com/sagernet/sing v0.6.12-0.20250718132236-21daaa465e88/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
github.com/sagernet/sing-mux v0.3.2 h1:meZVFiiStvHThb/trcpAkCrmtJOuItG5Dzl1RRP5/NE=
|
github.com/sagernet/sing-mux v0.3.2 h1:meZVFiiStvHThb/trcpAkCrmtJOuItG5Dzl1RRP5/NE=
|
||||||
github.com/sagernet/sing-mux v0.3.2/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
|
github.com/sagernet/sing-mux v0.3.2/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
|
||||||
github.com/sagernet/sing-quic v0.5.0-beta.3 h1:X/acRNsqQNfDlmwE7SorHfaZiny5e67hqIzM/592ric=
|
github.com/sagernet/sing-quic v0.5.0-beta.3 h1:X/acRNsqQNfDlmwE7SorHfaZiny5e67hqIzM/592ric=
|
||||||
@ -180,8 +180,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq
|
|||||||
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w=
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w=
|
||||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
||||||
github.com/sagernet/sing-tun v0.6.10-0.20250703121732-a0881ada3251 h1:eH9naJXvyF/DZDk0V1SYkL6ypYD+A1tUFWLcT7PRezg=
|
github.com/sagernet/sing-tun v0.6.10-0.20250718030019-3af7305b853e h1:IH6N3oTKs4bqXLoKP7uFfIAAuZHCNq6OCV4MlrGGLqs=
|
||||||
github.com/sagernet/sing-tun v0.6.10-0.20250703121732-a0881ada3251/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
github.com/sagernet/sing-tun v0.6.10-0.20250718030019-3af7305b853e/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||||
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88 h1:0pVm8sPOel+BoiCddW3pV3cKDKEaSioVTYDdTSKjyFI=
|
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88 h1:0pVm8sPOel+BoiCddW3pV3cKDKEaSioVTYDdTSKjyFI=
|
||||||
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88/go.mod h1:IL8Rr+EGwuqijszZkNrEFTQDKhilEpkqFqOlvdpS6/w=
|
github.com/sagernet/sing-vmess v0.2.4-0.20250605032146-38cc72672c88/go.mod h1:IL8Rr+EGwuqijszZkNrEFTQDKhilEpkqFqOlvdpS6/w=
|
||||||
github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=
|
github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=
|
||||||
|
@ -180,7 +180,7 @@ func (o *DNSServerOptions) Upgrade(ctx context.Context) error {
|
|||||||
options := o.Options.(*LegacyDNSServerOptions)
|
options := o.Options.(*LegacyDNSServerOptions)
|
||||||
serverURL, _ := url.Parse(options.Address)
|
serverURL, _ := url.Parse(options.Address)
|
||||||
var serverType string
|
var serverType string
|
||||||
if serverURL.Scheme != "" {
|
if serverURL != nil && serverURL.Scheme != "" {
|
||||||
serverType = serverURL.Scheme
|
serverType = serverURL.Scheme
|
||||||
} else {
|
} else {
|
||||||
switch options.Address {
|
switch options.Address {
|
||||||
@ -217,7 +217,7 @@ func (o *DNSServerOptions) Upgrade(ctx context.Context) error {
|
|||||||
o.Type = C.DNSTypeUDP
|
o.Type = C.DNSTypeUDP
|
||||||
o.Options = &remoteOptions
|
o.Options = &remoteOptions
|
||||||
var serverAddr M.Socksaddr
|
var serverAddr M.Socksaddr
|
||||||
if serverURL.Scheme == "" {
|
if serverURL == nil || serverURL.Scheme == "" {
|
||||||
serverAddr = M.ParseSocksaddr(options.Address)
|
serverAddr = M.ParseSocksaddr(options.Address)
|
||||||
} else {
|
} else {
|
||||||
serverAddr = M.ParseSocksaddr(serverURL.Host)
|
serverAddr = M.ParseSocksaddr(serverURL.Host)
|
||||||
@ -232,6 +232,9 @@ func (o *DNSServerOptions) Upgrade(ctx context.Context) error {
|
|||||||
case C.DNSTypeTCP:
|
case C.DNSTypeTCP:
|
||||||
o.Type = C.DNSTypeTCP
|
o.Type = C.DNSTypeTCP
|
||||||
o.Options = &remoteOptions
|
o.Options = &remoteOptions
|
||||||
|
if serverURL == nil {
|
||||||
|
return E.New("invalid server address")
|
||||||
|
}
|
||||||
serverAddr := M.ParseSocksaddr(serverURL.Host)
|
serverAddr := M.ParseSocksaddr(serverURL.Host)
|
||||||
if !serverAddr.IsValid() {
|
if !serverAddr.IsValid() {
|
||||||
return E.New("invalid server address")
|
return E.New("invalid server address")
|
||||||
@ -242,6 +245,9 @@ func (o *DNSServerOptions) Upgrade(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
case C.DNSTypeTLS, C.DNSTypeQUIC:
|
case C.DNSTypeTLS, C.DNSTypeQUIC:
|
||||||
o.Type = serverType
|
o.Type = serverType
|
||||||
|
if serverURL == nil {
|
||||||
|
return E.New("invalid server address")
|
||||||
|
}
|
||||||
serverAddr := M.ParseSocksaddr(serverURL.Host)
|
serverAddr := M.ParseSocksaddr(serverURL.Host)
|
||||||
if !serverAddr.IsValid() {
|
if !serverAddr.IsValid() {
|
||||||
return E.New("invalid server address")
|
return E.New("invalid server address")
|
||||||
@ -261,6 +267,9 @@ func (o *DNSServerOptions) Upgrade(ctx context.Context) error {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
o.Options = &httpsOptions
|
o.Options = &httpsOptions
|
||||||
|
if serverURL == nil {
|
||||||
|
return E.New("invalid server address")
|
||||||
|
}
|
||||||
serverAddr := M.ParseSocksaddr(serverURL.Host)
|
serverAddr := M.ParseSocksaddr(serverURL.Host)
|
||||||
if !serverAddr.IsValid() {
|
if !serverAddr.IsValid() {
|
||||||
return E.New("invalid server address")
|
return E.New("invalid server address")
|
||||||
@ -274,6 +283,9 @@ func (o *DNSServerOptions) Upgrade(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
case "rcode":
|
case "rcode":
|
||||||
var rcode int
|
var rcode int
|
||||||
|
if serverURL == nil {
|
||||||
|
return E.New("invalid server address")
|
||||||
|
}
|
||||||
switch serverURL.Host {
|
switch serverURL.Host {
|
||||||
case "success":
|
case "success":
|
||||||
rcode = dns.RcodeSuccess
|
rcode = dns.RcodeSuccess
|
||||||
@ -295,6 +307,9 @@ func (o *DNSServerOptions) Upgrade(ctx context.Context) error {
|
|||||||
case C.DNSTypeDHCP:
|
case C.DNSTypeDHCP:
|
||||||
o.Type = C.DNSTypeDHCP
|
o.Type = C.DNSTypeDHCP
|
||||||
dhcpOptions := DHCPDNSServerOptions{}
|
dhcpOptions := DHCPDNSServerOptions{}
|
||||||
|
if serverURL == nil {
|
||||||
|
return E.New("invalid server address")
|
||||||
|
}
|
||||||
if serverURL.Host != "" && serverURL.Host != "auto" {
|
if serverURL.Host != "" && serverURL.Host != "auto" {
|
||||||
dhcpOptions.Interface = serverURL.Host
|
dhcpOptions.Interface = serverURL.Host
|
||||||
}
|
}
|
||||||
|
@ -132,12 +132,13 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
|||||||
|
|
||||||
platformInterface := service.FromContext[platform.Interface](ctx)
|
platformInterface := service.FromContext[platform.Interface](ctx)
|
||||||
tunMTU := options.MTU
|
tunMTU := options.MTU
|
||||||
|
enableGSO := C.IsLinux && options.Stack == "gvisor" && platformInterface == nil && tunMTU > 0 && tunMTU < 49152
|
||||||
if tunMTU == 0 {
|
if tunMTU == 0 {
|
||||||
if platformInterface != nil && platformInterface.UnderNetworkExtension() {
|
if platformInterface != nil && platformInterface.UnderNetworkExtension() {
|
||||||
// In Network Extension, when MTU exceeds 4064 (4096-UTUN_IF_HEADROOM_SIZE), the performance of tun will drop significantly, which may be a system bug.
|
// In Network Extension, when MTU exceeds 4064 (4096-UTUN_IF_HEADROOM_SIZE), the performance of tun will drop significantly, which may be a system bug.
|
||||||
tunMTU = 4064
|
tunMTU = 4064
|
||||||
} else {
|
} else {
|
||||||
tunMTU = 9000
|
tunMTU = 65535
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var udpTimeout time.Duration
|
var udpTimeout time.Duration
|
||||||
@ -179,6 +180,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
|||||||
outputMark = tun.DefaultAutoRedirectOutputMark
|
outputMark = tun.DefaultAutoRedirectOutputMark
|
||||||
}
|
}
|
||||||
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
||||||
|
multiPendingPackets := C.IsDarwin && ((options.Stack == "gvisor" && tunMTU < 32768) || (options.Stack != "gvisor" && options.MTU <= 9000))
|
||||||
inbound := &Inbound{
|
inbound := &Inbound{
|
||||||
tag: tag,
|
tag: tag,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@ -189,6 +191,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
|||||||
tunOptions: tun.Options{
|
tunOptions: tun.Options{
|
||||||
Name: options.InterfaceName,
|
Name: options.InterfaceName,
|
||||||
MTU: tunMTU,
|
MTU: tunMTU,
|
||||||
|
GSO: enableGSO,
|
||||||
Inet4Address: inet4Address,
|
Inet4Address: inet4Address,
|
||||||
Inet6Address: inet6Address,
|
Inet6Address: inet6Address,
|
||||||
AutoRoute: options.AutoRoute,
|
AutoRoute: options.AutoRoute,
|
||||||
@ -211,6 +214,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
|||||||
IncludePackage: options.IncludePackage,
|
IncludePackage: options.IncludePackage,
|
||||||
ExcludePackage: options.ExcludePackage,
|
ExcludePackage: options.ExcludePackage,
|
||||||
InterfaceMonitor: networkManager.InterfaceMonitor(),
|
InterfaceMonitor: networkManager.InterfaceMonitor(),
|
||||||
|
EXP_MultiPendingPackets: multiPendingPackets,
|
||||||
},
|
},
|
||||||
udpTimeout: udpTimeout,
|
udpTimeout: udpTimeout,
|
||||||
stack: options.Stack,
|
stack: options.Stack,
|
||||||
|
@ -277,7 +277,7 @@ func (m *ConnectionManager) connectionCopy(ctx context.Context, source net.Conn,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := bufio.CopyWithCounters(destinationWriter, sourceReader, source, readCounters, writeCounters, bufio.DefaultIncreaseBufferAfter)
|
_, err := bufio.CopyWithCounters(destinationWriter, sourceReader, source, readCounters, writeCounters, bufio.DefaultIncreaseBufferAfter, bufio.DefaultBatchSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.Close(source, destination)
|
common.Close(source, destination)
|
||||||
} else if duplexDst, isDuplex := destination.(N.WriteCloser); isDuplex {
|
} else if duplexDst, isDuplex := destination.(N.WriteCloser); isDuplex {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user