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:
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/util/reflect_util"
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/web/entity"
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/xray/dnsconf"
|
||||
)
|
||||
|
||||
//go:embed config.json
|
||||
@@ -146,6 +147,7 @@ var defaultValueMap = map[string]string{
|
||||
"subJsonMux": "",
|
||||
"subJsonRules": "",
|
||||
"subJsonRoutingRules": "",
|
||||
"subJsonDns": "",
|
||||
"subJsonFinalMask": "",
|
||||
"subJsonObservatory": "",
|
||||
"subThemeDir": "",
|
||||
@@ -1023,6 +1025,10 @@ func (s *SettingService) GetSubJsonRoutingRules() (string, error) {
|
||||
return s.getString("subJsonRoutingRules")
|
||||
}
|
||||
|
||||
func (s *SettingService) GetSubJsonDns() (string, error) {
|
||||
return s.getString("subJsonDns")
|
||||
}
|
||||
|
||||
func (s *SettingService) GetSubJsonFinalMask() (string, error) {
|
||||
return s.getString("subJsonFinalMask")
|
||||
}
|
||||
@@ -1339,6 +1345,9 @@ func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting, clears
|
||||
if err := validateSubUserAgentRegexes(allSetting); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateSubJsonDnsSetting(allSetting); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := allSetting.CheckValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1508,6 +1517,19 @@ func validateRemoteRoutingURLSetting(name string, value *string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// The same parser the sub server uses, so a value can never be saved as valid
|
||||
// and then silently ignored at request time.
|
||||
func validateSubJsonDnsSetting(allSetting *entity.AllSetting) error {
|
||||
value := strings.TrimSpace(allSetting.SubJsonDns)
|
||||
if value != "" {
|
||||
if _, err := dnsconf.Parse(value); err != nil {
|
||||
return common.NewError("JSON subscription DNS is invalid:", err.Error())
|
||||
}
|
||||
}
|
||||
allSetting.SubJsonDns = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SettingService) UpdateSecret(key string, value string) error {
|
||||
switch key {
|
||||
case "tgBotToken", "ldapPassword", "twoFactorToken":
|
||||
|
||||
Reference in New Issue
Block a user