Compare commits

..
Author SHA1 Message Date
世界 139a48780f documentation: Bump version 2025-04-25 11:58:57 +08:00
世界 bc63a6028d clash-api: Add more meta api 2025-04-25 11:58:57 +08:00
世界 284f10b296 Fix DNS Lookup 2025-04-25 11:58:56 +08:00
世界 7a109569f9 Fix tailscale sending unexpected stuff 2025-04-25 11:58:51 +08:00
世界 ea342f257a Fix fetch ECH configs 2025-04-25 11:56:39 +08:00
reletorand世界 8814994368 documentation: Minor fixes 2025-04-25 11:56:39 +08:00
caelansarand世界 20d338a06b Fix callback deletion in UDP transport 2025-04-25 11:56:39 +08:00
世界 7527134ef2 documentation: Try to make the play review happy 2025-04-25 11:56:39 +08:00
世界 43230a89ef Fix missing handling of legacy domain_strategy options 2025-04-25 11:56:38 +08:00
世界 967d84825f Improve local DNS server 2025-04-25 11:56:38 +08:00
anytls世界anytls <anytls>
c38000d94f Update anytls
Co-authored-by: anytls <anytls>
2025-04-25 11:56:15 +08:00
世界 ff8e11dfe3 Fix DNS dialer 2025-04-25 11:56:15 +08:00
世界 eaaa70f118 release: Skip override version for iOS 2025-04-25 11:56:14 +08:00
iikiraand世界 13870fb4b5 Fix UDP DNS server crash
Signed-off-by: iikira <i2@mail.iikira.com>
2025-04-25 11:56:14 +08:00
ReleTorand世界 961d586e47 Fix fetch ECH configs 2025-04-25 11:56:14 +08:00
世界 4f4b7def78 release: Update Go to 1.24.2 2025-04-25 11:56:13 +08:00
世界 4acb3065b8 Allow direct outbounds without domain_resolver 2025-04-25 11:56:13 +08:00
世界 0ab2ef8c44 Fix Tailscale dialer 2025-04-25 11:56:13 +08:00
dyhkwongand世界 56c144fc2b Fix DNS over QUIC stream close 2025-04-25 11:56:13 +08:00
anytls世界anytls <anytls>
7f0fec0bb3 Update anytls
Co-authored-by: anytls <anytls>
2025-04-25 11:56:12 +08:00
Rambling2076and世界 448d534d25 Fix missing with_tailscale in Dockerfile
Signed-off-by: Rambling2076 <Rambling2076@proton.me>
2025-04-25 11:56:12 +08:00
世界 f9f60bb9ea Fail when default DNS server not found 2025-04-25 11:56:12 +08:00
世界 9554908971 Update gVisor to 20250319.0 2025-04-25 11:56:11 +08:00
世界 74be568a93 release: Do not build tailscale on iOS and tvOS 2025-04-25 11:56:11 +08:00
世界 b37f4b68d5 Explicitly reject detour to empty direct outbounds 2025-04-25 11:56:11 +08:00
世界 bbe6ded13c Add netns support 2025-04-25 11:56:11 +08:00
世界 9111cfa5d7 Add wildcard name support for predefined records 2025-04-25 11:56:11 +08:00
世界 546218c0f8 Remove map usage in options 2025-04-25 11:56:10 +08:00
世界 680f8dd008 Fix unhandled DNS loop 2025-04-25 11:56:10 +08:00
世界 13c251287b Add wildcard-sni support for shadow-tls inbound 2025-04-25 11:56:09 +08:00
世界 8051bb4f3b Fix Tailscale DNS 2025-04-25 11:56:09 +08:00
k9982874and世界 24c7b040c5 Add ntp protocol sniffing 2025-04-25 11:56:08 +08:00
世界 ac74bbf5dd option: Fix marshal legacy DNS options 2025-04-25 11:56:08 +08:00
世界 2d72940096 Make domain_resolver optional when only one DNS server is configured 2025-04-25 11:56:08 +08:00
世界 b2d6708f96 Fix DNS lookup context pollution 2025-04-25 11:56:08 +08:00
世界 5108103f3f Fix http3 DNS server connecting to wrong address 2025-04-25 11:56:07 +08:00
Restia-Ashbelland世界 e875eebf9c documentation: Fix typo 2025-04-25 11:56:07 +08:00
anytls世界anytls <anytls>
445eae88ab Update sing-anytls
Co-authored-by: anytls <anytls>
2025-04-25 11:56:07 +08:00
k9982874and世界 3f4f804e3e Fix hosts DNS server 2025-04-25 11:56:07 +08:00
世界 1347d92ebe Fix UDP DNS server crash 2025-04-25 11:56:06 +08:00
世界 2819ec16f3 documentation: Fix missing ip_accept_any DNS rule option 2025-04-25 11:56:06 +08:00
世界 aa5e7822a4 Fix anytls dialer usage 2025-04-25 11:56:06 +08:00
世界 fa7d03542d Move predefined DNS server to rule action 2025-04-25 11:56:06 +08:00
世界 dbbab063fe Fix domain resolver on direct outbound 2025-04-25 11:56:05 +08:00
Zephyrusoand世界 ded7d45dee Fix missing AnyTLS display name 2025-04-25 11:56:05 +08:00
anytls世界anytls <anytls>
96bf78ddc1 Update sing-anytls
Co-authored-by: anytls <anytls>
2025-04-25 11:56:05 +08:00
Esteland世界 5af81fa969 documentation: Fix typo
Signed-off-by: Estel <callmebedrockdigger@gmail.com>
2025-04-25 11:56:04 +08:00
TargetLockedand世界 a4ff6f2075 Fix parsing legacy DNS options 2025-04-25 11:56:04 +08:00
世界 3ea9468107 Fix DNS fallback 2025-04-25 11:56:04 +08:00
世界 a7c7703fd3 documentation: Fix missing hosts DNS server 2025-04-25 11:56:03 +08:00
anytls世界anytls <anytls>
db33a68eb2 Add MinIdleSession option to AnyTLS outbound
Co-authored-by: anytls <anytls>
2025-04-25 11:56:03 +08:00
ReleTorand世界 c3e4bf6a4c documentation: Minor fixes 2025-04-25 11:56:03 +08:00
libtry486and世界 3e455902c9 documentation: Fix typo
fix typo

