Skip to content

Commit

Permalink
Feature: add experimental config for resolving ip fail behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
Dreamacro committed Apr 24, 2019
1 parent 90e3dcc commit cec2206
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 30 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 19 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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) {
Expand All @@ -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,
},
Expand All @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions hub/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
Expand Down
1 change: 0 additions & 1 deletion proxy/socks/udp.go

This file was deleted.

58 changes: 37 additions & 21 deletions tunnel/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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,
}
}

Expand Down

0 comments on commit cec2206

Please sign in to comment.