Compare commits

..

25 Commits

Author SHA1 Message Date
世界
3572acf266
documentation: Bump version 2025-08-20 09:22:04 +08:00
世界
92d175c615
Fix wireguard crash 2025-08-20 09:22:04 +08:00
世界
ca90727e9b
documentation: Update behavior of local DNS server on darwin 2025-08-20 09:22:04 +08:00
世界
9510bc7911
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-08-20 09:22:04 +08:00
世界
e2281f4f9d
Remove use of ldflags -checklinkname=0 on darwin 2025-08-20 09:22:04 +08:00
世界
b18c002b3c
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-08-20 09:22:03 +08:00
世界
a81bbbd811
Fix legacy DNS config 2025-08-20 09:22:03 +08:00
世界
9629d6cab7
Fix rule-set format 2025-08-20 09:22:03 +08:00
世界
32f64972e1
documentation: Remove outdated icons 2025-08-20 09:22:03 +08:00
世界
dd894adeb5
documentation: Improve local DNS server 2025-08-20 09:22:03 +08:00
世界
4f9e334679
Use libresolv in local DNS server on darwin 2025-08-20 09:22:02 +08:00
世界
fc1204fb8b
Use resolved in local DNS server if available 2025-08-20 09:22:02 +08:00
xchacha20-poly1305
5ca20e1cf6
Fix rule set version 2025-08-20 09:22:02 +08:00
世界
8073f299dd
documentation: Add preferred_by route rule item 2025-08-20 09:22:02 +08:00
世界
005cdadffb
Add preferred_by route rule item 2025-08-20 09:22:02 +08:00
世界
8b511086e4
documentation: Add interface address rule items 2025-08-20 09:22:02 +08:00
世界
253750a555
Add interface address rule items 2025-08-20 09:22:01 +08:00
neletor
213c2be747
Add support for ech retry configs 2025-08-20 09:22:01 +08:00
Zephyruso
5fdc3e3edb
Add /dns/flush-clash meta api 2025-08-20 09:22:01 +08:00
世界
97f0dc8a60
Bump version 2025-08-20 09:20:41 +08:00
dyhkwong
ee02532ab5
Fix tlsfragment fallback writeAndWaitAck 2025-08-20 09:20:41 +08:00
世界
f1dd0dba78
Make ReadWaitConn reader replaceable 2025-08-20 09:18:03 +08:00
wwqgtxx
f4ed684146
Update cast using in sing-vmess 2025-08-20 08:45:09 +08:00
wwqgtxx
83f02d0bfb
Make utlsConnWrapper replaceable 2025-08-20 08:45:09 +08:00
wwqgtxx
52fa5f20a3
Make realityConnWrapper replaceable 2025-08-20 08:45:09 +08:00
7 changed files with 37 additions and 15 deletions

View File

@ -128,6 +128,10 @@ func (c *ReadWaitConn) Upstream() any {
return c.Conn return c.Conn
} }
func (c *ReadWaitConn) ReaderReplaceable() bool {
return true
}
var tlsRegistry []func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) var tlsRegistry []func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error)
func init() { func init() {

View File

@ -6,22 +6,26 @@ import (
"net" "net"
_ "unsafe" _ "unsafe"
"github.com/sagernet/sing/common"
"github.com/metacubex/utls" "github.com/metacubex/utls"
) )
func init() { func init() {
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) { tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) {
tlsConn, loaded := common.Cast[*tls.UConn](conn) switch tlsConn := conn.(type) {
if !loaded { case *tls.UConn:
return return true, func() error {
return utlsReadRecord(tlsConn.Conn)
}, func() error {
return utlsHandlePostHandshakeMessage(tlsConn.Conn)
}
case *tls.Conn:
return true, func() error {
return utlsReadRecord(tlsConn)
}, func() error {
return utlsHandlePostHandshakeMessage(tlsConn)
}
} }
return true, func() error { return
return utlsReadRecord(tlsConn.Conn)
}, func() error {
return utlsHandlePostHandshakeMessage(tlsConn.Conn)
}
}) })
} }

View File

@ -109,6 +109,9 @@ func (c *Conn) Write(b []byte) (n int, err error) {
if err != nil { if err != nil {
return return
} }
if i != len(splitIndexes) {
time.Sleep(c.fallbackDelay)
}
} }
} }
} }

View File

@ -9,6 +9,10 @@ import (
) )
func writeAndWaitAck(ctx context.Context, conn *net.TCPConn, payload []byte, fallbackDelay time.Duration) error { func writeAndWaitAck(ctx context.Context, conn *net.TCPConn, payload []byte, fallbackDelay time.Duration) error {
_, err := conn.Write(payload)
if err != nil {
return err
}
time.Sleep(fallbackDelay) time.Sleep(fallbackDelay)
return nil return nil
} }

View File

@ -16,6 +16,9 @@ func writeAndWaitAck(ctx context.Context, conn *net.TCPConn, payload []byte, fal
err := winiphlpapi.WriteAndWaitAck(ctx, conn, payload) err := winiphlpapi.WriteAndWaitAck(ctx, conn, payload)
if err != nil { if err != nil {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) { if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
if _, err := conn.Write(payload); err != nil {
return err
}
time.Sleep(fallbackDelay) time.Sleep(fallbackDelay)
return nil return nil
} }

View File

@ -76,6 +76,8 @@ func NewRawTransport(transportAdapter dns.TransportAdapter, ctx context.Context,
dialer: dialer, dialer: dialer,
logger: logger, logger: logger,
networkManager: service.FromContext[adapter.NetworkManager](ctx), networkManager: service.FromContext[adapter.NetworkManager](ctx),
ndots: 1,
attempts: 2,
} }
} }
@ -83,13 +85,15 @@ func (t *Transport) Start(stage adapter.StartStage) error {
if stage != adapter.StartStateStart { if stage != adapter.StartStateStart {
return nil return nil
} }
_, err := t.Fetch()
if err != nil {
t.logger.Error(E.Cause(err, "fetch DNS servers"))
}
if t.interfaceName == "" { if t.interfaceName == "" {
t.interfaceCallback = t.networkManager.InterfaceMonitor().RegisterCallback(t.interfaceUpdated) t.interfaceCallback = t.networkManager.InterfaceMonitor().RegisterCallback(t.interfaceUpdated)
} }
go func() {
_, err := t.Fetch()
if err != nil {
t.logger.Error(E.Cause(err, "fetch DNS servers"))
}
}()
return nil return nil
} }

View File

@ -85,7 +85,7 @@ func (t *Transport) tryOneName(ctx context.Context, servers []M.Socksaddr, fqdn
var lastErr error var lastErr error
for i := 0; i < t.attempts; i++ { for i := 0; i < t.attempts; i++ {
for j := 0; j < sLen; j++ { for j := 0; j < sLen; j++ {
server := servers[j%sLen] server := servers[j]
question := message.Question[0] question := message.Question[0]
question.Name = fqdn question.Name = fqdn
response, err := t.exchangeOne(ctx, server, question, C.DNSTimeout, false, true) response, err := t.exchangeOne(ctx, server, question, C.DNSTimeout, false, true)