mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-17 07:37:15 +00:00
feat(sub): let the panel set the JSON subscription DNS servers (#6485)
* feat(sub): let the panel set the JSON subscription DNS servers A baked routing profile (#6402) carries only the DNS its preset defines, so an operator who wants their own resolvers has to override the whole profile or patch the subscription behind a proxy. Add the subJsonDns setting: either a full xray dns block or a bare array of servers. It wins over the profile's DNS while leaving the profile's routing rules intact, and reaches per-inbound, balancer and info-node documents alike. The value is validated with xray's own schema (internal/xray/dnsconf): a block the client could not load is rejected when the settings are saved and ignored with a warning at request time, instead of being baked into every document. Both the sub server and the settings API share that validator, so a stored value can never be silently dropped. xray's Build() is deliberately not used for validation: it resolves geosite tokens from the geodata files and would reject valid configs whenever those are absent from the panel's working directory. * style(dnsconf): drop the ineffectual initial map assignment golangci's ineffassign flagged the zero-value map whose value both paths overwrite: the object branch now assigns the decoded map directly. * docs(sub): scope the DNS setting to the documents it rewrites The Routing header mirrored to Happ/INCY keeps the routing profile's own resolvers, so the setting description and the header-source comment now say so instead of claiming the profile's DNS is replaced everywhere. Also trims two comments in the new dnsconf package to the repo's two-line cap.
This commit is contained in:
@@ -37,6 +37,9 @@ type SubJsonService struct {
|
||||
bakedRoutingMu sync.Mutex
|
||||
bakedRouting *bakedRoutingState
|
||||
|
||||
// dnsBlock is the panel DNS override, fixed for the service's lifetime.
|
||||
dnsBlock map[string]any
|
||||
|
||||
SubService *SubService
|
||||
}
|
||||
|
||||
@@ -83,7 +86,7 @@ func NewSubJsonService(mux string, rules string, finalMask string, routingRules
|
||||
// Re-resolved per call so an upstream edit reaches the documents without a
|
||||
// restart; a failed resolve keeps the last good template.
|
||||
func (s *SubJsonService) bakedTemplate() map[string]any {
|
||||
if s.routingRules == "" {
|
||||
if s.routingRules == "" && s.dnsBlock == nil {
|
||||
return s.configJson
|
||||
}
|
||||
spec := resolveJsonRoutingSpec(s.routingRules)
|
||||
@@ -93,12 +96,19 @@ func (s *SubJsonService) bakedTemplate() map[string]any {
|
||||
if spec.empty() || spec.equal(s.bakedRouting.spec) {
|
||||
return s.bakedRouting.configJson
|
||||
}
|
||||
} else if spec.empty() {
|
||||
} else if spec.empty() && s.dnsBlock == nil {
|
||||
return s.configJson
|
||||
}
|
||||
template := make(map[string]any, len(s.configJson)+2)
|
||||
maps.Copy(template, s.configJson)
|
||||
applyJsonRouting(template, spec)
|
||||
if !spec.empty() {
|
||||
applyJsonRouting(template, spec)
|
||||
}
|
||||
// The panel-level DNS block is an explicit choice, so it also replaces the
|
||||
// dns subtree a routing profile would otherwise bake in.
|
||||
if s.dnsBlock != nil {
|
||||
template["dns"] = s.dnsBlock
|
||||
}
|
||||
s.bakedRouting = &bakedRoutingState{spec: spec, configJson: template}
|
||||
return template
|
||||
}
|
||||
@@ -1041,6 +1051,9 @@ func (s *SubJsonService) genDummySocksConfig(remark string) json_util.RawMessage
|
||||
|
||||
newConfigJson := make(map[string]any)
|
||||
maps.Copy(newConfigJson, s.configJson)
|
||||
if s.dnsBlock != nil {
|
||||
newConfigJson["dns"] = s.dnsBlock
|
||||
}
|
||||
newConfigJson["outbounds"] = newOutbounds
|
||||
newConfigJson["remarks"] = remark
|
||||
|
||||
|
||||
Reference in New Issue
Block a user