Resolve conflicts

This commit is contained in:
Sergei Maklagin
2025-08-15 12:56:52 +03:00
365 changed files with 22978 additions and 4724 deletions

View File

@@ -14,7 +14,6 @@ import (
"github.com/sagernet/sing-box/common/sniff"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
@@ -22,6 +21,8 @@ import (
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/miekg/dns"
)
func NewRuleAction(ctx context.Context, logger logger.ContextLogger, action option.RuleAction) (adapter.RuleAction, error) {
@@ -39,6 +40,9 @@ func NewRuleAction(ctx context.Context, logger logger.ContextLogger, action opti
FallbackDelay: time.Duration(action.RouteOptions.FallbackDelay),
UDPDisableDomainUnmapping: action.RouteOptions.UDPDisableDomainUnmapping,
UDPConnect: action.RouteOptions.UDPConnect,
TLSFragment: action.RouteOptions.TLSFragment,
TLSFragmentFallbackDelay: time.Duration(action.RouteOptions.TLSFragmentFallbackDelay),
TLSRecordFragment: action.RouteOptions.TLSRecordFragment,
},
}, nil
case C.RuleActionTypeRouteOptions:
@@ -50,9 +54,12 @@ func NewRuleAction(ctx context.Context, logger logger.ContextLogger, action opti
UDPDisableDomainUnmapping: action.RouteOptionsOptions.UDPDisableDomainUnmapping,
UDPConnect: action.RouteOptionsOptions.UDPConnect,
UDPTimeout: time.Duration(action.RouteOptionsOptions.UDPTimeout),
TLSFragment: action.RouteOptionsOptions.TLSFragment,
TLSFragmentFallbackDelay: time.Duration(action.RouteOptionsOptions.TLSFragmentFallbackDelay),
TLSRecordFragment: action.RouteOptionsOptions.TLSRecordFragment,
}, nil
case C.RuleActionTypeDirect:
directDialer, err := dialer.New(ctx, option.DialerOptions(action.DirectOptions))
directDialer, err := dialer.New(ctx, option.DialerOptions(action.DirectOptions), false)
if err != nil {
return nil, err
}
@@ -87,8 +94,11 @@ func NewRuleAction(ctx context.Context, logger logger.ContextLogger, action opti
return sniffAction, sniffAction.build()
case C.RuleActionTypeResolve:
return &RuleActionResolve{
Strategy: dns.DomainStrategy(action.ResolveOptions.Strategy),
Server: action.ResolveOptions.Server,
Server: action.ResolveOptions.Server,
Strategy: C.DomainStrategy(action.ResolveOptions.Strategy),
DisableCache: action.ResolveOptions.DisableCache,
RewriteTTL: action.ResolveOptions.RewriteTTL,
ClientSubnet: action.ResolveOptions.ClientSubnet.Build(netip.Prefix{}),
}, nil
default:
panic(F.ToString("unknown rule action: ", action.Action))
@@ -103,6 +113,7 @@ func NewDNSRuleAction(logger logger.ContextLogger, action option.DNSRuleAction)
return &RuleActionDNSRoute{
Server: action.RouteOptions.Server,
RuleActionDNSRouteOptions: RuleActionDNSRouteOptions{
Strategy: C.DomainStrategy(action.RouteOptions.Strategy),
DisableCache: action.RouteOptions.DisableCache,
RewriteTTL: action.RouteOptions.RewriteTTL,
ClientSubnet: netip.Prefix(common.PtrValueOrDefault(action.RouteOptions.ClientSubnet)),
@@ -110,6 +121,7 @@ func NewDNSRuleAction(logger logger.ContextLogger, action option.DNSRuleAction)
}
case C.RuleActionTypeRouteOptions:
return &RuleActionDNSRouteOptions{
Strategy: C.DomainStrategy(action.RouteOptionsOptions.Strategy),
DisableCache: action.RouteOptionsOptions.DisableCache,
RewriteTTL: action.RouteOptionsOptions.RewriteTTL,
ClientSubnet: netip.Prefix(common.PtrValueOrDefault(action.RouteOptionsOptions.ClientSubnet)),
@@ -120,6 +132,13 @@ func NewDNSRuleAction(logger logger.ContextLogger, action option.DNSRuleAction)
NoDrop: action.RejectOptions.NoDrop,
logger: logger,
}
case C.RuleActionTypePredefined:
return &RuleActionPredefined{
Rcode: action.PredefinedOptions.Rcode.Build(),
Answer: common.Map(action.PredefinedOptions.Answer, option.DNSRecordOptions.Build),
Ns: common.Map(action.PredefinedOptions.Ns, option.DNSRecordOptions.Build),
Extra: common.Map(action.PredefinedOptions.Extra, option.DNSRecordOptions.Build),
}
default:
panic(F.ToString("unknown rule action: ", action.Action))
}
@@ -137,12 +156,7 @@ func (r *RuleActionRoute) Type() string {
func (r *RuleActionRoute) String() string {
var descriptions []string
descriptions = append(descriptions, r.Outbound)
if r.UDPDisableDomainUnmapping {
descriptions = append(descriptions, "udp-disable-domain-unmapping")
}
if r.UDPConnect {
descriptions = append(descriptions, "udp-connect")
}
descriptions = append(descriptions, r.Descriptions()...)
return F.ToString("route(", strings.Join(descriptions, ","), ")")
}
@@ -157,6 +171,9 @@ type RuleActionRouteOptions struct {
UDPDisableDomainUnmapping bool
UDPConnect bool
UDPTimeout time.Duration
TLSFragment bool
TLSFragmentFallbackDelay time.Duration
TLSRecordFragment bool
}
func (r *RuleActionRouteOptions) Type() string {
@@ -164,6 +181,10 @@ func (r *RuleActionRouteOptions) Type() string {
}
func (r *RuleActionRouteOptions) String() string {
return F.ToString("route-options(", strings.Join(r.Descriptions(), ","), ")")
}
func (r *RuleActionRouteOptions) Descriptions() []string {
var descriptions []string
if r.OverrideAddress.IsValid() {
descriptions = append(descriptions, F.ToString("override-address=", r.OverrideAddress.AddrString()))
@@ -192,7 +213,19 @@ func (r *RuleActionRouteOptions) String() string {
if r.UDPConnect {
descriptions = append(descriptions, "udp-connect")
}
return F.ToString("route-options(", strings.Join(descriptions, ","), ")")
if r.UDPTimeout > 0 {
descriptions = append(descriptions, "udp-timeout")
}
if r.TLSFragment {
descriptions = append(descriptions, "tls-fragment")
}
if r.TLSFragmentFallbackDelay > 0 {
descriptions = append(descriptions, F.ToString("tls-fragment-fallback-delay=", r.TLSFragmentFallbackDelay.String()))
}
if r.TLSRecordFragment {
descriptions = append(descriptions, "tls-record-fragment")
}
return descriptions
}
type RuleActionDNSRoute struct {
@@ -220,6 +253,7 @@ func (r *RuleActionDNSRoute) String() string {
}
type RuleActionDNSRouteOptions struct {
Strategy C.DomainStrategy
DisableCache bool
RewriteTTL *uint32
ClientSubnet netip.Prefix
@@ -368,6 +402,8 @@ func (r *RuleActionSniff) build() error {
r.StreamSniffers = append(r.StreamSniffers, sniff.SSH)
case C.ProtocolRDP:
r.StreamSniffers = append(r.StreamSniffers, sniff.RDP)
case C.ProtocolNTP:
r.PacketSniffers = append(r.PacketSniffers, sniff.NTP)
default:
return E.New("unknown sniffer: ", name)
}
@@ -388,8 +424,11 @@ func (r *RuleActionSniff) String() string {
}
type RuleActionResolve struct {
Strategy dns.DomainStrategy
Server string
Server string
Strategy C.DomainStrategy
DisableCache bool
RewriteTTL *uint32
ClientSubnet netip.Prefix
}
func (r *RuleActionResolve) Type() string {
@@ -397,13 +436,74 @@ func (r *RuleActionResolve) Type() string {
}
func (r *RuleActionResolve) String() string {
if r.Strategy == dns.DomainStrategyAsIS && r.Server == "" {
return F.ToString("resolve")
} else if r.Strategy != dns.DomainStrategyAsIS && r.Server == "" {
return F.ToString("resolve(", option.DomainStrategy(r.Strategy).String(), ")")
} else if r.Strategy == dns.DomainStrategyAsIS && r.Server != "" {
return F.ToString("resolve(", r.Server, ")")
var options []string
if r.Server != "" {
options = append(options, r.Server)
}
if r.Strategy != C.DomainStrategyAsIS {
options = append(options, F.ToString(option.DomainStrategy(r.Strategy)))
}
if r.DisableCache {
options = append(options, "disable_cache")
}
if r.RewriteTTL != nil {
options = append(options, F.ToString("rewrite_ttl=", *r.RewriteTTL))
}
if r.ClientSubnet.IsValid() {
options = append(options, F.ToString("client_subnet=", r.ClientSubnet))
}
if len(options) == 0 {
return "resolve"
} else {
return F.ToString("resolve(", option.DomainStrategy(r.Strategy).String(), ",", r.Server, ")")
return F.ToString("resolve(", strings.Join(options, ","), ")")
}
}
type RuleActionPredefined struct {
Rcode int
Answer []dns.RR
Ns []dns.RR
Extra []dns.RR
}
func (r *RuleActionPredefined) Type() string {
return C.RuleActionTypePredefined
}
func (r *RuleActionPredefined) String() string {
var options []string
options = append(options, dns.RcodeToString[r.Rcode])
options = append(options, common.Map(r.Answer, dns.RR.String)...)
options = append(options, common.Map(r.Ns, dns.RR.String)...)
options = append(options, common.Map(r.Extra, dns.RR.String)...)
return F.ToString("predefined(", strings.Join(options, ","), ")")
}
func (r *RuleActionPredefined) Response(request *dns.Msg) *dns.Msg {
return &dns.Msg{
MsgHdr: dns.MsgHdr{
Id: request.Id,
Response: true,
Authoritative: true,
RecursionDesired: true,
RecursionAvailable: true,
Rcode: r.Rcode,
},
Question: request.Question,
Answer: rewriteRecords(r.Answer, request.Question[0]),
Ns: rewriteRecords(r.Ns, request.Question[0]),
Extra: rewriteRecords(r.Extra, request.Question[0]),
}
}
func rewriteRecords(records []dns.RR, question dns.Question) []dns.RR {
return common.Map(records, func(it dns.RR) dns.RR {
if strings.HasPrefix(it.Header().Name, "*") {
if strings.HasSuffix(question.Name, it.Header().Name[1:]) {
it = dns.Copy(it)
it.Header().Name = question.Name
}
}
return it
})
}