From b22d1e082af133acab9192ca532df46126f967e6 Mon Sep 17 00:00:00 2001 From: Alireza Ahmadi Date: Tue, 12 Mar 2024 12:24:01 +0100 Subject: [PATCH] [subJson] add mux and direct --- sub/default.json | 2 +- sub/sub.go | 14 +++- sub/subController.go | 4 +- sub/subJsonService.go | 24 ++++++- web/assets/js/model/setting.js | 8 ++- web/entity/entity.go | 2 + web/html/xui/settings.html | 121 +++++++++++++++++++++++++++++++++ web/service/setting.go | 10 +++ 8 files changed, 177 insertions(+), 8 deletions(-) diff --git a/sub/default.json b/sub/default.json index d98a03ef..3f8c86a6 100644 --- a/sub/default.json +++ b/sub/default.json @@ -74,7 +74,7 @@ } }, "routing": { - "domainStrategy": "AsIs", + "domainStrategy": "IPIfNonMatch", "rules": [ { "type": "field", diff --git a/sub/sub.go b/sub/sub.go index 26dbcd2c..8fe025bc 100644 --- a/sub/sub.go +++ b/sub/sub.go @@ -92,9 +92,21 @@ func (s *Server) initRouter() (*gin.Engine, error) { SubJsonFragment = "" } + SubJsonMux, err := s.settingService.GetSubJsonMux() + if err != nil { + SubJsonMux = "" + } + + SubJsonRules, err := s.settingService.GetSubJsonRules() + if err != nil { + SubJsonRules = "" + } + g := engine.Group("/") - s.sub = NewSUBController(g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates, SubJsonFragment) + s.sub = NewSUBController( + g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates, + SubJsonFragment, SubJsonMux, SubJsonRules) return engine, nil } diff --git a/sub/subController.go b/sub/subController.go index 58d638d7..325d4519 100644 --- a/sub/subController.go +++ b/sub/subController.go @@ -26,6 +26,8 @@ func NewSUBController( rModel string, update string, jsonFragment string, + jsonMux string, + jsonRules string, ) *SUBController { sub := NewSubService(showInfo, rModel) a := &SUBController{ @@ -35,7 +37,7 @@ func NewSUBController( updateInterval: update, subService: sub, - subJsonService: NewSubJsonService(jsonFragment, sub), + subJsonService: NewSubJsonService(jsonFragment, jsonMux, jsonRules, sub), } a.initRouter(g) return a diff --git a/sub/subJsonService.go b/sub/subJsonService.go index d50e9644..0467e311 100644 --- a/sub/subJsonService.go +++ b/sub/subJsonService.go @@ -21,12 +21,13 @@ type SubJsonService struct { configJson map[string]interface{} defaultOutbounds []json_util.RawMessage fragment string + mux string inboundService service.InboundService SubService *SubService } -func NewSubJsonService(fragment string, subService *SubService) *SubJsonService { +func NewSubJsonService(fragment string, mux string, rules string, subService *SubService) *SubJsonService { var configJson map[string]interface{} var defaultOutbounds []json_util.RawMessage json.Unmarshal([]byte(defaultJson), &configJson) @@ -37,6 +38,17 @@ func NewSubJsonService(fragment string, subService *SubService) *SubJsonService } } + if rules != "" { + var newRules []interface{} + routing, _ := configJson["routing"].(map[string]interface{}) + defaultRules, _ := routing["rules"].([]interface{}) + json.Unmarshal([]byte(rules), &newRules) + defaultRules = append(newRules, defaultRules...) + fmt.Printf("routing: %#v\n\nRules: %#v\n\n", routing, defaultRules) + routing["rules"] = defaultRules + configJson["routing"] = routing + } + if fragment != "" { defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment)) } @@ -45,6 +57,7 @@ func NewSubJsonService(fragment string, subService *SubService) *SubJsonService configJson: configJson, defaultOutbounds: defaultOutbounds, fragment: fragment, + mux: mux, SubService: subService, } } @@ -174,6 +187,7 @@ func (s *SubJsonService) getConfig(inbound *model.Inbound, client model.Client, } newConfigJson["outbounds"] = newOutbounds newConfigJson["remarks"] = s.SubService.genRemark(inbound, client.Email, extPrxy["remark"].(string)) + newConfig, _ := json.MarshalIndent(newConfigJson, "", " ") newJsonArray = append(newJsonArray, newConfig) } @@ -277,6 +291,9 @@ func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_ut outbound.Protocol = string(inbound.Protocol) outbound.Tag = "proxy" + if s.mux != "" { + outbound.Mux = json_util.RawMessage(s.mux) + } outbound.StreamSettings = streamSettings outbound.Settings = OutboundSettings{ Vnext: vnextData, @@ -313,6 +330,9 @@ func (s *SubJsonService) genServer(inbound *model.Inbound, streamSettings json_u outbound.Protocol = string(inbound.Protocol) outbound.Tag = "proxy" + if s.mux != "" { + outbound.Mux = json_util.RawMessage(s.mux) + } outbound.StreamSettings = streamSettings outbound.Settings = OutboundSettings{ Servers: serverData, @@ -326,7 +346,7 @@ type Outbound struct { Protocol string `json:"protocol"` Tag string `json:"tag"` StreamSettings json_util.RawMessage `json:"streamSettings"` - Mux map[string]interface{} `json:"mux,omitempty"` + Mux json_util.RawMessage `json:"mux,omitempty"` ProxySettings map[string]interface{} `json:"proxySettings,omitempty"` Settings OutboundSettings `json:"settings,omitempty"` } diff --git a/web/assets/js/model/setting.js b/web/assets/js/model/setting.js index 286535d7..a60c0df6 100644 --- a/web/assets/js/model/setting.js +++ b/web/assets/js/model/setting.js @@ -31,9 +31,11 @@ class AllSetting { this.subUpdates = 0; this.subEncrypt = true; this.subShowInfo = false; - this.subURI = ''; - this.subJsonURI = ''; - this.subJsonFragment = ''; + this.subURI = ""; + this.subJsonURI = ""; + this.subJsonFragment = ""; + this.subJsonMux = ""; + this.subJsonRules = ""; this.timeLocation = "Asia/Tehran"; diff --git a/web/entity/entity.go b/web/entity/entity.go index 7b50341e..cb173394 100644 --- a/web/entity/entity.go +++ b/web/entity/entity.go @@ -50,6 +50,8 @@ type AllSetting struct { SubJsonPath string `json:"subJsonPath" form:"subJsonPath"` SubJsonURI string `json:"subJsonURI" form:"subJsonURI"` SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"` + SubJsonMux string `json:"subJsonMux" form:"subJsonMux"` + SubJsonRules string `json:"subJsonRules" form:"subJsonRules"` } func (s *AllSetting) CheckValid() error { diff --git a/web/html/xui/settings.html b/web/html/xui/settings.html index d887e401..85fe78d0 100644 --- a/web/html/xui/settings.html +++ b/web/html/xui/settings.html @@ -209,6 +209,8 @@ + + @@ -232,6 +234,36 @@ + + + + + + + + + + + + [[ p ]] + + + + + + + + + + + @@ -280,6 +312,40 @@ } } }, + defaultMux: { + enabled: true, + concurrency: 8, + xudpConcurrency: 16, + xudpProxyUDP443: "reject" + }, + defaultRules: [ + { + type: "field", + outboundTag: "direct", + domain: [ + "geosite:category-ir", + "geosite:cn" + ], + "enabled": true + }, + { + type: "field", + outboundTag: "direct", + ip: [ + "geoip:private", + "geoip:ir", + "geoip:cn" + ], + enabled: true + }, + ], + countryOptions: [ + { label: 'Private IP/Domain', value: 'private' }, + { label: '🇮🇷 Iran', value: 'ir' }, + { label: '🇨🇳 China', value: 'cn' }, + { label: '🇷🇺 Russia', value: 'ru' }, + { label: '🇻🇳 Vietnam', value: 'vn' }, + ], get remarkModel() { rm = this.allSetting.remarkModel; return rm.length>1 ? rm.substring(1).split('') : []; @@ -397,6 +463,61 @@ } } }, + enableMux: { + get: function() { return this.allSetting?.subJsonMux != ""; }, + set: function (v) { + this.allSetting.subJsonMux = v ? JSON.stringify(this.defaultMux) : ""; + } + }, + muxConcurrency: { + get: function() { return this.enableMux ? JSON.parse(this.allSetting.subJsonMux).concurrency : -1; }, + set: function(v) { + newMux = JSON.parse(this.allSetting.subJsonMux); + newMux.concurrency = v; + this.allSetting.subJsonMux = JSON.stringify(newMux); + } + }, + muxXudpConcurrency: { + get: function() { return this.enableMux ? JSON.parse(this.allSetting.subJsonMux).xudpConcurrency : -1; }, + set: function(v) { + newMux = JSON.parse(this.allSetting.subJsonMux); + newMux.xudpConcurrency = v; + this.allSetting.subJsonMux = JSON.stringify(newMux); + } + }, + muxXudpProxyUDP443: { + get: function() { return this.enableMux ? JSON.parse(this.allSetting.subJsonMux).xudpProxyUDP443 : "reject"; }, + set: function(v) { + newMux = JSON.parse(this.allSetting.subJsonMux); + newMux.xudpProxyUDP443 = v; + this.allSetting.subJsonMux = JSON.stringify(newMux); + } + }, + enableDirect: { + get: function() { return this.allSetting?.subJsonRules != ""; }, + set: function (v) { + this.allSetting.subJsonRules = v ? JSON.stringify(this.defaultRules) : ""; + } + }, + directCountries: { + get: function() { + if (!this.enableDirect) return []; + rules = JSON.parse(this.allSetting.subJsonRules); + return Array.isArray(rules) ? rules[1].ip.map(d => d.replace("geoip:","")) : []; + }, + set: function (v) { + rules = JSON.parse(this.allSetting.subJsonRules); + if (!Array.isArray(rules)) return; + rules[0].domain = []; + rules[1].ip = []; + v.forEach(d => { + category = ["cn","private"].includes(d) ? "" : "category-"; + rules[0].domain.push("geosite:"+category+d); + rules[1].ip.push("geoip:"+d); + }); + this.allSetting.subJsonRules = JSON.stringify(rules); + } + }, confAlerts: { get: function() { if (!this.allSetting) return []; diff --git a/web/service/setting.go b/web/service/setting.go index b7738194..43105411 100644 --- a/web/service/setting.go +++ b/web/service/setting.go @@ -59,6 +59,8 @@ var defaultValueMap = map[string]string{ "subJsonPath": "/json/", "subJsonURI": "", "subJsonFragment": "", + "subJsonMux": "", + "subJsonRules": "", "warp": "", } @@ -403,6 +405,14 @@ func (s *SettingService) GetSubJsonFragment() (string, error) { return s.getString("subJsonFragment") } +func (s *SettingService) GetSubJsonMux() (string, error) { + return s.getString("subJsonMux") +} + +func (s *SettingService) GetSubJsonRules() (string, error) { + return s.getString("subJsonRules") +} + func (s *SettingService) GetWarp() (string, error) { return s.getString("warp") }