@@ -12,12 +12,15 @@ import (
1212 "sync"
1313 "time"
1414
15+ router "github.com/xtls/xray-core/app/router"
1516 "github.com/xtls/xray-core/common"
1617 "github.com/xtls/xray-core/common/errors"
1718 "github.com/xtls/xray-core/common/net"
19+ "github.com/xtls/xray-core/common/platform/filesystem"
1820 "github.com/xtls/xray-core/common/session"
1921 "github.com/xtls/xray-core/common/strmatcher"
2022 "github.com/xtls/xray-core/features/dns"
23+ "google.golang.org/protobuf/proto"
2124)
2225
2326// DNS is a DNS rely server.
@@ -97,6 +100,25 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
97100 }
98101
99102 for _ , ns := range config .NameServer {
103+ if runtime .GOOS != "windows" && runtime .GOOS != "wasm" {
104+ err := parseDomains (ns )
105+ if err != nil {
106+ return nil , errors .New ("failed to parse dns domain rules: " ).Base (err )
107+ }
108+
109+ expectedGeoip , err := router .GetGeoIPList (ns .ExpectedGeoip )
110+ if err != nil {
111+ return nil , errors .New ("failed to parse dns expectIPs rules: " ).Base (err )
112+ }
113+ ns .ExpectedGeoip = expectedGeoip
114+
115+ unexpectedGeoip , err := router .GetGeoIPList (ns .UnexpectedGeoip )
116+ if err != nil {
117+ return nil , errors .New ("failed to parse dns unexpectedGeoip rules: " ).Base (err )
118+ }
119+ ns .UnexpectedGeoip = unexpectedGeoip
120+
121+ }
100122 domainRuleCount += len (ns .PrioritizedDomain )
101123 }
102124
@@ -580,3 +602,76 @@ func detectGUIPlatform() bool {
580602 }
581603 return false
582604}
605+
606+ func parseDomains (ns * NameServer ) error {
607+ pureDomains := []* router.Domain {}
608+
609+ // convert to pure domain
610+ for _ , pd := range ns .PrioritizedDomain {
611+ pureDomains = append (pureDomains , & router.Domain {
612+ Type : router .Domain_Type (pd .Type ),
613+ Value : pd .Domain ,
614+ })
615+ }
616+
617+ domainList := []* router.Domain {}
618+ for _ , domain := range pureDomains {
619+ val := strings .Split (domain .Value , "_" )
620+ if len (val ) >= 2 {
621+
622+ fileName := val [0 ]
623+ code := val [1 ]
624+
625+ bs , err := filesystem .ReadAsset (fileName )
626+ if err != nil {
627+ return errors .New ("failed to load file: " , fileName ).Base (err )
628+ }
629+ bs = filesystem .Find (bs , []byte (code ))
630+ var geosite router.GeoSite
631+
632+ if err := proto .Unmarshal (bs , & geosite ); err != nil {
633+ return errors .New ("failed Unmarshal :" ).Base (err )
634+ }
635+
636+ // parse attr
637+ if len (val ) == 3 {
638+ siteWithAttr := strings .Split (val [2 ], "," )
639+ attrs := router .ParseAttrs (siteWithAttr )
640+ if ! attrs .IsEmpty () {
641+ filteredDomains := make ([]* router.Domain , 0 , len (pureDomains ))
642+ for _ , domain := range geosite .Domain {
643+ if attrs .Match (domain ) {
644+ filteredDomains = append (filteredDomains , domain )
645+ }
646+ }
647+ geosite .Domain = filteredDomains
648+ }
649+
650+ }
651+
652+ domainList = append (domainList , geosite .Domain ... )
653+
654+ // update ns.OriginalRules Size
655+ ruleTag := strings .Join (val , ":" )
656+ for i , oRule := range ns .OriginalRules {
657+ if oRule .Rule == strings .ToLower (ruleTag ) {
658+ ns .OriginalRules [i ].Size = uint32 (len (geosite .Domain ))
659+ }
660+ }
661+
662+ } else {
663+ domainList = append (domainList , domain )
664+ }
665+ }
666+
667+ // convert back to NameServer_PriorityDomain
668+ ns .PrioritizedDomain = []* NameServer_PriorityDomain {}
669+ for _ , pd := range domainList {
670+ ns .PrioritizedDomain = append (ns .PrioritizedDomain , & NameServer_PriorityDomain {
671+ Type : ToDomainMatchingType (pd .Type ),
672+ Domain : pd .Value ,
673+ })
674+ }
675+
676+ return nil
677+ }
0 commit comments