diff --git a/README.md b/README.md index 7e834d34..3b753a6d 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,10 @@ external-controller: 127.0.0.1:9090 # Secret for RESTful API (Optional) # secret: "" +# experimental feature +experimental: + ignore-resolve-fail: true # ignore dns reslove fail, default value is true + # dns: # enable: true # set true to enable dns (default is false) # ipv6: false # default is false diff --git a/config/config.go b/config/config.go index 190478a1..ec82f788 100644 --- a/config/config.go +++ b/config/config.go @@ -43,12 +43,18 @@ type DNS struct { EnhancedMode dns.EnhancedMode `yaml:"enhanced-mode"` } +// Experimental config +type Experimental struct { + IgnoreResolveFail bool `yaml:"ignore-resolve-fail"` +} + // Config is clash config manager type Config struct { - General *General - DNS *DNS - Rules []C.Rule - Proxies map[string]C.Proxy + General *General + DNS *DNS + Experimental *Experimental + Rules []C.Rule + Proxies map[string]C.Proxy } type rawDNS struct { @@ -71,10 +77,11 @@ type rawConfig struct { ExternalUI string `yaml:"external-ui"` Secret string `yaml:"secret"` - DNS rawDNS `yaml:"dns"` - Proxy []map[string]interface{} `yaml:"Proxy"` - ProxyGroup []map[string]interface{} `yaml:"Proxy Group"` - Rule []string `yaml:"Rule"` + DNS rawDNS `yaml:"dns"` + Experimental Experimental `yaml:"experimental"` + Proxy []map[string]interface{} `yaml:"Proxy"` + ProxyGroup []map[string]interface{} `yaml:"Proxy Group"` + Rule []string `yaml:"Rule"` } func readConfig(path string) (*rawConfig, error) { @@ -98,6 +105,9 @@ func readConfig(path string) (*rawConfig, error) { Rule: []string{}, Proxy: []map[string]interface{}{}, ProxyGroup: []map[string]interface{}{}, + Experimental: Experimental{ + IgnoreResolveFail: true, + }, DNS: rawDNS{ Enable: false, }, @@ -114,6 +124,7 @@ func Parse(path string) (*Config, error) { if err != nil { return nil, err } + config.Experimental = &rawCfg.Experimental general, err := parseGeneral(rawCfg) if err != nil { diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 936bf4c6..6bb370c9 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -27,6 +27,7 @@ func ApplyConfig(cfg *config.Config, force bool) { updateProxies(cfg.Proxies) updateRules(cfg.Rules) updateDNS(cfg.DNS) + updateExperimental(cfg.Experimental) } func GetGeneral() *config.General { @@ -41,6 +42,10 @@ func GetGeneral() *config.General { } } +func updateExperimental(c *config.Experimental) { + T.Instance().UpdateExperimental(c.IgnoreResolveFail) +} + func updateDNS(c *config.DNS) { if c.Enable == false { T.Instance().SetResolver(nil) diff --git a/proxy/socks/udp.go b/proxy/socks/udp.go deleted file mode 100644 index a266580e..00000000 --- a/proxy/socks/udp.go +++ /dev/null @@ -1 +0,0 @@ -package socks diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 7af3daf3..ec5e2b2c 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -21,12 +21,15 @@ var ( // Tunnel handle relay inbound proxy and outbound proxy type Tunnel struct { - queue *channels.InfiniteChannel - rules []C.Rule - proxies map[string]C.Proxy - configLock *sync.RWMutex - traffic *C.Traffic - resolver *dns.Resolver + queue *channels.InfiniteChannel + rules []C.Rule + proxies map[string]C.Proxy + configMux *sync.RWMutex + traffic *C.Traffic + resolver *dns.Resolver + + // experimental features + ignoreResolveFail bool // Outbound Rule mode Mode @@ -49,9 +52,9 @@ func (t *Tunnel) Rules() []C.Rule { // UpdateRules handle update rules func (t *Tunnel) UpdateRules(rules []C.Rule) { - t.configLock.Lock() + t.configMux.Lock() t.rules = rules - t.configLock.Unlock() + t.configMux.Unlock() } // Proxies return all proxies @@ -61,9 +64,16 @@ func (t *Tunnel) Proxies() map[string]C.Proxy { // UpdateProxies handle update proxies func (t *Tunnel) UpdateProxies(proxies map[string]C.Proxy) { - t.configLock.Lock() + t.configMux.Lock() t.proxies = proxies - t.configLock.Unlock() + t.configMux.Unlock() +} + +// UpdateExperimental handle update experimental config +func (t *Tunnel) UpdateExperimental(ignoreResolveFail bool) { + t.configMux.Lock() + t.ignoreResolveFail = ignoreResolveFail + t.configMux.Unlock() } // Mode return current mode @@ -174,17 +184,23 @@ func (t *Tunnel) shouldResolveIP(rule C.Rule, metadata *C.Metadata) bool { } func (t *Tunnel) match(metadata *C.Metadata) (C.Proxy, error) { - t.configLock.RLock() - defer t.configLock.RUnlock() + t.configMux.RLock() + defer t.configMux.RUnlock() + var resolved bool for _, rule := range t.rules { - if t.shouldResolveIP(rule, metadata) { + if !resolved && t.shouldResolveIP(rule, metadata) { ip, err := t.resolveIP(metadata.Host) if err != nil { - return nil, fmt.Errorf("[DNS] resolve %s error: %s", metadata.Host, err.Error()) + if !t.ignoreResolveFail { + return nil, fmt.Errorf("[DNS] resolve %s error: %s", metadata.Host, err.Error()) + } + log.Debugln("[DNS] resolve %s error: %s", metadata.Host, err.Error()) + } else { + log.Debugln("[DNS] %s --> %s", metadata.Host, ip.String()) + metadata.IP = &ip } - log.Debugln("[DNS] %s --> %s", metadata.Host, ip.String()) - metadata.IP = &ip + resolved = true } if rule.IsMatch(metadata) { @@ -207,11 +223,11 @@ func (t *Tunnel) match(metadata *C.Metadata) (C.Proxy, error) { func newTunnel() *Tunnel { return &Tunnel{ - queue: channels.NewInfiniteChannel(), - proxies: make(map[string]C.Proxy), - configLock: &sync.RWMutex{}, - traffic: C.NewTraffic(time.Second), - mode: Rule, + queue: channels.NewInfiniteChannel(), + proxies: make(map[string]C.Proxy), + configMux: &sync.RWMutex{}, + traffic: C.NewTraffic(time.Second), + mode: Rule, } }