diff --git a/api/apimodel.go b/api/apimodel.go index 3db79b3..38f1005 100644 --- a/api/apimodel.go +++ b/api/apimodel.go @@ -3,6 +3,8 @@ package api import ( "encoding/json" "regexp" + + "github.com/xtls/xray-core/infra/conf" ) // Config API config @@ -45,6 +47,7 @@ type NodeInfo struct { ServerKey string ServiceName string Header json.RawMessage + NameServerConfig []*conf.NameServerConfig } type UserInfo struct { diff --git a/api/newV2board/v2board.go b/api/newV2board/v2board.go index ab9610f..021d6de 100644 --- a/api/newV2board/v2board.go +++ b/api/newV2board/v2board.go @@ -15,6 +15,8 @@ import ( "github.com/bitly/go-simplejson" "github.com/go-resty/resty/v2" + "github.com/xtls/xray-core/common/net" + "github.com/xtls/xray-core/infra/conf" "github.com/XrayR-project/XrayR/api" ) @@ -304,6 +306,7 @@ func (c *APIClient) parseTrojanNodeResponse(nodeInfoResponse *simplejson.Json) ( TLSType: TLSType, Host: nodeInfoResponse.Get("host").MustString(), ServiceName: nodeInfoResponse.Get("server_name").MustString(), + NameServerConfig: parseDNSConfig(nodeInfoResponse), } return nodeInfo, nil } @@ -318,6 +321,7 @@ func (c *APIClient) parseSSNodeResponse(nodeInfoResponse *simplejson.Json) (*api TransportProtocol: "tcp", CypherMethod: nodeInfoResponse.Get("cipher").MustString(), ServerKey: nodeInfoResponse.Get("server_key").MustString(), // shadowsocks2022 share key + NameServerConfig: parseDNSConfig(nodeInfoResponse), }, nil } @@ -373,5 +377,20 @@ func (c *APIClient) parseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (* EnableVless: c.EnableVless, ServiceName: serviceName, Header: header, + NameServerConfig: parseDNSConfig(nodeInfoResponse), }, nil } + +func parseDNSConfig(nodeInfoResponse *simplejson.Json) (nameServerList []*conf.NameServerConfig) { + for _, rule := range nodeInfoResponse.Get("routes").MustArray() { + r := rule.(map[string]any) + if r["action"] == "dns" { + nameServerList = append(nameServerList, &conf.NameServerConfig{ + Address: &conf.Address{Address: net.ParseAddress(r["action_value"].(string))}, + Domains: strings.Split(r["match"].(string), ","), + }) + } + } + + return +} diff --git a/panel/panel.go b/panel/panel.go index 3d13671..c40f861 100644 --- a/panel/panel.go +++ b/panel/panel.go @@ -66,10 +66,12 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance { } } } - dnsConfig, err := coreDnsConfig.Build() - if err != nil { - log.Panicf("Failed to understand DNS config, Please check: https://xtls.github.io/config/dns.html for help: %s", err) + + // init controller's DNS config + for _, config := range p.panelConfig.NodesConfig { + config.ControllerConfig.DNSConfig = coreDnsConfig } + // Routing config coreRouterConfig := &conf.RouterConfig{} if panelConfig.RouteConfigPath != "" { @@ -137,7 +139,6 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance { serial.ToTypedMessage(&proxyman.InboundConfig{}), serial.ToTypedMessage(&proxyman.OutboundConfig{}), serial.ToTypedMessage(policyConfig), - serial.ToTypedMessage(dnsConfig), serial.ToTypedMessage(routeConfig), }, Inbound: inBoundConfig, diff --git a/service/controller/config.go b/service/controller/config.go index d1b7080..430f74b 100644 --- a/service/controller/config.go +++ b/service/controller/config.go @@ -1,6 +1,8 @@ package controller import ( + "github.com/xtls/xray-core/infra/conf" + "github.com/XrayR-project/XrayR/common/limiter" "github.com/XrayR-project/XrayR/common/mylego" ) @@ -21,6 +23,7 @@ type Config struct { AutoSpeedLimitConfig *AutoSpeedLimitConfig `mapstructure:"AutoSpeedLimitConfig"` GlobalDeviceLimitConfig *limiter.GlobalDeviceLimitConfig `mapstructure:"GlobalDeviceLimitConfig"` FallBackConfigs []*FallBackConfig `mapstructure:"FallBackConfigs"` + DNSConfig *conf.DNSConfig } type AutoSpeedLimitConfig struct { diff --git a/service/controller/controller.go b/service/controller/controller.go index b791ba4..699c301 100644 --- a/service/controller/controller.go +++ b/service/controller/controller.go @@ -7,12 +7,15 @@ import ( "time" "github.com/xtls/xray-core/common/protocol" + "github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/core" + "github.com/xtls/xray-core/features" "github.com/xtls/xray-core/features/inbound" "github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/stats" + "github.com/xtls/xray-core/infra/conf" "github.com/XrayR-project/XrayR/api" "github.com/XrayR-project/XrayR/app/mydispatcher" @@ -77,6 +80,13 @@ func (c *Controller) Start() error { } c.nodeInfo = newNodeInfo c.Tag = c.buildNodeTag() + + // append remote DNS config and init dns service + err = c.addNewDNS(newNodeInfo) + if err != nil { + return err + } + // Add new tag err = c.addNewTag(newNodeInfo) if err != nil { @@ -252,6 +262,13 @@ func (c *Controller) nodeInfoMonitor() (err error) { log.Print(err) return nil } + + // Add DNS + log.Printf("%s Reload DNS service", c.logPrefix()) + if err := c.addNewDNS(newNodeInfo); err != nil { + log.Print(err) + return nil + } } else { var deleted, added []api.UserInfo if usersChanged { @@ -613,3 +630,32 @@ func (c *Controller) certMonitor() error { } return nil } + +// append remote dns +func (c *Controller) addNewDNS(newNodeInfo *api.NodeInfo) error { + // reserve local DNS + servers := make([]*conf.NameServerConfig, len(c.config.DNSConfig.Servers)) + copy(servers, c.config.DNSConfig.Servers) + servers = append(servers, newNodeInfo.NameServerConfig...) + + buf := &conf.DNSConfig{Servers: servers} + dnsConfig, err := buf.Build() + if err != nil { + log.Panicf("Failed to understand DNS config, Please check: https://xtls.github.io/config/dns.html for help: %s", err) + } + dnsInstance, err := serial.ToTypedMessage(dnsConfig).GetInstance() + if err != nil { + return err + } + obj, err := core.CreateObject(c.server, dnsInstance) + if err != nil { + return err + } + if feature, ok := obj.(features.Feature); ok { + if err := c.server.AddFeature(feature); err != nil { + return err + } + } + + return nil +}