mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-04 15:27:55 +07:00
optimize: url check and log
This commit is contained in:
@ -64,6 +64,7 @@ func Run() (err error) {
|
||||
¶m.Routing,
|
||||
param.Global.DnsUpstream,
|
||||
param.Global.CheckUrl,
|
||||
param.Global.CheckInterval,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ControlPlane struct {
|
||||
@ -58,6 +59,7 @@ func NewControlPlane(
|
||||
routingA *config.Routing,
|
||||
dnsUpstream string,
|
||||
checkUrl string,
|
||||
checkInterval time.Duration,
|
||||
) (c *ControlPlane, err error) {
|
||||
// Allow the current process to lock memory for eBPF resources.
|
||||
if err = rlimit.RemoveMemlock(); err != nil {
|
||||
@ -110,10 +112,12 @@ retryLoadBpf:
|
||||
if err = bpf.IpprotoHdrsizeMap.Update(uint32(unix.IPPROTO_UDP), int32(0), ebpf.UpdateAny); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// DialerGroups (outbounds).
|
||||
option := &dialer.GlobalOption{
|
||||
Log: log,
|
||||
CheckUrl: checkUrl,
|
||||
CheckInterval: checkInterval,
|
||||
}
|
||||
outbounds := []*outbound.DialerGroup{
|
||||
outbound.NewDialerGroup(option, consts.OutboundDirect.String(),
|
||||
@ -133,14 +137,26 @@ retryLoadBpf:
|
||||
// Filter out groups.
|
||||
dialerSet := outbound.NewDialerSetFromLinks(option, nodes)
|
||||
for _, group := range groups {
|
||||
dialers, err := dialerSet.Filter(group.Param.Filter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`failed to create group "%v": %w`, group.Name, err)
|
||||
}
|
||||
// Parse policy.
|
||||
policy, err := outbound.NewDialerSelectionPolicyFromGroupParam(&group.Param)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create group %v: %w", group.Name, err)
|
||||
}
|
||||
// Filter nodes.
|
||||
dialers, err := dialerSet.Filter(group.Param.Filter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`failed to create group "%v": %w`, group.Name, err)
|
||||
}
|
||||
// Convert node links to dialers.
|
||||
log.Infof(`Group "%v" node list:`, group.Name)
|
||||
for _, d := range dialers {
|
||||
log.Infoln("\t" + d.Name())
|
||||
d.ActiveCheck()
|
||||
}
|
||||
if len(dialers) == 0 {
|
||||
log.Infoln("\t<Empty>")
|
||||
}
|
||||
// Create dialer group and append it to outbounds.
|
||||
dialerGroup := outbound.NewDialerGroup(option, group.Name, dialers, *policy)
|
||||
outbounds = append(outbounds, dialerGroup)
|
||||
}
|
||||
|
@ -6,9 +6,9 @@
|
||||
package dialer
|
||||
|
||||
import (
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
"github.com/mzz2017/softwind/pkg/fastrand"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/common/consts"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@ -23,6 +23,7 @@ type minLatency struct {
|
||||
// It is thread-safe.
|
||||
type AliveDialerSet struct {
|
||||
log *logrus.Logger
|
||||
dialerGroupName string
|
||||
|
||||
mu sync.Mutex
|
||||
dialerToIndex map[*Dialer]int // *Dialer -> index of inorderedAliveDialerSet
|
||||
@ -35,12 +36,14 @@ type AliveDialerSet struct {
|
||||
|
||||
func NewAliveDialerSet(
|
||||
log *logrus.Logger,
|
||||
dialerGroupName string,
|
||||
selectionPolicy consts.DialerSelectionPolicy,
|
||||
dialers []*Dialer,
|
||||
setAlive bool,
|
||||
) *AliveDialerSet {
|
||||
a := &AliveDialerSet{
|
||||
log: log,
|
||||
dialerGroupName: dialerGroupName,
|
||||
dialerToIndex: make(map[*Dialer]int),
|
||||
dialerToLatency: make(map[*Dialer]time.Duration),
|
||||
inorderedAliveDialerSet: make([]*Dialer, 0, len(dialers)),
|
||||
@ -50,10 +53,6 @@ func NewAliveDialerSet(
|
||||
latency: time.Hour,
|
||||
},
|
||||
}
|
||||
if setAlive && len(dialers) > 0 {
|
||||
// Use first dialer if no dialer has alive state.
|
||||
a.minLatency.dialer = dialers[0]
|
||||
}
|
||||
for _, d := range dialers {
|
||||
a.dialerToIndex[d] = -1
|
||||
}
|
||||
@ -129,8 +128,9 @@ func (a *AliveDialerSet) SetAlive(dialer *Dialer, alive bool) {
|
||||
// This dialer is already not alive.
|
||||
}
|
||||
}
|
||||
|
||||
oldBestDialer := a.minLatency.dialer
|
||||
if hasLatency {
|
||||
// Calc minLatency.
|
||||
a.dialerToLatency[dialer] = latency
|
||||
if latency < a.minLatency.latency {
|
||||
a.minLatency.latency = latency
|
||||
@ -140,6 +140,15 @@ func (a *AliveDialerSet) SetAlive(dialer *Dialer, alive bool) {
|
||||
a.minLatency.dialer = nil
|
||||
a.calcMinLatency()
|
||||
}
|
||||
if a.minLatency.dialer != oldBestDialer {
|
||||
a.log.Infof("Group [%v] switched dialer to <%v> (%v): %v", a.dialerGroupName, a.minLatency.dialer.Name(), a.selectionPolicy, a.minLatency.latency)
|
||||
}
|
||||
} else {
|
||||
if alive && a.minLatency.dialer == nil {
|
||||
// Use first dialer if no dialer has alive state.
|
||||
a.minLatency.dialer = dialer
|
||||
a.log.Infof("Group [%v] switched dialer to <%v>", a.dialerGroupName, a.minLatency.dialer.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,5 +16,5 @@ func (*blockDialer) Dial(network string, addr string) (c net.Conn, err error) {
|
||||
}
|
||||
|
||||
func NewBlockDialer(option *GlobalOption) *Dialer {
|
||||
return newDialer(&blockDialer{}, option, true, "block", "block", "")
|
||||
return NewDialer(&blockDialer{}, option, InstanceOption{Check: false}, true, "block", "block", "")
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ var (
|
||||
|
||||
type Dialer struct {
|
||||
*GlobalOption
|
||||
instanceOption InstanceOption
|
||||
proxy.Dialer
|
||||
supportUDP bool
|
||||
name string
|
||||
@ -42,20 +43,19 @@ type Dialer struct {
|
||||
type GlobalOption struct {
|
||||
Log *logrus.Logger
|
||||
CheckUrl string
|
||||
CheckInterval time.Duration
|
||||
}
|
||||
|
||||
type InstanceOption struct {
|
||||
Check bool
|
||||
}
|
||||
|
||||
// NewDialer is for register in general.
|
||||
func NewDialer(dialer proxy.Dialer, option *GlobalOption, supportUDP bool, name string, protocol string, link string) *Dialer {
|
||||
d := newDialer(dialer, option, supportUDP, name, protocol, link)
|
||||
go d.aliveBackground()
|
||||
return d
|
||||
}
|
||||
|
||||
// newDialer does not run background tasks.
|
||||
func newDialer(dialer proxy.Dialer, option *GlobalOption, supportUDP bool, name string, protocol string, link string) *Dialer {
|
||||
func NewDialer(dialer proxy.Dialer, option *GlobalOption, iOption InstanceOption, supportUDP bool, name string, protocol string, link string) *Dialer {
|
||||
d := &Dialer{
|
||||
Dialer: dialer,
|
||||
GlobalOption: option,
|
||||
instanceOption: iOption,
|
||||
supportUDP: supportUDP,
|
||||
name: name,
|
||||
protocol: protocol,
|
||||
@ -65,12 +65,24 @@ func newDialer(dialer proxy.Dialer, option *GlobalOption, supportUDP bool, name
|
||||
ticker: time.NewTicker(time.Hour),
|
||||
aliveDialerSetSet: make(map[*AliveDialerSet]int),
|
||||
}
|
||||
if iOption.Check {
|
||||
go d.aliveBackground()
|
||||
}
|
||||
return d
|
||||
}
|
||||
func (d *Dialer) ActiveCheck() {
|
||||
d.tickerMu.Lock()
|
||||
defer d.tickerMu.Unlock()
|
||||
if d.instanceOption.Check {
|
||||
return
|
||||
}
|
||||
d.instanceOption.Check = true
|
||||
go d.aliveBackground()
|
||||
}
|
||||
|
||||
func (d *Dialer) aliveBackground() {
|
||||
timeout := 10 * time.Second
|
||||
cycle := 15 * time.Second
|
||||
cycle := d.CheckInterval
|
||||
// Check once immediately.
|
||||
go d.Check(timeout, d.CheckUrl)
|
||||
|
||||
@ -137,13 +149,14 @@ func (d *Dialer) Check(timeout time.Duration, url string) (ok bool, err error) {
|
||||
if ok && err == nil {
|
||||
// No error.
|
||||
latency := time.Since(start)
|
||||
d.Log.Debugf("Connectivity Check [%v]: %v", d.name, latency)
|
||||
d.Latencies10.AppendLatency(latency)
|
||||
avg, _ := d.Latencies10.AvgLatency()
|
||||
d.Log.Debugf("Connectivity Check <%v>: last: %v, avg_10: %v", d.name, latency, avg)
|
||||
alive = true
|
||||
} else {
|
||||
// Append timeout if there is any error or unexpected status code.
|
||||
if err != nil {
|
||||
d.Log.Debugf("Connectivity Check [%v]: %v", d.name, err.Error())
|
||||
d.Log.Debugf("Connectivity Check <%v>: %v", d.name, err.Error())
|
||||
}
|
||||
d.Latencies10.AppendLatency(timeout)
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ var FullconeDirect = newDirect(true)
|
||||
|
||||
func NewDirectDialer(option *GlobalOption, fullcone bool) *Dialer {
|
||||
if fullcone {
|
||||
return newDialer(FullconeDirect, option, true, "direct", "direct", "")
|
||||
return NewDialer(FullconeDirect, option, InstanceOption{Check: false}, true, "direct", "direct", "")
|
||||
} else {
|
||||
return newDialer(SymmetricDirect, option, true, "direct", "direct", "")
|
||||
return NewDialer(SymmetricDirect, option, InstanceOption{Check: false}, true, "direct", "direct", "")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,12 @@ type HTTP struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewHTTP(option *dialer.GlobalOption, link string) (*dialer.Dialer, error) {
|
||||
func NewHTTP(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseHTTPURL(link)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", dialer.InvalidParameterErr, err)
|
||||
}
|
||||
return s.Dialer(option)
|
||||
return s.Dialer(option, iOption)
|
||||
}
|
||||
|
||||
func ParseHTTPURL(link string) (data *HTTP, err error) {
|
||||
@ -61,13 +61,13 @@ func ParseHTTPURL(link string) (data *HTTP, err error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *HTTP) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, error) {
|
||||
func (s *HTTP) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
u := s.URL()
|
||||
d, err := http.NewHTTPProxy(&u, dialer.SymmetricDirect) // HTTP Proxy does not support full-cone.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, false, s.Name, s.Protocol, u.String()), nil
|
||||
return dialer.NewDialer(d, option, iOption, false, s.Name, s.Protocol, u.String()), nil
|
||||
}
|
||||
|
||||
func (s *HTTP) URL() url.URL {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type FromLinkCreator func(option *GlobalOption, link string) (dialer *Dialer, err error)
|
||||
type FromLinkCreator func(gOption *GlobalOption, iOption InstanceOption, link string) (dialer *Dialer, err error)
|
||||
|
||||
var fromLinkCreators = make(map[string]FromLinkCreator)
|
||||
|
||||
@ -18,13 +18,13 @@ func FromLinkRegister(name string, creator FromLinkCreator) {
|
||||
fromLinkCreators[name] = creator
|
||||
}
|
||||
|
||||
func NewFromLink(option *GlobalOption, link string) (dialer *Dialer, err error) {
|
||||
func NewFromLink(gOption *GlobalOption, iOption InstanceOption, link string) (dialer *Dialer, err error) {
|
||||
u, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if creator, ok := fromLinkCreators[u.Scheme]; ok {
|
||||
return creator(option, link)
|
||||
return creator(gOption, iOption, link)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unexpected link type: %v", u.Scheme)
|
||||
}
|
||||
|
@ -33,15 +33,15 @@ type Shadowsocks struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewShadowsocksFromLink(option *dialer.GlobalOption, link string) (*dialer.Dialer, error) {
|
||||
func NewShadowsocksFromLink(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseSSURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer(option)
|
||||
return s.Dialer(option, iOption)
|
||||
}
|
||||
|
||||
func (s *Shadowsocks) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, error) {
|
||||
func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
// FIXME: support plain/none.
|
||||
switch s.Cipher {
|
||||
case "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305":
|
||||
@ -76,7 +76,7 @@ func (s *Shadowsocks) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, error
|
||||
}
|
||||
supportUDP = false
|
||||
}
|
||||
return dialer.NewDialer(d, option, supportUDP, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
return dialer.NewDialer(d, option, iOption, supportUDP, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseSSURL(u string) (data *Shadowsocks, err error) {
|
||||
|
@ -30,15 +30,15 @@ type ShadowsocksR struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewShadowsocksR(option *dialer.GlobalOption, link string) (*dialer.Dialer, error) {
|
||||
func NewShadowsocksR(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseSSRURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer(option)
|
||||
return s.Dialer(option, iOption)
|
||||
}
|
||||
|
||||
func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, error) {
|
||||
func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
u := url.URL{
|
||||
Scheme: "ssr",
|
||||
User: url.UserPassword(s.Cipher, s.Password),
|
||||
@ -54,7 +54,7 @@ func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, false, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
return dialer.NewDialer(d, option, iOption, false, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseSSRURL(u string) (data *ShadowsocksR, err error) {
|
||||
|
@ -26,15 +26,15 @@ type Socks struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewSocks(option *dialer.GlobalOption, link string) (*dialer.Dialer, error) {
|
||||
func NewSocks(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseSocksURL(link)
|
||||
if err != nil {
|
||||
return nil, dialer.InvalidParameterErr
|
||||
}
|
||||
return s.Dialer(option)
|
||||
return s.Dialer(option, iOption)
|
||||
}
|
||||
|
||||
func (s *Socks) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, error) {
|
||||
func (s *Socks) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
link := s.ExportToURL()
|
||||
switch s.Protocol {
|
||||
case "", "socks", "socks5":
|
||||
@ -42,7 +42,7 @@ func (s *Socks) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, true, s.Name, s.Protocol, link), nil
|
||||
return dialer.NewDialer(d, option, iOption, true, s.Name, s.Protocol, link), nil
|
||||
//case "socks4", "socks4a":
|
||||
// d, err := socks4.NewSocks4Dialer(link, &proxy.Direct{})
|
||||
// if err != nil {
|
||||
|
@ -34,15 +34,15 @@ type Trojan struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewTrojan(option *dialer.GlobalOption, link string) (*dialer.Dialer, error) {
|
||||
func NewTrojan(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
s, err := ParseTrojanURL(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Dialer(option)
|
||||
return s.Dialer(option, iOption)
|
||||
}
|
||||
|
||||
func (s *Trojan) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, error) {
|
||||
func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
|
||||
d := dialer.FullconeDirect // Trojan Proxy supports full-cone.
|
||||
u := url.URL{
|
||||
Scheme: "tls",
|
||||
@ -101,7 +101,7 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption) (*dialer.Dialer, error) {
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, true, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
return dialer.NewDialer(d, option, iOption, true, s.Name, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseTrojanURL(u string) (data *Trojan, err error) {
|
||||
|
@ -41,7 +41,7 @@ type V2Ray struct {
|
||||
Protocol string `json:"protocol"`
|
||||
}
|
||||
|
||||
func NewV2Ray(option *dialer.GlobalOption, link string) (*dialer.Dialer, error) {
|
||||
func NewV2Ray(option *dialer.GlobalOption, iOption dialer.InstanceOption, link string) (*dialer.Dialer, error) {
|
||||
var (
|
||||
s *V2Ray
|
||||
err error
|
||||
@ -63,10 +63,10 @@ func NewV2Ray(option *dialer.GlobalOption, link string) (*dialer.Dialer, error)
|
||||
default:
|
||||
return nil, dialer.InvalidParameterErr
|
||||
}
|
||||
return s.Dialer(option)
|
||||
return s.Dialer(option, iOption)
|
||||
}
|
||||
|
||||
func (s *V2Ray) Dialer(option *dialer.GlobalOption) (data *dialer.Dialer, err error) {
|
||||
func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (data *dialer.Dialer, err error) {
|
||||
var d proxy.Dialer
|
||||
switch s.Protocol {
|
||||
case "vmess":
|
||||
@ -147,7 +147,7 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption) (data *dialer.Dialer, err er
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dialer.NewDialer(d, option, true, s.Ps, s.Protocol, s.ExportToURL()), nil
|
||||
return dialer.NewDialer(d, option, iOption, true, s.Ps, s.Protocol, s.ExportToURL()), nil
|
||||
}
|
||||
|
||||
func ParseVlessURL(vless string) (data *V2Ray, err error) {
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
"github.com/v2rayA/dae/config"
|
||||
"github.com/v2rayA/dae/pkg/config_parser"
|
||||
"golang.org/x/net/proxy"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
@ -84,8 +83,9 @@ type DialerGroup struct {
|
||||
}
|
||||
|
||||
func NewDialerGroup(option *dialer.GlobalOption, name string, dialers []*dialer.Dialer, p DialerSelectionPolicy) *DialerGroup {
|
||||
log := option.Log
|
||||
var registeredAliveDialerSet bool
|
||||
a := dialer.NewAliveDialerSet(option.Log, p.Policy, dialers, true)
|
||||
a := dialer.NewAliveDialerSet(log, name, p.Policy, dialers, true)
|
||||
|
||||
switch p.Policy {
|
||||
case consts.DialerSelectionPolicy_Random,
|
||||
@ -105,7 +105,7 @@ func NewDialerGroup(option *dialer.GlobalOption, name string, dialers []*dialer.
|
||||
}
|
||||
|
||||
return &DialerGroup{
|
||||
log: option.Log,
|
||||
log: log,
|
||||
Name: name,
|
||||
Dialers: dialers,
|
||||
block: dialer.NewBlockDialer(option),
|
||||
@ -170,6 +170,6 @@ func (g *DialerGroup) Dial(network string, addr string) (c net.Conn, err error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.log.Tracef("Group [%v] dial using [%v]", g.Name, d.Name())
|
||||
g.log.Tracef("Group [%v] dial using <%v>", g.Name, d.Name())
|
||||
return d.Dial(network, addr)
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ package outbound
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/pkg/config_parser"
|
||||
"regexp"
|
||||
@ -31,7 +30,7 @@ type DialerSet struct {
|
||||
func NewDialerSetFromLinks(option *dialer.GlobalOption, nodes []string) *DialerSet {
|
||||
s := &DialerSet{Dialers: make([]*dialer.Dialer, 0, len(nodes))}
|
||||
for _, node := range nodes {
|
||||
d, err := dialer.NewFromLink(option, node)
|
||||
d, err := dialer.NewFromLink(option, dialer.InstanceOption{Check: false}, node)
|
||||
if err != nil {
|
||||
option.Log.Infof("failed to parse node: %v: %v", node, err)
|
||||
continue
|
||||
@ -56,7 +55,7 @@ func hit(dialer *dialer.Dialer, filters []*config_parser.Function) (hit bool, er
|
||||
switch param.Key {
|
||||
case FilterKey_Name_Regex:
|
||||
matched, _ := regexp.MatchString(param.Val, dialer.Name())
|
||||
logrus.Warnln(param.Val, matched, dialer.Name())
|
||||
//logrus.Warnln(param.Val, matched, dialer.Name())
|
||||
if matched {
|
||||
subFilterHit = true
|
||||
break
|
||||
|
16
example.conf
16
example.conf
@ -4,7 +4,7 @@ global {
|
||||
|
||||
# Node connectivity check.
|
||||
check_url: 'https://connectivitycheck.gstatic.com/generate_204'
|
||||
check_interval: 15s
|
||||
check_interval: 30s
|
||||
|
||||
# Now only support UDP and IP:Port.
|
||||
# Please make sure DNS traffic will go through and be forwarded by dae.
|
||||
@ -38,7 +38,7 @@ group {
|
||||
|
||||
disney {
|
||||
# Pass node names as input of keyword/regex filter.
|
||||
filter: name(regex:'HK|SG', keyword:'JP') && name(keyword:'disney')
|
||||
filter: name(regex:'HK|SG|TW', keyword:'JP') && name(keyword:'GCP')
|
||||
|
||||
# Select the node with min average of the last 10 latencies from the group for every connection.
|
||||
policy: min_avg10
|
||||
@ -46,24 +46,16 @@ group {
|
||||
|
||||
netflix {
|
||||
# Pass node names as input of keyword filter.
|
||||
filter: name(keyword:netflix)
|
||||
filter: name(keyword:AWS)
|
||||
|
||||
# Select the first node from the group for every connection.
|
||||
policy: min
|
||||
}
|
||||
|
||||
BT {
|
||||
# Pass node names as input of keyword filter.
|
||||
filter: name(regex:'.*')
|
||||
|
||||
# Select the first node from the group for every connection.
|
||||
policy: random
|
||||
}
|
||||
}
|
||||
|
||||
routing {
|
||||
domain(geosite:category-ads) -> block
|
||||
l4proto(udp) && mac('02:42:ac:11:00:02') -> BT
|
||||
l4proto(udp) && mac('02:42:ac:11:00:03') -> BT
|
||||
domain(geosite:category-ads) -> block
|
||||
domain(geosite:disney) -> disney
|
||||
domain(geosite:netflix) -> netflix
|
||||
|
Reference in New Issue
Block a user