Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 0 additions & 95 deletions app/dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@ import (
"sync"
"time"

router "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/features/dns"
"google.golang.org/protobuf/proto"
)

// DNS is a DNS rely server.
Expand Down Expand Up @@ -100,25 +97,6 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
}

for _, ns := range config.NameServer {
if runtime.GOOS != "windows" && runtime.GOOS != "wasm" {
err := parseDomains(ns)
if err != nil {
return nil, errors.New("failed to parse dns domain rules: ").Base(err)
}

expectedGeoip, err := router.GetGeoIPList(ns.ExpectedGeoip)
if err != nil {
return nil, errors.New("failed to parse dns expectIPs rules: ").Base(err)
}
ns.ExpectedGeoip = expectedGeoip

unexpectedGeoip, err := router.GetGeoIPList(ns.UnexpectedGeoip)
if err != nil {
return nil, errors.New("failed to parse dns unexpectedGeoip rules: ").Base(err)
}
ns.UnexpectedGeoip = unexpectedGeoip

}
domainRuleCount += len(ns.PrioritizedDomain)
}

Expand Down Expand Up @@ -602,76 +580,3 @@ func detectGUIPlatform() bool {
}
return false
}

func parseDomains(ns *NameServer) error {
pureDomains := []*router.Domain{}

// convert to pure domain
for _, pd := range ns.PrioritizedDomain {
pureDomains = append(pureDomains, &router.Domain{
Type: router.Domain_Type(pd.Type),
Value: pd.Domain,
})
}

domainList := []*router.Domain{}
for _, domain := range pureDomains {
val := strings.Split(domain.Value, "_")
if len(val) >= 2 {

fileName := val[0]
code := val[1]

bs, err := filesystem.ReadAsset(fileName)
if err != nil {
return errors.New("failed to load file: ", fileName).Base(err)
}
bs = filesystem.Find(bs, []byte(code))
var geosite router.GeoSite

if err := proto.Unmarshal(bs, &geosite); err != nil {
return errors.New("failed Unmarshal :").Base(err)
}

// parse attr
if len(val) == 3 {
siteWithAttr := strings.Split(val[2], ",")
attrs := router.ParseAttrs(siteWithAttr)
if !attrs.IsEmpty() {
filteredDomains := make([]*router.Domain, 0, len(pureDomains))
for _, domain := range geosite.Domain {
if attrs.Match(domain) {
filteredDomains = append(filteredDomains, domain)
}
}
geosite.Domain = filteredDomains
}

}

domainList = append(domainList, geosite.Domain...)

// update ns.OriginalRules Size
ruleTag := strings.Join(val, ":")
for i, oRule := range ns.OriginalRules {
if oRule.Rule == strings.ToLower(ruleTag) {
ns.OriginalRules[i].Size = uint32(len(geosite.Domain))
}
}

} else {
domainList = append(domainList, domain)
}
}

// convert back to NameServer_PriorityDomain
ns.PrioritizedDomain = []*NameServer_PriorityDomain{}
for _, pd := range domainList {
ns.PrioritizedDomain = append(ns.PrioritizedDomain, &NameServer_PriorityDomain{
Type: ToDomainMatchingType(pd.Type),
Domain: pd.Value,
})
}

return nil
}
8 changes: 4 additions & 4 deletions app/dns/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ func TestIPMatch(t *testing.T) {
},
ExpectedGeoip: []*router.GeoIP{
{
// local
CountryCode: "local",
Cidr: []*router.CIDR{
{
// inner ip, will not match
Expand All @@ -565,7 +565,7 @@ func TestIPMatch(t *testing.T) {
},
ExpectedGeoip: []*router.GeoIP{
{
// test
CountryCode: "test",
Cidr: []*router.CIDR{
{
Ip: []byte{8, 8, 8, 8},
Expand All @@ -574,7 +574,7 @@ func TestIPMatch(t *testing.T) {
},
},
{
// test
CountryCode: "test",
Cidr: []*router.CIDR{
{
Ip: []byte{8, 8, 8, 4},
Expand Down Expand Up @@ -669,7 +669,7 @@ func TestLocalDomain(t *testing.T) {
},
ExpectedGeoip: []*router.GeoIP{
{ // Will match localhost, localhost-a and localhost-b,
// local
CountryCode: "local",
Cidr: []*router.CIDR{
{Ip: []byte{127, 0, 0, 2}, Prefix: 32},
{Ip: []byte{127, 0, 0, 3}, Prefix: 32},
Expand Down
15 changes: 0 additions & 15 deletions app/dns/nameserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,18 +297,3 @@ func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption)
return ipOption
}
}

func ToDomainMatchingType(t router.Domain_Type) DomainMatchingType {
switch t {
case router.Domain_Domain:
return DomainMatchingType_Subdomain
case router.Domain_Full:
return DomainMatchingType_Full
case router.Domain_Plain:
return DomainMatchingType_Keyword
case router.Domain_Regex:
return DomainMatchingType_Regex
default:
panic("unknown domain type")
}
}
44 changes: 1 addition & 43 deletions app/router/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,48 +309,6 @@ func (m *AttributeMatcher) Apply(ctx routing.Context) bool {
return m.Match(attributes)
}

// Geo attribute
type GeoAttributeMatcher interface {
Match(*Domain) bool
}

type GeoBooleanMatcher string

func (m GeoBooleanMatcher) Match(domain *Domain) bool {
for _, attr := range domain.Attribute {
if attr.Key == string(m) {
return true
}
}
return false
}

type GeoAttributeList struct {
Matcher []GeoAttributeMatcher
}

func (al *GeoAttributeList) Match(domain *Domain) bool {
for _, matcher := range al.Matcher {
if !matcher.Match(domain) {
return false
}
}
return true
}

func (al *GeoAttributeList) IsEmpty() bool {
return len(al.Matcher) == 0
}

func ParseAttrs(attrs []string) *GeoAttributeList {
al := new(GeoAttributeList)
for _, attr := range attrs {
lc := strings.ToLower(attr)
al.Matcher = append(al.Matcher, GeoBooleanMatcher(lc))
}
return al
}

type ProcessNameMatcher struct {
ProcessNames []string
AbsPaths []string
Expand Down Expand Up @@ -439,4 +397,4 @@ func (m *ProcessNameMatcher) Apply(ctx routing.Context) bool {
}
}
return false
}
}
81 changes: 55 additions & 26 deletions app/router/condition_geoip_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
package router_test

import (
"fmt"
"os"
"path/filepath"
"runtime"
"testing"

"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/infra/conf"
"github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem"
"google.golang.org/protobuf/proto"
)

func getAssetPath(file string) (string, error) {
path := platform.GetAssetLocation(file)
_, err := os.Stat(path)
if os.IsNotExist(err) {
path := filepath.Join("..", "..", "resources", file)
_, err := os.Stat(path)
if os.IsNotExist(err) {
return "", fmt.Errorf("can't find %s in standard asset locations or {project_root}/resources", file)
}
if err != nil {
return "", fmt.Errorf("can't stat %s: %v", path, err)
}
return path, nil
}
if err != nil {
return "", fmt.Errorf("can't stat %s: %v", path, err)
}

return path, nil
}

func TestGeoIPMatcher(t *testing.T) {
cidrList := []*router.CIDR{
{Ip: []byte{0, 0, 0, 0}, Prefix: 8},
Expand Down Expand Up @@ -159,11 +182,12 @@ func TestGeoIPReverseMatcher(t *testing.T) {
}

func TestGeoIPMatcher4CN(t *testing.T) {
geo := "geoip:cn"
geoip, err := loadGeoIP(geo)
ips, err := loadGeoIP("CN")
common.Must(err)

matcher, err := router.BuildOptimizedGeoIPMatcher(geoip)
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
Cidr: ips,
})
common.Must(err)

if matcher.Match([]byte{8, 8, 8, 8}) {
Expand All @@ -172,46 +196,50 @@ func TestGeoIPMatcher4CN(t *testing.T) {
}

func TestGeoIPMatcher6US(t *testing.T) {
geo := "geoip:us"
geoip, err := loadGeoIP(geo)
ips, err := loadGeoIP("US")
common.Must(err)

matcher, err := router.BuildOptimizedGeoIPMatcher(geoip)
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
Cidr: ips,
})
common.Must(err)

if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
}
}

func loadGeoIP(geo string) (*router.GeoIP, error) {
os.Setenv("XRAY_LOCATION_ASSET", filepath.Join("..", "..", "resources"))

geoip, err := conf.ToCidrList([]string{geo})
func loadGeoIP(country string) ([]*router.CIDR, error) {
path, err := getAssetPath("geoip.dat")
if err != nil {
return nil, err
}
geoipBytes, err := filesystem.ReadFile(path)
if err != nil {
return nil, err
}

if runtime.GOOS != "windows" && runtime.GOOS != "wasm" {
geoip, err = router.GetGeoIPList(geoip)
if err != nil {
return nil, err
}
var geoipList router.GeoIPList
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
return nil, err
}

if len(geoip) == 0 {
panic("country not found: " + geo)
for _, geoip := range geoipList.Entry {
if geoip.CountryCode == country {
return geoip.Cidr, nil
}
}

return geoip[0], nil
panic("country not found: " + country)
}

func BenchmarkGeoIPMatcher4CN(b *testing.B) {
geo := "geoip:cn"
geoip, err := loadGeoIP(geo)
ips, err := loadGeoIP("CN")
common.Must(err)

matcher, err := router.BuildOptimizedGeoIPMatcher(geoip)
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
Cidr: ips,
})
common.Must(err)

b.ResetTimer()
Expand All @@ -222,11 +250,12 @@ func BenchmarkGeoIPMatcher4CN(b *testing.B) {
}

func BenchmarkGeoIPMatcher6US(b *testing.B) {
geo := "geoip:us"
geoip, err := loadGeoIP(geo)
ips, err := loadGeoIP("US")
common.Must(err)

matcher, err := router.BuildOptimizedGeoIPMatcher(geoip)
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
Cidr: ips,
})
common.Must(err)

b.ResetTimer()
Expand Down
Loading