1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2025-01-03 07:56:42 -05:00

Fix DNS servers with same tag wrongly merged

This commit is contained in:
Vigilans 2024-05-08 00:22:36 +08:00 committed by Xiaokang Wang (Shelikhoo)
parent 54c2c6d537
commit 7243392af2
3 changed files with 129 additions and 14 deletions

View File

@ -194,6 +194,108 @@ func TestMergeTagDeep(t *testing.T) {
assertResult(t, m, expected)
}
func TestNoMergeDnsServers(t *testing.T) {
json1 := `
{
"dns": {
"queryStrategy": "UseIPv4",
"fallbackStrategy": "disabled-if-any-match",
"domainMatcher": "mph",
"servers": [
{
"address": "aaa.bbb.ccc.ddd",
"port": 53,
"domains": [
"geosite:cn"
],
"tag": "dns-domestic"
},
{
"address": "114.114.114.114",
"port": 53,
"domains": [
"geosite:cn"
],
"tag": "dns-domestic"
},
{
"address": "https://1.1.1.1/dns-query",
"tag": "dns-international"
}
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"domainMatcher": "mph",
"rules": [
{
"type": "field",
"inboundTag": "dns-domestic",
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": "dns-international",
"outboundTag": "proxy"
}
]
}
}
`
expected := `
{
"dns": {
"queryStrategy": "UseIPv4",
"fallbackStrategy": "disabled-if-any-match",
"domainMatcher": "mph",
"servers": [
{
"address": "aaa.bbb.ccc.ddd",
"port": 53,
"domains": [
"geosite:cn"
],
"tag": "dns-domestic"
},
{
"address": "114.114.114.114",
"port": 53,
"domains": [
"geosite:cn"
],
"tag": "dns-domestic"
},
{
"address": "https://1.1.1.1/dns-query",
"tag": "dns-international"
}
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"domainMatcher": "mph",
"rules": [
{
"type": "field",
"inboundTag": "dns-domestic",
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": "dns-international",
"outboundTag": "proxy"
}
]
}
}
`
m, err := merge.JSONs([][]byte{[]byte(json1)})
if err != nil {
t.Error(err)
}
assertResult(t, m, expected)
}
func assertResult(t *testing.T, value []byte, expected string) {
v := make(map[string]interface{})
err := serial.DecodeJSON(bytes.NewReader(value), &v)

View File

@ -4,6 +4,8 @@
package merge
import "fmt"
const (
priorityKey string = "_priority"
tagKey string = "_tag"
@ -11,7 +13,7 @@ const (
// ApplyRules applies merge rules according to _tag, _priority fields, and remove them
func ApplyRules(m map[string]interface{}) error {
err := sortMergeSlices(m)
err := sortMergeSlices(m, "")
if err != nil {
return err
}
@ -20,22 +22,22 @@ func ApplyRules(m map[string]interface{}) error {
}
// sortMergeSlices enumerates all slices in a map, to sort by priority and merge by tag
func sortMergeSlices(target map[string]interface{}) error {
func sortMergeSlices(target map[string]interface{}, path string) error {
for key, value := range target {
if slice, ok := value.([]interface{}); ok {
sortByPriority(slice)
s, err := mergeSameTag(slice)
s, err := mergeSameTag(slice, fmt.Sprintf("%s.%s", path, key))
if err != nil {
return err
}
target[key] = s
for _, item := range s {
for i, item := range s {
if m, ok := item.(map[string]interface{}); ok {
sortMergeSlices(m)
sortMergeSlices(m, fmt.Sprintf("%s.%s.%d", path, key, i))
}
}
} else if field, ok := value.(map[string]interface{}); ok {
sortMergeSlices(field)
sortMergeSlices(field, fmt.Sprintf("%s.%s", path, key))
}
}
return nil

View File

@ -4,12 +4,18 @@
package merge
func getTag(v map[string]interface{}) string {
import (
"strings"
)
func getTag(v map[string]interface{}, tagKeyOnly bool) string {
if !tagKeyOnly {
if field, ok := v["tag"]; ok {
if t, ok := field.(string); ok {
return t
}
}
}
if field, ok := v[tagKey]; ok {
if t, ok := field.(string); ok {
return t
@ -18,16 +24,21 @@ func getTag(v map[string]interface{}) string {
return ""
}
func mergeSameTag(s []interface{}) ([]interface{}, error) {
func mergeSameTag(s []interface{}, path string) ([]interface{}, error) {
// from: [a,"",b,"",a,"",b,""]
// to: [a,"",b,"",merged,"",merged,""]
merged := &struct{}{}
tagKeyOnly := false
// See https://github.com/v2fly/v2ray-core/issues/2981
if strings.HasPrefix(path, ".dns.servers") {
tagKeyOnly = true
}
for i, item1 := range s {
map1, ok := item1.(map[string]interface{})
if !ok {
continue
}
tag1 := getTag(map1)
tag1 := getTag(map1, tagKeyOnly)
if tag1 == "" {
continue
}
@ -36,7 +47,7 @@ func mergeSameTag(s []interface{}) ([]interface{}, error) {
if !ok {
continue
}
tag2 := getTag(map2)
tag2 := getTag(map2, tagKeyOnly)
if tag1 == tag2 {
s[j] = merged
err := mergeMaps(map1, map2)