[subJson] add mux and direct

Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
This commit is contained in:
MHSanaei 2024-03-12 19:44:51 +03:30
parent fc23af5db6
commit 8b5fe0b018
7 changed files with 175 additions and 7 deletions

View file

@ -92,9 +92,21 @@ func (s *Server) initRouter() (*gin.Engine, error) {
SubJsonFragment = "" SubJsonFragment = ""
} }
SubJsonMux, err := s.settingService.GetSubJsonMux()
if err != nil {
SubJsonMux = ""
}
SubJsonRules, err := s.settingService.GetSubJsonRules()
if err != nil {
SubJsonRules = ""
}
g := engine.Group("/") 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 return engine, nil
} }

View file

@ -26,6 +26,8 @@ func NewSUBController(
rModel string, rModel string,
update string, update string,
jsonFragment string, jsonFragment string,
jsonMux string,
jsonRules string,
) *SUBController { ) *SUBController {
sub := NewSubService(showInfo, rModel) sub := NewSubService(showInfo, rModel)
a := &SUBController{ a := &SUBController{
@ -35,7 +37,7 @@ func NewSUBController(
updateInterval: update, updateInterval: update,
subService: sub, subService: sub,
subJsonService: NewSubJsonService(jsonFragment, sub), subJsonService: NewSubJsonService(jsonFragment, jsonMux, jsonRules, sub),
} }
a.initRouter(g) a.initRouter(g)
return a return a

View file

@ -21,12 +21,13 @@ type SubJsonService struct {
configJson map[string]interface{} configJson map[string]interface{}
defaultOutbounds []json_util.RawMessage defaultOutbounds []json_util.RawMessage
fragment string fragment string
mux string
inboundService service.InboundService inboundService service.InboundService
SubService *SubService 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 configJson map[string]interface{}
var defaultOutbounds []json_util.RawMessage var defaultOutbounds []json_util.RawMessage
json.Unmarshal([]byte(defaultJson), &configJson) 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 != "" { if fragment != "" {
defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment)) defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment))
} }
@ -45,6 +57,7 @@ func NewSubJsonService(fragment string, subService *SubService) *SubJsonService
configJson: configJson, configJson: configJson,
defaultOutbounds: defaultOutbounds, defaultOutbounds: defaultOutbounds,
fragment: fragment, fragment: fragment,
mux: mux,
SubService: subService, SubService: subService,
} }
} }
@ -277,6 +290,9 @@ func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_ut
outbound.Protocol = string(inbound.Protocol) outbound.Protocol = string(inbound.Protocol)
outbound.Tag = "proxy" outbound.Tag = "proxy"
if s.mux != "" {
outbound.Mux = json_util.RawMessage(s.mux)
}
outbound.StreamSettings = streamSettings outbound.StreamSettings = streamSettings
outbound.Settings = OutboundSettings{ outbound.Settings = OutboundSettings{
Vnext: vnextData, Vnext: vnextData,
@ -313,6 +329,9 @@ func (s *SubJsonService) genServer(inbound *model.Inbound, streamSettings json_u
outbound.Protocol = string(inbound.Protocol) outbound.Protocol = string(inbound.Protocol)
outbound.Tag = "proxy" outbound.Tag = "proxy"
if s.mux != "" {
outbound.Mux = json_util.RawMessage(s.mux)
}
outbound.StreamSettings = streamSettings outbound.StreamSettings = streamSettings
outbound.Settings = OutboundSettings{ outbound.Settings = OutboundSettings{
Servers: serverData, Servers: serverData,
@ -326,7 +345,7 @@ type Outbound struct {
Protocol string `json:"protocol"` Protocol string `json:"protocol"`
Tag string `json:"tag"` Tag string `json:"tag"`
StreamSettings json_util.RawMessage `json:"streamSettings"` 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"` ProxySettings map[string]interface{} `json:"proxySettings,omitempty"`
Settings OutboundSettings `json:"settings,omitempty"` Settings OutboundSettings `json:"settings,omitempty"`
} }

View file

@ -35,9 +35,11 @@ class AllSetting {
this.subUpdates = 0; this.subUpdates = 0;
this.subEncrypt = true; this.subEncrypt = true;
this.subShowInfo = false; this.subShowInfo = false;
this.subURI = ''; this.subURI = "";
this.subJsonURI = ''; this.subJsonURI = "";
this.subJsonFragment = ''; this.subJsonFragment = "";
this.subJsonMux = "";
this.subJsonRules = "";
this.timeLocation = "Asia/Tehran"; this.timeLocation = "Asia/Tehran";

View file

@ -52,6 +52,8 @@ type AllSetting struct {
SubJsonPath string `json:"subJsonPath" form:"subJsonPath"` SubJsonPath string `json:"subJsonPath" form:"subJsonPath"`
SubJsonURI string `json:"subJsonURI" form:"subJsonURI"` SubJsonURI string `json:"subJsonURI" form:"subJsonURI"`
SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"` SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"`
SubJsonMux string `json:"subJsonMux" form:"subJsonMux"`
SubJsonRules string `json:"subJsonRules" form:"subJsonRules"`
Datepicker string `json:"datepicker" form:"datepicker"` Datepicker string `json:"datepicker" form:"datepicker"`
} }

View file

@ -295,6 +295,8 @@
<setting-list-item type="text" title='{{ i18n "pages.settings.subPath"}}' desc='{{ i18n "pages.settings.subPathDesc"}}' v-model="allSetting.subJsonPath"></setting-list-item> <setting-list-item type="text" title='{{ i18n "pages.settings.subPath"}}' desc='{{ i18n "pages.settings.subPathDesc"}}' v-model="allSetting.subJsonPath"></setting-list-item>
<setting-list-item type="text" title='{{ i18n "pages.settings.subURI"}}' desc='{{ i18n "pages.settings.subURIDesc"}}' v-model="allSetting.subJsonURI" placeholder="(http|https)://domain[:port]/path/"></setting-list-item> <setting-list-item type="text" title='{{ i18n "pages.settings.subURI"}}' desc='{{ i18n "pages.settings.subURIDesc"}}' v-model="allSetting.subJsonURI" placeholder="(http|https)://domain[:port]/path/"></setting-list-item>
<setting-list-item type="switch" title='{{ i18n "pages.settings.fragment"}}' desc='{{ i18n "pages.settings.fragmentDesc"}}' v-model="fragment"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.settings.fragment"}}' desc='{{ i18n "pages.settings.fragmentDesc"}}' v-model="fragment"></setting-list-item>
<setting-list-item type="switch" title='Mux' v-model="enableMux"></setting-list-item>
<setting-list-item type="switch" title='{{ i18n "pages.xray.directCountryConfigs"}}' desc='{{ i18n "pages.xray.directCountryConfigsDesc"}}' v-model="enableDirect"></setting-list-item>
</a-list> </a-list>
<a-collapse v-if="fragment"> <a-collapse v-if="fragment">
<a-collapse-panel header='{{ i18n "pages.settings.fragment"}}'> <a-collapse-panel header='{{ i18n "pages.settings.fragment"}}'>
@ -318,6 +320,36 @@
<setting-list-item type="text" title='Length' v-model="fragmentLength" placeholder="100-200"></setting-list-item> <setting-list-item type="text" title='Length' v-model="fragmentLength" placeholder="100-200"></setting-list-item>
<setting-list-item type="text" title='Interval' v-model="fragmentInterval" placeholder="10-20"></setting-list-item> <setting-list-item type="text" title='Interval' v-model="fragmentInterval" placeholder="10-20"></setting-list-item>
</a-collapse-panel> </a-collapse-panel>
<a-collapse-panel header='Mux' v-if="enableMux">
<setting-list-item type="number" title='Concurrency' v-model="muxConcurrency" :min="-1" :max="1024"></setting-list-item>
<setting-list-item type="number" title='xudp Concurrency' v-model="muxXudpConcurrency" :min="-1" :max="1024"></setting-list-item>
<a-list-item style="padding: 20px">
<a-row>
<a-col :lg="24" :xl="12">
<a-list-item-meta title='xudp UDP 443'/>
</a-col>
<a-col :lg="24" :xl="12">
<a-select
v-model="muxXudpProxyUDP443"
style="width: 100%"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option :value="p" :label="p" v-for="p in ['reject', 'allow', 'skip']">
[[ p ]]
</a-select-option>
</a-select>
</a-col>
</a-row>
</a-list-item>
</a-collapse-panel>
<a-collapse-panel header='{{ i18n "pages.xray.directCountryConfigs"}}' v-if="enableDirect">
<a-list-item style="padding: 20px">
<a-checkbox-group
v-model="directCountries"
name="Countries"
:options="countryOptions"
/>
</a-list-item>
</a-collapse-panel>
</a-collapse> </a-collapse>
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
@ -367,6 +399,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() { get remarkModel() {
rm = this.allSetting.remarkModel; rm = this.allSetting.remarkModel;
return rm.length>1 ? rm.substring(1).split('') : []; return rm.length>1 ? rm.substring(1).split('') : [];
@ -530,6 +596,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: { confAlerts: {
get: function() { get: function() {
if (!this.allSetting) return []; if (!this.allSetting) return [];

View file

@ -61,6 +61,8 @@ var defaultValueMap = map[string]string{
"subJsonPath": "/json/", "subJsonPath": "/json/",
"subJsonURI": "", "subJsonURI": "",
"subJsonFragment": "", "subJsonFragment": "",
"subJsonMux": "",
"subJsonRules": "",
"datepicker": "gregorian", "datepicker": "gregorian",
"warp": "", "warp": "",
} }
@ -437,6 +439,14 @@ func (s *SettingService) GetSubJsonFragment() (string, error) {
return s.getString("subJsonFragment") 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) GetDatepicker() (string, error) { func (s *SettingService) GetDatepicker() (string, error) {
return s.getString("datepicker") return s.getString("datepicker")
} }