From b03348d136d091261041fe3c2b50ed1918408d13 Mon Sep 17 00:00:00 2001 From: KagurazakaNyaa Date: Sat, 7 Sep 2024 10:07:18 +0800 Subject: [PATCH] feat: allow group override global node connectivity check --- component/outbound/dialer/dialer.go | 4 +++ config/config.go | 6 ++++ config/desc.go | 5 +++ control/control_plane.go | 52 +++++++++++++++++++++++++++++ example.dae | 7 ++++ 5 files changed, 74 insertions(+) diff --git a/component/outbound/dialer/dialer.go b/component/outbound/dialer/dialer.go index 5d08706084..bec9a4ea2f 100644 --- a/component/outbound/dialer/dialer.go +++ b/component/outbound/dialer/dialer.go @@ -83,6 +83,10 @@ func NewDialer(dialer netproxy.Dialer, option *GlobalOption, iOption InstanceOpt return d } +func (d *Dialer) Clone() *Dialer { + return NewDialer(d.Dialer, d.GlobalOption, d.InstanceOption, d.property) +} + func (d *Dialer) Close() error { d.cancel() d.tickerMu.Lock() diff --git a/config/config.go b/config/config.go index 873278d701..85c2434bc8 100644 --- a/config/config.go +++ b/config/config.go @@ -89,6 +89,12 @@ type Group struct { Filter [][]*config_parser.Function `mapstructure:"filter" repeatable:""` FilterAnnotation [][]*config_parser.Param `mapstructure:"_"` Policy FunctionListOrString `mapstructure:"policy" required:""` + + TcpCheckUrl []string `mapstructure:"tcp_check_url"` + TcpCheckHttpMethod string `mapstructure:"tcp_check_http_method"` + UdpCheckDns []string `mapstructure:"udp_check_dns"` + CheckInterval time.Duration `mapstructure:"check_interval"` + CheckTolerance time.Duration `mapstructure:"check_tolerance"` } type DnsRequestRouting struct { diff --git a/config/desc.go b/config/desc.go index 2440527cbc..121bf6cbac 100644 --- a/config/desc.go +++ b/config/desc.go @@ -85,4 +85,9 @@ min: Select node by the latency of last check. min_avg10: Select node by the average of latencies of last 10 checks. min_moving_avg: Select node by the moving average of latencies of checks, which means more recent latencies have higher weight. `, + "tcp_check_url": "Override global config.", + "tcp_check_http_method": "Override global config.", + "udp_check_dns": "Override global config.", + "check_interval": "Override global config.", + "check_tolerance": "Override global config.", } diff --git a/control/control_plane.go b/control/control_plane.go index 5cc190853c..57b3120576 100644 --- a/control/control_plane.go +++ b/control/control_plane.go @@ -323,6 +323,17 @@ func NewControlPlane( if len(dialers) == 0 { log.Infoln("\t") } + groupOption, err := ParseGroupOverrideOption(group, *global, log) + if err == nil && groupOption != nil { + newDialerSet := make([]*dialer.Dialer, 0) + for _, d := range dialers { + newDialer := d.Clone() + newDialer.GlobalOption = groupOption + newDialerSet = append(newDialerSet, newDialer) + } + log.Infof(`Group "%v"'s check option has been override.`, group.Name) + dialers = newDialerSet + } // Create dialer group and append it to outbounds. dialerGroup := outbound.NewDialerGroup(option, group.Name, dialers, annos, *policy, core.outboundAliveChangeCallback(uint8(len(outbounds)), disableKernelAliveCallback)) @@ -515,6 +526,47 @@ func ParseFixedDomainTtl(ks []config.KeyableString) (map[string]int, error) { return m, nil } +func ParseGroupOverrideOption(group config.Group, global config.Global, log *logrus.Logger) (*dialer.GlobalOption, error) { + result := global + changed := false + if group.TcpCheckUrl != nil { + result.TcpCheckUrl = group.TcpCheckUrl + changed = true + } + if group.TcpCheckHttpMethod == "" { + result.TcpCheckHttpMethod = group.TcpCheckHttpMethod + changed = true + } + if group.UdpCheckDns != nil { + result.UdpCheckDns = group.UdpCheckDns + changed = true + } + if group.CheckInterval != 0 { + result.CheckInterval = group.CheckInterval + changed = true + } + if group.CheckTolerance != 0 { + result.CheckTolerance = group.CheckTolerance + changed = true + } + if changed { + option := dialer.GlobalOption{ + ExtraOption: D.ExtraOption{ + AllowInsecure: global.AllowInsecure, + TlsImplementation: global.TlsImplementation, + UtlsImitate: global.UtlsImitate}, + Log: log, + TcpCheckOptionRaw: dialer.TcpCheckOptionRaw{Raw: result.TcpCheckUrl, Log: log, ResolverNetwork: common.MagicNetwork("udp", global.SoMarkFromDae, global.Mptcp), Method: result.TcpCheckHttpMethod}, + CheckDnsOptionRaw: dialer.CheckDnsOptionRaw{Raw: result.UdpCheckDns, ResolverNetwork: common.MagicNetwork("udp", global.SoMarkFromDae, global.Mptcp), Somark: global.SoMarkFromDae}, + CheckInterval: result.CheckInterval, + CheckTolerance: result.CheckTolerance, + CheckDnsTcp: true, + } + return &option, nil + } + return nil, nil +} + // EjectBpf will resect bpf from destroying life-cycle of control plane. func (c *ControlPlane) EjectBpf() *bpfObjects { return c.core.EjectBpf() diff --git a/example.dae b/example.dae index e1814e2b86..29d95e2d95 100644 --- a/example.dae +++ b/example.dae @@ -40,6 +40,7 @@ global { auto_config_kernel_parameter: true ##### Node connectivity check. + # These options, as defaults, are effective when no definition is given in the group. # Host of URL should have both IPv4 and IPv6 if you have double stack in local. # First is URL, others are IP addresses if given. @@ -212,6 +213,12 @@ group { # Select the node with min average of the last 10 latencies from the group for every connection. policy: min_avg10 + + # Override tcp_check_url in global. + tcp_check_url: https://gstatic.com/generate_204 + + # This not override global tcp_check_http_method so it still will be "HEAD" + #tcp_check_http_method: GET } }