Feature: resolve ip with a proxy adapter

This commit is contained in:
yaling888
2022-02-23 02:38:50 +08:00
parent b192238699
commit d876d6e74c
14 changed files with 357 additions and 101 deletions

View File

@ -15,6 +15,8 @@ import (
"github.com/Dreamacro/clash/adapter/provider"
"github.com/Dreamacro/clash/component/auth"
"github.com/Dreamacro/clash/component/fakeip"
"github.com/Dreamacro/clash/component/geodata"
"github.com/Dreamacro/clash/component/geodata/router"
"github.com/Dreamacro/clash/component/trie"
C "github.com/Dreamacro/clash/constant"
providerTypes "github.com/Dreamacro/clash/constant/provider"
@ -74,10 +76,11 @@ type DNS struct {
// FallbackFilter config
type FallbackFilter struct {
GeoIP bool `yaml:"geoip"`
GeoIPCode string `yaml:"geoip-code"`
IPCIDR []*net.IPNet `yaml:"ipcidr"`
Domain []string `yaml:"domain"`
GeoIP bool `yaml:"geoip"`
GeoIPCode string `yaml:"geoip-code"`
IPCIDR []*net.IPNet `yaml:"ipcidr"`
Domain []string `yaml:"domain"`
GeoSite []*router.DomainMatcher `yaml:"geosite"`
}
// Profile config
@ -131,6 +134,7 @@ type RawFallbackFilter struct {
GeoIPCode string `yaml:"geoip-code"`
IPCIDR []string `yaml:"ipcidr"`
Domain []string `yaml:"domain"`
GeoSite []string `yaml:"geosite"`
}
type RawConfig struct {
@ -198,6 +202,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
GeoIP: true,
GeoIPCode: "CN",
IPCIDR: []string{},
GeoSite: []string{},
},
DefaultNameserver: []string{
"114.114.114.114",
@ -247,7 +252,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
}
config.Hosts = hosts
dnsCfg, err := parseDNS(rawCfg, hosts)
dnsCfg, err := parseDNS(rawCfg, hosts, rules)
if err != nil {
return nil, err
}
@ -533,8 +538,9 @@ func parseNameServer(servers []string) ([]dns.NameServer, error) {
nameservers = append(
nameservers,
dns.NameServer{
Net: dnsNetType,
Addr: addr,
Net: dnsNetType,
Addr: addr,
ProxyAdapter: u.Fragment,
},
)
}
@ -572,7 +578,37 @@ func parseFallbackIPCIDR(ips []string) ([]*net.IPNet, error) {
return ipNets, nil
}
func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie) (*DNS, error) {
func parseFallbackGeoSite(countries []string, rules []C.Rule) ([]*router.DomainMatcher, error) {
sites := []*router.DomainMatcher{}
for _, country := range countries {
found := false
for _, rule := range rules {
if rule.RuleType() == C.GEOSITE {
if strings.EqualFold(country, rule.Payload()) {
found = true
sites = append(sites, rule.(C.RuleGeoSite).GetDomainMatcher())
log.Infoln("Start initial GeoSite dns fallback filter from rule `%s`", country)
}
}
}
if !found {
matcher, recordsCount, err := geodata.LoadGeoSiteMatcher(country)
if err != nil {
return nil, err
}
sites = append(sites, matcher)
log.Infoln("Start initial GeoSite dns fallback filter `%s`, records: %d", country, recordsCount)
}
}
runtime.GC()
return sites, nil
}
func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie, rules []C.Rule) (*DNS, error) {
cfg := rawCfg.DNS
if cfg.Enable && len(cfg.NameServer) == 0 {
return nil, fmt.Errorf("if DNS configuration is turned on, NameServer cannot be empty")
@ -584,7 +620,8 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie) (*DNS, error) {
IPv6: cfg.IPv6,
EnhancedMode: cfg.EnhancedMode,
FallbackFilter: FallbackFilter{
IPCIDR: []*net.IPNet{},
IPCIDR: []*net.IPNet{},
GeoSite: []*router.DomainMatcher{},
},
}
var err error
@ -629,6 +666,18 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie) (*DNS, error) {
}
}
if len(dnsCfg.Fallback) != 0 {
if host == nil {
host = trie.New()
}
for _, fb := range dnsCfg.Fallback {
if net.ParseIP(fb.Addr) != nil {
continue
}
host.Insert(fb.Addr, true)
}
}
pool, err := fakeip.New(fakeip.Options{
IPNet: ipnet,
Size: 1000,
@ -642,12 +691,19 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie) (*DNS, error) {
dnsCfg.FakeIPRange = pool
}
dnsCfg.FallbackFilter.GeoIP = cfg.FallbackFilter.GeoIP
dnsCfg.FallbackFilter.GeoIPCode = cfg.FallbackFilter.GeoIPCode
if fallbackip, err := parseFallbackIPCIDR(cfg.FallbackFilter.IPCIDR); err == nil {
dnsCfg.FallbackFilter.IPCIDR = fallbackip
if len(cfg.Fallback) != 0 {
dnsCfg.FallbackFilter.GeoIP = cfg.FallbackFilter.GeoIP
dnsCfg.FallbackFilter.GeoIPCode = cfg.FallbackFilter.GeoIPCode
if fallbackip, err := parseFallbackIPCIDR(cfg.FallbackFilter.IPCIDR); err == nil {
dnsCfg.FallbackFilter.IPCIDR = fallbackip
}
dnsCfg.FallbackFilter.Domain = cfg.FallbackFilter.Domain
fallbackGeoSite, err := parseFallbackGeoSite(cfg.FallbackFilter.GeoSite, rules)
if err != nil {
return nil, fmt.Errorf("load GeoSite dns fallback filter error, %w", err)
}
dnsCfg.FallbackFilter.GeoSite = fallbackGeoSite
}
dnsCfg.FallbackFilter.Domain = cfg.FallbackFilter.Domain
if cfg.UseHosts {
dnsCfg.Hosts = hosts