Signed-off-by: libtry486 <89328481+libtry486@users.noreply.github.com>
2025-04-25 11:56:02 +08:00
Alireza Ahmadiand世界 aaba387a8a Fix Outbound deadlock 2025-04-25 11:56:02 +08:00
世界 4d1be802cb documentation: Fix AnyTLS doc 2025-04-25 11:56:02 +08:00
anytlsand世界 83ccc72e2b Add AnyTLS protocol 2025-04-25 11:56:02 +08:00
世界 f9e850867a Migrate to stdlib ECH support 2025-04-25 11:56:01 +08:00
世界 342c2361f1 Add fallback local DNS server for iOS 2025-04-25 11:56:01 +08:00
世界 ac4e30b190 Get darwin local DNS server from libresolv 2025-04-25 11:56:00 +08:00
世界 cf008519fd Improve resolve action 2025-04-25 11:56:00 +08:00
世界 91d9fc63b7 Fix toolchain version 2025-04-25 11:55:59 +08:00
世界 7d054da0b1 Add back port hopping to hysteria 1 2025-04-25 11:55:59 +08:00
世界 40d35829e1 Update dependencies 2025-04-25 11:55:59 +08:00
xchacha20-poly1305and世界 41ad180be1 Remove single quotes of raw Moziila certs 2025-04-25 11:55:58 +08:00
世界 9cb07a2387 Add Tailscale endpoint 2025-04-25 11:55:58 +08:00
世界 086784baf3 Build legacy binaries with latest Go 2025-04-25 11:55:58 +08:00
世界 0e8cd7d3be documentation: Remove outdated icons 2025-04-25 11:55:57 +08:00
世界 58f712d222 documentation: Certificate store 2025-04-25 11:55:57 +08:00
世界 dfb7569d11 documentation: TLS fragment 2025-04-25 11:55:56 +08:00
世界 638179fd7c documentation: Outbound domain resolver 2025-04-25 11:55:56 +08:00
世界 69fff5591f documentation: Refactor DNS 2025-04-25 11:55:56 +08:00
世界 7c3c3ddbeb Add certificate store 2025-04-25 11:55:56 +08:00
世界 d88e87b9a4 Add TLS fragment support 2025-04-25 11:55:42 +08:00
世界 1f529be0f1 refactor: Outbound domain resolver 2025-04-25 11:54:18 +08:00
世界 f87808f8c3 refactor: DNS 2025-04-25 11:54:14 +08:00
世界 11e3634a63 Fix panic on some stupid input 2025-04-25 11:49:25 +08:00
世界 c46f70a4c8 Fix ssh outbound 2025-04-25 11:35:22 +08:00
世界 4ed2e1ee1b Fix wireguard listening 2025-04-25 09:55:54 +08:00
世界 aa8a85b4bc option: Fix listable again and again 2025-04-25 09:52:00 +08:00
世界 6103ecb771 option: Fix omitempty reject method 2025-04-25 09:47:45 +08:00
世界 3dbe90c535 release: Fix apt-get install 2025-04-25 09:07:41 +08:00
世界 0eac73a8fd Fix set wireguard reserved on Linux 2025-04-25 09:02:20 +08:00
世界 f9cb268ee7 Fix vmess working with zero uuids 2025-04-25 08:55:26 +08:00
世界 d7085167e7 Fix hysteria1 server panic 2025-04-24 21:46:23 +08:00
世界 c80d62968c Fix DNS crash 2025-04-22 23:02:06 +08:00
29 changed files with 301 additions and 174 deletions
+1 -11
View File
@@ -341,17 +341,7 @@ func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destina
}
func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) {
udpListener := d.udpListener
udpListener.Control = control.Append(udpListener.Control, func(network, address string, conn syscall.RawConn) error {
for _, wgControlFn := range WgControlFns {
err := wgControlFn(network, address, conn)
if err != nil {
return err
}
}
return nil
})
return udpListener.ListenPacket(context.Background(), network, address)
return d.udpListener.ListenPacket(context.Background(), network, address)
}
func trackConn(conn net.Conn, err error) (net.Conn, error) {
+158
View File
@@ -0,0 +1,158 @@
package humanize
import (
"fmt"
"math"
"strconv"
"strings"
"unicode"
)
// IEC Sizes.
// kibis of bits
const (
Byte = 1 << (iota * 10)
KiByte
MiByte
GiByte
TiByte
PiByte
EiByte
)
// SI Sizes.
const (
IByte = 1
KByte = IByte * 1000
MByte = KByte * 1000
GByte = MByte * 1000
TByte = GByte * 1000
PByte = TByte * 1000
EByte = PByte * 1000
)
var defaultSizeTable = map[string]uint64{
"b": Byte,
"kib": KiByte,
"kb": KByte,
"mib": MiByte,
"mb": MByte,
"gib": GiByte,
"gb": GByte,
"tib": TiByte,
"tb": TByte,
"pib": PiByte,
"pb": PByte,
"eib": EiByte,
"eb": EByte,
// Without suffix
"": Byte,
"ki": KiByte,
"k": KByte,
"mi": MiByte,
"m": MByte,
"gi": GiByte,
"g": GByte,
"ti": TiByte,
"t": TByte,
"pi": PiByte,
"p": PByte,
"ei": EiByte,
"e": EByte,
}
var memorysSizeTable = map[string]uint64{
"b": Byte,
"kb": KiByte,
"mb": MiByte,
"gb": GiByte,
"tb": TiByte,
"pb": PiByte,
"eb": EiByte,
"": Byte,
"k": KiByte,
"m": MiByte,
"g": GiByte,
"t": TiByte,
"p": PiByte,
"e": EiByte,
}
var (
defaultSizes = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB"}
iSizes = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"}
)
func Bytes(s uint64) string {
return humanateBytes(s, 1000, defaultSizes)
}
func MemoryBytes(s uint64) string {
return humanateBytes(s, 1024, defaultSizes)
}
func IBytes(s uint64) string {
return humanateBytes(s, 1024, iSizes)
}
func logn(n, b float64) float64 {
return math.Log(n) / math.Log(b)
}
func humanateBytes(s uint64, base float64, sizes []string) string {
if s < 10 {
return fmt.Sprintf("%d B", s)
}
e := math.Floor(logn(float64(s), base))
suffix := sizes[int(e)]
val := math.Floor(float64(s)/math.Pow(base, e)*10+0.5) / 10
f := "%.0f %s"
if val < 10 {
f = "%.1f %s"
}
return fmt.Sprintf(f, val, suffix)
}
func ParseBytes(s string) (uint64, error) {
return parseBytes0(s, defaultSizeTable)
}
func ParseMemoryBytes(s string) (uint64, error) {
return parseBytes0(s, memorysSizeTable)
}
func parseBytes0(s string, sizeTable map[string]uint64) (uint64, error) {
lastDigit := 0
hasComma := false
for _, r := range s {
if !(unicode.IsDigit(r) || r == '.' || r == ',') {
break
}
if r == ',' {
hasComma = true
}
lastDigit++
}
num := s[:lastDigit]
if hasComma {
num = strings.Replace(num, ",", "", -1)
}
f, err := strconv.ParseFloat(num, 64)
if err != nil {
return 0, err
}
extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
if m, ok := sizeTable[extra]; ok {
f *= float64(m)
if f >= math.MaxUint64 {
return 0, fmt.Errorf("too large: %v", s)
}
return uint64(f), nil
}
return 0, fmt.Errorf("unhandled size name: %v", extra)
}
+3 -3
View File
@@ -24,9 +24,9 @@ func applyDebugOptions(options option.DebugOptions) {
if options.TraceBack != "" {
debug.SetTraceback(options.TraceBack)
}
if options.MemoryLimit.Value() != 0 {
debug.SetMemoryLimit(int64(float64(options.MemoryLimit.Value()) / 1.5))
conntrack.MemoryLimit = options.MemoryLimit.Value()
if options.MemoryLimit != 0 {
debug.SetMemoryLimit(int64(float64(options.MemoryLimit) / 1.5))
conntrack.MemoryLimit = uint64(options.MemoryLimit)
}
if options.OOMKiller != nil {
conntrack.KillerEnabled = *options.OOMKiller
+4 -4
View File
@@ -7,9 +7,9 @@ import (
"runtime/debug"
"strings"
"github.com/sagernet/sing-box/common/humanize"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common/byteformats"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"
"github.com/sagernet/sing/common/json/badjson"
@@ -38,9 +38,9 @@ func applyDebugListenOption(options option.DebugOptions) {
runtime.ReadMemStats(&memStats)
var memObject badjson.JSONObject
memObject.Put("heap", byteformats.FormatMemoryBytes(memStats.HeapInuse))
memObject.Put("stack", byteformats.FormatMemoryBytes(memStats.StackInuse))
memObject.Put("idle", byteformats.FormatMemoryBytes(memStats.HeapIdle-memStats.HeapReleased))
memObject.Put("heap", humanize.MemoryBytes(memStats.HeapInuse))
memObject.Put("stack", humanize.MemoryBytes(memStats.StackInuse))
memObject.Put("idle", humanize.MemoryBytes(memStats.HeapIdle-memStats.HeapReleased))
memObject.Put("goroutines", runtime.NumGoroutine())
memObject.Put("rss", rusageMaxRSS())
+5 -2
View File
@@ -268,10 +268,13 @@ func (c *Client) Lookup(ctx context.Context, transport adapter.DNSTransport, dom
return nil
})
err := group.Run(ctx)
if len(response4) == 0 && len(response6) == 0 {
if len(response4) > 0 || len(response6) > 0 {
return sortAddresses(response4, response6, options.Strategy), nil
} else if err != nil {
return nil, err
} else {
return nil, RcodeError(dns.RcodeNameError)
}
return sortAddresses(response4, response6, options.Strategy), nil
}
func (c *Client) ClearCache() {
+3 -7
View File
@@ -323,9 +323,6 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ
err error
)
printResult := func() {
if err == nil && len(responseAddrs) == 0 {
err = E.New("empty result")
}
if err != nil {
if errors.Is(err, ErrResponseRejectedCached) {
r.logger.DebugContext(ctx, "response rejected for ", domain, " (cached)")
@@ -334,15 +331,14 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ
} else {
r.logger.ErrorContext(ctx, E.Cause(err, "lookup failed for ", domain))
}
}
if err != nil {
err = E.Cause(err, "lookup ", domain)
} else if len(responseAddrs) == 0 {
panic("unexpected empty result")
}
}
responseAddrs, cached = r.client.LookupCache(domain, options.Strategy)
if cached {
if len(responseAddrs) == 0 {
return nil, E.New("lookup ", domain, ": empty result (cached)")
return nil, RcodeNameError
}
return responseAddrs, nil
}
-3
View File
@@ -96,9 +96,6 @@ func NewHTTPS(ctx context.Context, logger log.ContextLogger, tag string, options
if serverAddr.Port == 0 {
serverAddr.Port = 443
}
if !serverAddr.IsValid() {
return nil, E.New("invalid server address: ", serverAddr)
}
return NewHTTPSRaw(
dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeHTTPS, tag, options.RemoteDNSServerOptions),
logger,
+2 -4
View File
@@ -3,7 +3,6 @@ package local
import (
"context"
"math/rand"
"net/netip"
"time"
"github.com/sagernet/sing-box/adapter"
@@ -91,9 +90,8 @@ func (t *Transport) exchangeParallel(ctx context.Context, systemConfig *dnsConfi
startRacer := func(ctx context.Context, fqdn string) {
response, err := t.tryOneName(ctx, systemConfig, fqdn, message)
if err == nil {
var addresses []netip.Addr
addresses, err = dns.MessageToAddresses(response)
if err == nil && len(addresses) == 0 {
addresses, _ := dns.MessageToAddresses(response)
if len(addresses) == 0 {
err = E.New(fqdn, ": empty result")
}
}
-3
View File
@@ -92,9 +92,6 @@ func NewHTTP3(ctx context.Context, logger log.ContextLogger, tag string, options
if serverAddr.Port == 0 {
serverAddr.Port = 443
}
if !serverAddr.IsValid() {
return nil, E.New("invalid server address: ", serverAddr)
}
return &HTTP3Transport{
TransportAdapter: dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeHTTP3, tag, options.RemoteDNSServerOptions),
logger: logger,
-4
View File
@@ -16,7 +16,6 @@ import (
sQUIC "github.com/sagernet/sing-quic"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
@@ -59,9 +58,6 @@ func NewQUIC(ctx context.Context, logger log.ContextLogger, tag string, options
if serverAddr.Port == 0 {
serverAddr.Port = 853
}
if !serverAddr.IsValid() {
return nil, E.New("invalid server address: ", serverAddr)
}
return &Transport{
TransportAdapter: dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeQUIC, tag, options.RemoteDNSServerOptions),
ctx: ctx,
-4
View File
@@ -13,7 +13,6 @@ import (
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
@@ -41,9 +40,6 @@ func NewTCP(ctx context.Context, logger log.ContextLogger, tag string, options o
if serverAddr.Port == 0 {
serverAddr.Port = 53
}
if !serverAddr.IsValid() {
return nil, E.New("invalid server address: ", serverAddr)
}
return &TCPTransport{
TransportAdapter: dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeTCP, tag, options),
dialer: transportDialer,
-3
View File
@@ -57,9 +57,6 @@ func NewTLS(ctx context.Context, logger log.ContextLogger, tag string, options o
if serverAddr.Port == 0 {
serverAddr.Port = 853
}
if !serverAddr.IsValid() {
return nil, E.New("invalid server address: ", serverAddr)
}
return &TLSTransport{
TransportAdapter: dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeTLS, tag, options.RemoteDNSServerOptions),
logger: logger,
-4
View File
@@ -13,7 +13,6 @@ import (
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
@@ -48,9 +47,6 @@ func NewUDP(ctx context.Context, logger log.ContextLogger, tag string, options o
if serverAddr.Port == 0 {
serverAddr.Port = 53
}
if !serverAddr.IsValid() {
return nil, E.New("invalid server address: ", serverAddr)
}
return NewUDPRaw(logger, dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeUDP, tag, options), transportDialer, serverAddr), nil
}
-10
View File
@@ -2,16 +2,6 @@
icon: material/alert-decagram
---
#### 1.12.0-beta.7
* Fixes and improvements
### 1.11.9
* Fixes and improvements
_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)._
#### 1.12.0-beta.5
* Fixes and improvements
+10 -12
View File
@@ -42,18 +42,16 @@ AnyTLS padding scheme line array.
Default padding scheme:
```json
[
"stop=8",
"0=30-30",
"1=100-400",
"2=400-500,c,500-1000,c,500-1000,c,500-1000,c,500-1000",
"3=9-9,500-1000",
"4=500-1000",
"5=500-1000",
"6=500-1000",
"7=500-1000"
]
```
stop=8
0=30-30
1=100-400
2=400-500,c,500-1000,c,500-1000,c,500-1000,c,500-1000
3=9-9,500-1000
4=500-1000
5=500-1000
6=500-1000
7=500-1000
```
#### tls
+10 -12
View File
@@ -42,18 +42,16 @@ AnyTLS 填充方案行数组。
默认填充方案:
```json
[
"stop=8",
"0=30-30",
"1=100-400",
"2=400-500,c,500-1000,c,500-1000,c,500-1000,c,500-1000",
"3=9-9,500-1000",
"4=500-1000",
"5=500-1000",
"6=500-1000",
"7=500-1000"
]
```
stop=8
0=30-30
1=100-400
2=400-500,c,500-1000,c,500-1000,c,500-1000,c,500-1000
3=9-9,500-1000
4=500-1000
5=500-1000
6=500-1000
7=500-1000
```
#### tls
+3 -3
View File
@@ -7,10 +7,10 @@ import (
"strconv"
"time"
"github.com/sagernet/sing-box/common/humanize"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/experimental/locale"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common/byteformats"
)
var (
@@ -75,11 +75,11 @@ func Version() string {
}
func FormatBytes(length int64) string {
return byteformats.FormatBytes(uint64(length))
return humanize.Bytes(uint64(length))
}
func FormatMemoryBytes(length int64) string {
return byteformats.FormatMemoryBytes(uint64(length))
return humanize.MemoryBytes(uint64(length))
}
func FormatDuration(duration int64) string {
+2 -2
View File
@@ -26,13 +26,13 @@ require (
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
github.com/sagernet/quic-go v0.49.0-beta.1
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.6.8-0.20250428152347-91813c8e3960
github.com/sagernet/sing v0.6.8-0.20250425035333-84184da91a3a
github.com/sagernet/sing-mux v0.3.1
github.com/sagernet/sing-quic v0.4.1-0.20250423030647-0eb05f373a76
github.com/sagernet/sing-shadowsocks v0.2.7
github.com/sagernet/sing-shadowsocks2 v0.2.0
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056
github.com/sagernet/sing-tun v0.6.6-0.20250428031943-0686f8c4f210
github.com/sagernet/sing-tun v0.6.5-0.20250412112220-15069fc1c20a
github.com/sagernet/sing-vmess v0.2.1
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
github.com/sagernet/tailscale v1.80.3-mod.4
+4 -4
View File
@@ -178,8 +178,8 @@ github.com/sagernet/quic-go v0.49.0-beta.1/go.mod h1:uesWD1Ihrldq1M3XtjuEvIUqi8W
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
github.com/sagernet/sing v0.6.8-0.20250428152347-91813c8e3960 h1:bBSVJ0d5YtbhhwugBXH8GrVaKi1ZIHYdL03LN006Fng=
github.com/sagernet/sing v0.6.8-0.20250428152347-91813c8e3960/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing v0.6.8-0.20250425035333-84184da91a3a h1:oE67hmp5rzLlE6clE7FpK4Hg6yLXsa1Zu3A01vcazb0=
github.com/sagernet/sing v0.6.8-0.20250425035333-84184da91a3a/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-mux v0.3.1 h1:kvCc8HyGAskDHDQ0yQvoTi/7J4cZPB/VJMsAM3MmdQI=
github.com/sagernet/sing-mux v0.3.1/go.mod h1:Mkdz8LnDstthz0HWuA/5foncnDIdcNN5KZ6AdJX+x78=
github.com/sagernet/sing-quic v0.4.1-0.20250423030647-0eb05f373a76 h1:iwpCX6H3nZEOGUGwx0q5azcgYOA9f6v9YssihXoRKHk=
@@ -190,8 +190,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056 h1:GFNJQAHhSXqAfxAw1wDG/QWbdpGH5Na3k8qUynqWnEA=
github.com/sagernet/sing-shadowtls v0.2.1-0.20250316154757-6f9e732e5056/go.mod h1:HyacBPIFiKihJQR8LQp56FM4hBtd/7MZXnRxxQIOPsc=
github.com/sagernet/sing-tun v0.6.6-0.20250428031943-0686f8c4f210 h1:6H4BZaTqKI3YcDMyTV3E576LuJM4S4wY99xoq2T1ECw=
github.com/sagernet/sing-tun v0.6.6-0.20250428031943-0686f8c4f210/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
github.com/sagernet/sing-tun v0.6.5-0.20250412112220-15069fc1c20a h1:2aLxZFD2HPCLrnFGpH+KBuPqMOk0cuaDE2dgEvANuMk=
github.com/sagernet/sing-tun v0.6.5-0.20250412112220-15069fc1c20a/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
github.com/sagernet/sing-vmess v0.2.1 h1:6izHC2+B68aQCxTagki6eZZc+g5eh4dYwxOV5a2Lhug=
github.com/sagernet/sing-vmess v0.2.1/go.mod h1:jDAZ0A0St1zVRkyvhAPRySOFfhC+4SQtO5VYyeFotgA=
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
+38 -9
View File
@@ -1,14 +1,43 @@
package option
import "github.com/sagernet/sing/common/byteformats"
import (
"github.com/sagernet/sing-box/common/humanize"
"github.com/sagernet/sing/common/json"
)
type DebugOptions struct {
Listen string `json:"listen,omitempty"`
GCPercent *int `json:"gc_percent,omitempty"`
MaxStack *int `json:"max_stack,omitempty"`
MaxThreads *int `json:"max_threads,omitempty"`
PanicOnFault *bool `json:"panic_on_fault,omitempty"`
TraceBack string `json:"trace_back,omitempty"`
MemoryLimit *byteformats.MemoryBytes `json:"memory_limit,omitempty"`
OOMKiller *bool `json:"oom_killer,omitempty"`
Listen string `json:"listen,omitempty"`
GCPercent *int `json:"gc_percent,omitempty"`
MaxStack *int `json:"max_stack,omitempty"`
MaxThreads *int `json:"max_threads,omitempty"`
PanicOnFault *bool `json:"panic_on_fault,omitempty"`
TraceBack string `json:"trace_back,omitempty"`
MemoryLimit MemoryBytes `json:"memory_limit,omitempty"`
OOMKiller *bool `json:"oom_killer,omitempty"`
}
type MemoryBytes uint64
func (l MemoryBytes) MarshalJSON() ([]byte, error) {
return json.Marshal(humanize.MemoryBytes(uint64(l)))
}
func (l *MemoryBytes) UnmarshalJSON(bytes []byte) error {
var valueInteger int64
err := json.Unmarshal(bytes, &valueInteger)
if err == nil {
*l = MemoryBytes(valueInteger)
return nil
}
var valueString string
err = json.Unmarshal(bytes, &valueString)
if err != nil {
return err
}
parsedValue, err := humanize.ParseMemoryBytes(valueString)
if err != nil {
return err
}
*l = MemoryBytes(parsedValue)
return nil
}
+24 -27
View File
@@ -1,22 +1,19 @@
package option
import (
"github.com/sagernet/sing/common/byteformats"
"github.com/sagernet/sing/common/json/badoption"
)
import "github.com/sagernet/sing/common/json/badoption"
type HysteriaInboundOptions struct {
ListenOptions
Up *byteformats.NetworkBytesCompat `json:"up,omitempty"`
UpMbps int `json:"up_mbps,omitempty"`
Down *byteformats.NetworkBytesCompat `json:"down,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs string `json:"obfs,omitempty"`
Users []HysteriaUser `json:"users,omitempty"`
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
ReceiveWindowClient uint64 `json:"recv_window_client,omitempty"`
MaxConnClient int `json:"max_conn_client,omitempty"`
DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"`
Up string `json:"up,omitempty"`
UpMbps int `json:"up_mbps,omitempty"`
Down string `json:"down,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs string `json:"obfs,omitempty"`
Users []HysteriaUser `json:"users,omitempty"`
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
ReceiveWindowClient uint64 `json:"recv_window_client,omitempty"`
MaxConnClient int `json:"max_conn_client,omitempty"`
DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"`
InboundTLSOptionsContainer
}
@@ -29,18 +26,18 @@ type HysteriaUser struct {
type HysteriaOutboundOptions struct {
DialerOptions
ServerOptions
ServerPorts badoption.Listable[string] `json:"server_ports,omitempty"`
HopInterval badoption.Duration `json:"hop_interval,omitempty"`
Up *byteformats.NetworkBytesCompat `json:"up,omitempty"`
UpMbps int `json:"up_mbps,omitempty"`
Down *byteformats.NetworkBytesCompat `json:"down,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs string `json:"obfs,omitempty"`
Auth []byte `json:"auth,omitempty"`
AuthString string `json:"auth_str,omitempty"`
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
ReceiveWindow uint64 `json:"recv_window,omitempty"`
DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"`
Network NetworkList `json:"network,omitempty"`
ServerPorts badoption.Listable[string] `json:"server_ports,omitempty"`
HopInterval badoption.Duration `json:"hop_interval,omitempty"`
Up string `json:"up,omitempty"`
UpMbps int `json:"up_mbps,omitempty"`
Down string `json:"down,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs string `json:"obfs,omitempty"`
Auth []byte `json:"auth,omitempty"`
AuthString string `json:"auth_str,omitempty"`
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
ReceiveWindow uint64 `json:"recv_window,omitempty"`
DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"`
Network NetworkList `json:"network,omitempty"`
OutboundTLSOptionsContainer
}
+1
View File
@@ -83,6 +83,7 @@ type DialerOptions struct {
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
FallbackNetworkType badoption.Listable[InterfaceType] `json:"fallback_network_type,omitempty"`
FallbackDelay badoption.Duration `json:"fallback_delay,omitempty"`
IsWireGuardListener bool `json:"-"`
// Deprecated: migrated to domain resolver
DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"`
+12 -4
View File
@@ -7,6 +7,7 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/adapter/inbound"
"github.com/sagernet/sing-box/common/humanize"
"github.com/sagernet/sing-box/common/listener"
"github.com/sagernet/sing-box/common/tls"
C "github.com/sagernet/sing-box/constant"
@@ -15,6 +16,7 @@ import (
"github.com/sagernet/sing-quic/hysteria"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/auth"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
@@ -54,13 +56,19 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
tlsConfig: tlsConfig,
}
var sendBps, receiveBps uint64
if options.Up.Value() > 0 {
sendBps = options.Up.Value()
if len(options.Up) > 0 {
sendBps, err = humanize.ParseBytes(options.Up)
if err != nil {
return nil, E.Cause(err, "invalid up speed format: ", options.Up)
}
} else {
sendBps = uint64(options.UpMbps) * hysteria.MbpsToBps
}
if options.Down.Value() > 0 {
receiveBps = options.Down.Value()
if len(options.Down) > 0 {
receiveBps, err = humanize.ParseBytes(options.Down)
if err != nil {
return nil, E.Cause(err, "invalid down speed format: ", options.Down)
}
} else {
receiveBps = uint64(options.DownMbps) * hysteria.MbpsToBps
}
+11 -4
View File
@@ -9,6 +9,7 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/adapter/outbound"
"github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/common/humanize"
"github.com/sagernet/sing-box/common/tls"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
@@ -59,13 +60,19 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
password = string(options.Auth)
}
var sendBps, receiveBps uint64
if options.Up.Value() > 0 {
sendBps = options.Up.Value()
if len(options.Up) > 0 {
sendBps, err = humanize.ParseBytes(options.Up)
if err != nil {
return nil, E.Cause(err, "invalid up speed format: ", options.Up)
}
} else {
sendBps = uint64(options.UpMbps) * hysteria.MbpsToBps
}
if options.Down.Value() > 0 {
receiveBps = options.Down.Value()
if len(options.Down) > 0 {
receiveBps, err = humanize.ParseBytes(options.Down)
if err != nil {
return nil, E.Cause(err, "invalid down speed format: ", options.Down)
}
} else {
receiveBps = uint64(options.DownMbps) * hysteria.MbpsToBps
}
+2 -2
View File
@@ -45,8 +45,8 @@ func NewEndpoint(ctx context.Context, router adapter.Router, logger log.ContextL
logger: logger,
localAddresses: options.Address,
}
if options.Detour != "" && options.ListenPort != 0 {
return nil, E.New("`listen_port` is conflict with `detour`")
if options.Detour == "" {
options.IsWireGuardListener = true
}
outboundDialer, err := dialer.NewWithOptions(dialer.Options{
Context: ctx,
+3 -1
View File
@@ -46,7 +46,9 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
logger: logger,
localAddresses: options.LocalAddress,
}
if options.Detour != "" && options.GSO {
if options.Detour == "" {
options.IsWireGuardListener = true
} else if options.GSO {
return nil, E.New("gso is conflict with detour")
}
outboundDialer, err := dialer.NewWithOptions(dialer.Options{
+3 -30
View File
@@ -7,7 +7,6 @@ import (
"net"
"net/netip"
"os"
"strings"
"sync"
"sync/atomic"
"time"
@@ -67,17 +66,7 @@ func (m *ConnectionManager) NewConnection(ctx context.Context, this N.Dialer, co
remoteConn, err = this.DialContext(ctx, N.NetworkTCP, metadata.Destination)
}
if err != nil {
var remoteString string
if len(metadata.DestinationAddresses) > 0 {
remoteString = "[" + strings.Join(common.Map(metadata.DestinationAddresses, netip.Addr.String), ",") + "]"
} else {
remoteString = metadata.Destination.String()
}
var dialerString string
if outbound, isOutbound := this.(adapter.Outbound); isOutbound {
dialerString = " using outbound/" + outbound.Type() + "[" + outbound.Tag() + "]"
}
err = E.Cause(err, "open connection to ", remoteString, dialerString)
err = E.Cause(err, "open outbound connection")
N.CloseOnHandshakeFailure(conn, onClose, err)
m.logger.ErrorContext(ctx, err)
return
@@ -144,19 +133,8 @@ func (m *ConnectionManager) NewPacketConnection(ctx context.Context, this N.Dial
remoteConn, err = this.DialContext(ctx, N.NetworkUDP, metadata.Destination)
}
if err != nil {
var remoteString string
if len(metadata.DestinationAddresses) > 0 {
remoteString = "[" + strings.Join(common.Map(metadata.DestinationAddresses, netip.Addr.String), ",") + "]"
} else {
remoteString = metadata.Destination.String()
}
var dialerString string
if outbound, isOutbound := this.(adapter.Outbound); isOutbound {
dialerString = " using outbound/" + outbound.Type() + "[" + outbound.Tag() + "]"
}
err = E.Cause(err, "open packet connection to ", remoteString, dialerString)
N.CloseOnHandshakeFailure(conn, onClose, err)
m.logger.ErrorContext(ctx, err)
m.logger.ErrorContext(ctx, "open outbound packet connection: ", err)
return
}
remotePacketConn = bufio.NewUnbindPacketConn(remoteConn)
@@ -171,13 +149,8 @@ func (m *ConnectionManager) NewPacketConnection(ctx context.Context, this N.Dial
remotePacketConn, err = this.ListenPacket(ctx, metadata.Destination)
}
if err != nil {
var dialerString string
if outbound, isOutbound := this.(adapter.Outbound); isOutbound {
dialerString = " using outbound/" + outbound.Type() + "[" + outbound.Tag() + "]"
}
err = E.Cause(err, "listen packet connection using ", dialerString)
N.CloseOnHandshakeFailure(conn, onClose, err)
m.logger.ErrorContext(ctx, err)
m.logger.ErrorContext(ctx, "listen outbound packet connection: ", err)
return
}
}
+1 -1
View File
@@ -141,7 +141,7 @@ func (e *Endpoint) Start(resolve bool) error {
return nil
}
var bind conn.Bind
wgListener, isWgListener := common.Cast[conn.Listener](e.options.Dialer)
wgListener, isWgListener := e.options.Dialer.(conn.Listener)
if isWgListener {
bind = conn.NewStdNetBind(wgListener)
} else {