Files
elmprodvpn/selective-vpn-api/app/transport_singbox_dns_migration_map.go

126 lines
3.2 KiB
Go

package app
import (
"fmt"
"strings"
)
func transportMigrateSingBoxDNSConfigMap(root map[string]any) (bool, []string) {
if root == nil {
return false, nil
}
rawDNS, ok := root["dns"].(map[string]any)
if !ok || rawDNS == nil {
return false, nil
}
rawServers, ok := rawDNS["servers"].([]any)
if !ok || len(rawServers) == 0 {
return false, nil
}
changed := false
warnings := make([]string, 0)
migratedFakeIP := false
fakeIPCfg, _ := rawDNS["fakeip"].(map[string]any)
for i, raw := range rawServers {
srv, ok := raw.(map[string]any)
if !ok || srv == nil {
continue
}
if strings.EqualFold(strings.TrimSpace(asString(srv["detour"])), "direct") {
delete(srv, "detour")
rawServers[i] = srv
changed = true
}
if strings.TrimSpace(asString(srv["type"])) != "" {
continue
}
addr := strings.TrimSpace(asString(srv["address"]))
if addr == "" {
continue
}
converted, warn, ok := convertLegacyDNSServer(addr)
if !ok {
warnings = append(warnings, fmt.Sprintf("dns.servers[%d]: %s", i, warn))
continue
}
legacyAddrResolver := strings.TrimSpace(asString(srv["address_resolver"]))
legacyAddrStrategy := strings.TrimSpace(asString(srv["address_strategy"]))
legacyStrategy := strings.TrimSpace(asString(srv["strategy"]))
legacySubnet := strings.TrimSpace(asString(srv["client_subnet"]))
tag := strings.TrimSpace(asString(srv["tag"]))
// Required new fields for typed DNS server.
for k, v := range converted {
srv[k] = v
}
delete(srv, "address")
if legacyAddrResolver != "" && strings.TrimSpace(asString(srv["domain_resolver"])) == "" {
srv["domain_resolver"] = legacyAddrResolver
}
delete(srv, "address_resolver")
if legacyAddrStrategy != "" && strings.TrimSpace(asString(srv["domain_strategy"])) == "" {
srv["domain_strategy"] = legacyAddrStrategy
}
delete(srv, "address_strategy")
if legacyStrategy != "" {
if strings.TrimSpace(asString(rawDNS["strategy"])) == "" {
rawDNS["strategy"] = legacyStrategy
} else if tag != "" {
transportAppendDNSRule(rawDNS, map[string]any{
"server": tag,
"strategy": legacyStrategy,
})
} else {
warnings = append(warnings, fmt.Sprintf("dns.servers[%d]: strategy moved partially (missing tag)", i))
}
delete(srv, "strategy")
}
if legacySubnet != "" {
if tag != "" {
transportAppendDNSRule(rawDNS, map[string]any{
"server": tag,
"client_subnet": legacySubnet,
})
} else if strings.TrimSpace(asString(rawDNS["client_subnet"])) == "" {
rawDNS["client_subnet"] = legacySubnet
} else {
warnings = append(warnings, fmt.Sprintf("dns.servers[%d]: client_subnet moved partially (missing tag)", i))
}
delete(srv, "client_subnet")
}
if strings.EqualFold(asString(srv["type"]), "fakeip") && fakeIPCfg != nil {
if _, ok := srv["inet4_range"]; !ok {
if v, ok := fakeIPCfg["inet4_range"]; ok {
srv["inet4_range"] = v
}
}
if _, ok := srv["inet6_range"]; !ok {
if v, ok := fakeIPCfg["inet6_range"]; ok {
srv["inet6_range"] = v
}
}
migratedFakeIP = true
}
rawServers[i] = srv
changed = true
}
if changed {
rawDNS["servers"] = rawServers
if migratedFakeIP {
delete(rawDNS, "fakeip")
}
root["dns"] = rawDNS
}
return changed, dedupeStrings(warnings)
}