mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
Compare commits
44 Commits
7b7820a322
...
c131c1bdca
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c131c1bdca | ||
![]() |
07f633af2a | ||
![]() |
69e8c7b4fb | ||
![]() |
2fa8c77bc4 | ||
![]() |
c926fae081 | ||
![]() |
06a3712f1d | ||
![]() |
6f63c9b416 | ||
![]() |
aed9a50988 | ||
![]() |
be664fb221 | ||
![]() |
2e44ecf0ca | ||
![]() |
f97046b4fa | ||
![]() |
4ab3d1e2a9 | ||
![]() |
273cd5e726 | ||
![]() |
f3a2fec725 | ||
![]() |
e46d66c5cf | ||
![]() |
efc4c653d9 | ||
![]() |
becc8dbedf | ||
![]() |
84d69f4363 | ||
![]() |
970d4dded1 | ||
![]() |
94a2845585 | ||
![]() |
bb18a23370 | ||
![]() |
6f25cf80e9 | ||
![]() |
c6d6a10ca7 | ||
![]() |
8ecfb6feb3 | ||
![]() |
538b0b70b6 | ||
![]() |
d7d3c09523 | ||
![]() |
35a227ab4f | ||
![]() |
d356f0f0a2 | ||
![]() |
3c5e618006 | ||
![]() |
6bdcdfc4de | ||
![]() |
a7041ee791 | ||
![]() |
36fcffc022 | ||
![]() |
b789b69d78 | ||
![]() |
3b21852b85 | ||
![]() |
b967be7fde | ||
![]() |
7e94fe66f0 | ||
![]() |
49f4802d2c | ||
![]() |
b1abb73b04 | ||
![]() |
9ec5b07bfb | ||
![]() |
a3c95327e4 | ||
![]() |
2d45335723 | ||
![]() |
6e66c232b9 | ||
![]() |
ccd3de39eb | ||
![]() |
4f3ee61104 |
@ -103,9 +103,14 @@ func NewWithOptions(options Options) (N.Dialer, error) {
|
|||||||
resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
|
resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
|
||||||
} else if options.NewDialer {
|
} else if options.NewDialer {
|
||||||
return nil, E.New("missing domain resolver for domain server address")
|
return nil, E.New("missing domain resolver for domain server address")
|
||||||
|
} else {
|
||||||
|
transports := dnsTransport.Transports()
|
||||||
|
if len(transports) < 2 {
|
||||||
|
dnsQueryOptions.Transport = dnsTransport.Default()
|
||||||
} else {
|
} else {
|
||||||
deprecated.Report(options.Context, deprecated.OptionMissingDomainResolver)
|
deprecated.Report(options.Context, deprecated.OptionMissingDomainResolver)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
dialer = NewResolveDialer(
|
dialer = NewResolveDialer(
|
||||||
options.Context,
|
options.Context,
|
||||||
dialer,
|
dialer,
|
||||||
|
@ -4,8 +4,15 @@ icon: material/alert-decagram
|
|||||||
|
|
||||||
#### 1.12.0-alpha.16
|
#### 1.12.0-alpha.16
|
||||||
|
|
||||||
|
* Update `domain_resolver` behavior **1**
|
||||||
* Fixes and improvements
|
* 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
|
||||||
|
@ -106,6 +106,10 @@ Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
|||||||
|
|
||||||
`outbound` DNS rule items are deprecated and will be removed in sing-box 1.14.0, so this item will be required for outbound/endpoints using domain name in server address since sing-box 1.14.0.
|
`outbound` DNS rule items are deprecated and will be removed in sing-box 1.14.0, so this item will be required for outbound/endpoints using domain name in server address since sing-box 1.14.0.
|
||||||
|
|
||||||
|
!!! info ""
|
||||||
|
|
||||||
|
`domain_resolver` or `route.default_domain_resolver` is optional when only one DNS server is configured.
|
||||||
|
|
||||||
Set domain resolver to use for resolving domain names.
|
Set domain resolver to use for resolving domain names.
|
||||||
|
|
||||||
This option uses the same format as the [route DNS rule action](/configuration/dns/rule_action/#route) without the `action` field.
|
This option uses the same format as the [route DNS rule action](/configuration/dns/rule_action/#route) without the `action` field.
|
||||||
|
@ -105,6 +105,10 @@ icon: material/new-box
|
|||||||
|
|
||||||
`outbound` DNS 规则项已弃用,且将在 sing-box 1.14.0 中被移除。因此,从 sing-box 1.14.0 版本开始,所有在服务器地址中使用域名的出站/端点均需配置此项。
|
`outbound` DNS 规则项已弃用,且将在 sing-box 1.14.0 中被移除。因此,从 sing-box 1.14.0 版本开始,所有在服务器地址中使用域名的出站/端点均需配置此项。
|
||||||
|
|
||||||
|
!!! info ""
|
||||||
|
|
||||||
|
当只有一个 DNS 服务器已配置时,`domain_resolver` 或 `route.default_domain_resolver` 是可选的。
|
||||||
|
|
||||||
用于设置解析域名的域名解析器。
|
用于设置解析域名的域名解析器。
|
||||||
|
|
||||||
此选项的格式与 [路由 DNS 规则动作](/configuration/dns/rule_action/#route) 相同,但不包含 `action` 字段。
|
此选项的格式与 [路由 DNS 规则动作](/configuration/dns/rule_action/#route) 相同,但不包含 `action` 字段。
|
||||||
|
@ -116,7 +116,14 @@ func (o *DomainResolveOptions) UnmarshalJSON(bytes []byte) error {
|
|||||||
o.Server = stringValue
|
o.Server = stringValue
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return json.Unmarshal(bytes, (*_DomainResolveOptions)(o))
|
err = json.Unmarshal(bytes, (*_DomainResolveOptions)(o))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if o.Server == "" {
|
||||||
|
return E.New("empty domain_resolver.server")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *DialerOptions) TakeDialerOptions() DialerOptions {
|
func (o *DialerOptions) TakeDialerOptions() DialerOptions {
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -14,6 +15,7 @@ import (
|
|||||||
"github.com/sagernet/sing-box/common/tlsfragment"
|
"github.com/sagernet/sing-box/common/tlsfragment"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
"github.com/sagernet/sing/common/canceler"
|
"github.com/sagernet/sing/common/canceler"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
@ -206,14 +208,16 @@ func (m *ConnectionManager) NewPacketConnection(ctx context.Context, this N.Dial
|
|||||||
go m.packetConnectionCopy(ctx, destination, conn, true, &done, onClose)
|
go m.packetConnectionCopy(ctx, destination, conn, true, &done, onClose)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ConnectionManager) connectionCopy(ctx context.Context, source io.Reader, destination io.Writer, direction bool, done *atomic.Bool, onClose N.CloseHandlerFunc) {
|
func (m *ConnectionManager) connectionCopy(ctx context.Context, source net.Conn, destination net.Conn, direction bool, done *atomic.Bool, onClose N.CloseHandlerFunc) {
|
||||||
originSource := source
|
var (
|
||||||
originDestination := destination
|
sourceReader io.Reader = source
|
||||||
|
destinationWriter io.Writer = destination
|
||||||
|
)
|
||||||
var readCounters, writeCounters []N.CountFunc
|
var readCounters, writeCounters []N.CountFunc
|
||||||
for {
|
for {
|
||||||
source, readCounters = N.UnwrapCountReader(source, readCounters)
|
sourceReader, readCounters = N.UnwrapCountReader(sourceReader, readCounters)
|
||||||
destination, writeCounters = N.UnwrapCountWriter(destination, writeCounters)
|
destinationWriter, writeCounters = N.UnwrapCountWriter(destinationWriter, writeCounters)
|
||||||
if cachedSrc, isCached := source.(N.CachedReader); isCached {
|
if cachedSrc, isCached := sourceReader.(N.CachedReader); isCached {
|
||||||
cachedBuffer := cachedSrc.ReadCached()
|
cachedBuffer := cachedSrc.ReadCached()
|
||||||
if cachedBuffer != nil {
|
if cachedBuffer != nil {
|
||||||
dataLen := cachedBuffer.Len()
|
dataLen := cachedBuffer.Len()
|
||||||
@ -223,7 +227,7 @@ func (m *ConnectionManager) connectionCopy(ctx context.Context, source io.Reader
|
|||||||
if done.Swap(true) {
|
if done.Swap(true) {
|
||||||
onClose(err)
|
onClose(err)
|
||||||
}
|
}
|
||||||
common.Close(originSource, originDestination)
|
common.Close(source, destination)
|
||||||
if !direction {
|
if !direction {
|
||||||
m.logger.ErrorContext(ctx, "connection upload payload: ", err)
|
m.logger.ErrorContext(ctx, "connection upload payload: ", err)
|
||||||
} else {
|
} else {
|
||||||
@ -242,9 +246,13 @@ func (m *ConnectionManager) connectionCopy(ctx context.Context, source io.Reader
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if earlyConn, isEarlyConn := common.Cast[N.EarlyConn](destination); isEarlyConn && earlyConn.NeedHandshake() {
|
if earlyConn, isEarlyConn := common.Cast[N.EarlyConn](destinationWriter); isEarlyConn && earlyConn.NeedHandshake() {
|
||||||
_, err := destination.Write(nil)
|
err := m.connectionCopyEarly(source, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if done.Swap(true) {
|
||||||
|
onClose(err)
|
||||||
|
}
|
||||||
|
common.Close(source, destination)
|
||||||
if !direction {
|
if !direction {
|
||||||
m.logger.ErrorContext(ctx, "connection upload handshake: ", err)
|
m.logger.ErrorContext(ctx, "connection upload handshake: ", err)
|
||||||
} else {
|
} else {
|
||||||
@ -253,20 +261,20 @@ func (m *ConnectionManager) connectionCopy(ctx context.Context, source io.Reader
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err := bufio.CopyWithCounters(destination, source, originSource, readCounters, writeCounters)
|
_, err := bufio.CopyWithCounters(destination, sourceReader, source, readCounters, writeCounters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.Close(originDestination)
|
common.Close(source, destination)
|
||||||
} else if duplexDst, isDuplex := destination.(N.WriteCloser); isDuplex {
|
} else if duplexDst, isDuplex := destination.(N.WriteCloser); isDuplex {
|
||||||
err = duplexDst.CloseWrite()
|
err = duplexDst.CloseWrite()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.Close(originSource, originDestination)
|
common.Close(source, destination)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
common.Close(originDestination)
|
destination.Close()
|
||||||
}
|
}
|
||||||
if done.Swap(true) {
|
if done.Swap(true) {
|
||||||
onClose(err)
|
onClose(err)
|
||||||
common.Close(originSource, originDestination)
|
common.Close(source, destination)
|
||||||
}
|
}
|
||||||
if !direction {
|
if !direction {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -287,6 +295,28 @@ func (m *ConnectionManager) connectionCopy(ctx context.Context, source io.Reader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *ConnectionManager) connectionCopyEarly(source net.Conn, destination io.Writer) error {
|
||||||
|
payload := buf.NewPacket()
|
||||||
|
defer payload.Release()
|
||||||
|
err := source.SetReadDeadline(time.Now().Add(C.ReadPayloadTimeout))
|
||||||
|
if err != nil {
|
||||||
|
if err == os.ErrInvalid {
|
||||||
|
return common.Error(destination.Write(nil))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = payload.ReadOnceFrom(source)
|
||||||
|
if err != nil && !E.IsTimeout(err) {
|
||||||
|
return E.Cause(err, "read payload")
|
||||||
|
}
|
||||||
|
_ = source.SetReadDeadline(time.Time{})
|
||||||
|
_, err = destination.Write(payload.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "write payload")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *ConnectionManager) packetConnectionCopy(ctx context.Context, source N.PacketReader, destination N.PacketWriter, direction bool, done *atomic.Bool, onClose N.CloseHandlerFunc) {
|
func (m *ConnectionManager) packetConnectionCopy(ctx context.Context, source N.PacketReader, destination N.PacketWriter, direction bool, done *atomic.Bool, onClose N.CloseHandlerFunc) {
|
||||||
_, err := bufio.CopyPacket(destination, source)
|
_, err := bufio.CopyPacket(destination, source)
|
||||||
if !direction {
|
if !direction {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user