update 2024-11-06 00:26:14

This commit is contained in:
kenzok8 2024-11-06 00:26:14 +08:00
parent 371d3c520b
commit 7b70cb2bf5
12 changed files with 334 additions and 130 deletions

View File

@ -23,6 +23,7 @@ define Package/luci-app-fchomo/conffiles
/etc/fchomo/resources.json
/etc/fchomo/geoip.dat
/etc/fchomo/geosite.dat
/etc/fchomo/asn.mmdb
/etc/fchomo/cache.db
endef

View File

@ -132,11 +132,11 @@ return baseclass.extend({
['IP-CIDR'],
['IP-CIDR6'],
['IP-SUFFIX'],
//['IP-ASN'],
['IP-ASN'],
['GEOIP'],
['SRC-GEOIP'],
//['SRC-IP-ASN'],
['SRC-IP-ASN'],
['SRC-IP-CIDR'],
['SRC-IP-SUFFIX'],
@ -158,6 +158,8 @@ return baseclass.extend({
//['DSCP'],
['RULE-SET'],
['MATCH']
],
rules_logical_type: [
@ -447,6 +449,23 @@ return baseclass.extend({
return this.super('load', section_id);
},
loadSubRuleGroup: function(section_id) {
delete this.keylist;
delete this.vallist;
this.value('', _('-- Please choose --'));
let groups = {};
uci.sections(this.config, 'subrules', (res) => {
if (res.enabled !== '0')
groups[res.group] = res.group;
});
Object.keys(groups).forEach((group) => {
this.value(group, group);
});
return this.super('load', section_id);
},
renderStatus: function(self, ElId, isRunning, instance, noGlobal) {
var visible = isRunning && (isRunning.http || isRunning.https);

View File

@ -66,7 +66,20 @@ class DNSAddress {
class RulesEntry {
constructor(entry) {
this.input = entry || '';
this.rawparams = this.input.split(',');
var content = this.input;
this.subrule = content.split(',');
if (this.subrule.shift() === 'SUB-RULE') {
var subrule_payload = this.subrule.join(',').match(/^\(.*\)/);
if (subrule_payload) {
content = subrule_payload[0].slice(1, -1);
this.subrule = this.subrule.pop() || ' ';
} else {
content = this.subrule.join(',');
this.subrule = ' ';
}
} else
this.subrule = false;
this.rawparams = content.split(',');
this.type = this.rawparams.shift() || '';
var logical_payload, rawfactor;
(function(rawparams_typecuted) {
@ -78,6 +91,8 @@ class RulesEntry {
rawfactor = this.rawparams.shift() || '';
}.call(this, this.rawparams.join(',')));
this.detour = this.rawparams.shift() || '';
if (this.type === 'MATCH')
this.detour = rawfactor;
this.payload = [];
if (logical_payload) { // ႇ ❟
@ -144,9 +159,15 @@ class RulesEntry {
} else
factor = this.payload[0].factor;
return [this.type, factor, this.detour].concat(
['no-resolve', 'src'].filter(k => this.params[k])
).join(',');
if (this.subrule) {
return 'SUB-RULE,(%s),%s'.format([this.type, factor].join(','), this.subrule);
} else
if (this.type === 'MATCH') {
return [this.type, this.detour].join(',');
} else
return [this.type, factor, this.detour].concat(
['no-resolve', 'src'].filter(k => this.params[k])
).join(',');
}
}
@ -223,18 +244,23 @@ function renderPayload(s, total, uciconfig) {
if (n === 0) {
o.depends({type: /\bDOMAIN\b/});
o.depends({type: /\bGEO(SITE|IP)\b/});
o.depends({type: /\bASN\b/});
o.depends({type: /\bPROCESS\b/});
}
o.depends(Object.fromEntries([[prefix + 'type', /\bDOMAIN\b/]]));
o.depends(Object.fromEntries([[prefix + 'type', /\bGEO(SITE|IP)\b/]]));
o.depends(Object.fromEntries([[prefix + 'type', /\bASN\b/]]));
o.depends(Object.fromEntries([[prefix + 'type', /\bPROCESS\b/]]));
initPayload(o, n, 'factor', uciconfig);
o = s.option(form.Value, prefix + 'ip', _('Factor') + ` ${n+1}`);
o.datatype = 'cidr';
if (n === 0)
o.depends({type: /\bIP\b/});
o.depends(Object.fromEntries([[prefix + 'type', /\bIP\b/]]));
if (n === 0) {
o.depends({type: /\b(CIDR|CIDR6)\b/});
o.depends({type: /\bIP-SUFFIX\b/});
}
o.depends(Object.fromEntries([[prefix + 'type', /\b(CIDR|CIDR6)\b/]]));
o.depends(Object.fromEntries([[prefix + 'type', /\bIP-SUFFIX\b/]]));
initPayload(o, n, 'factor', uciconfig);
o = s.option(form.Value, prefix + 'port', _('Factor') + ` ${n+1}`);
@ -266,6 +292,118 @@ function renderPayload(s, total, uciconfig) {
}
}
function renderRules(s, uciconfig) {
var o;
o = s.option(form.DummyValue, 'entry', _('Entry'));
o.load = function(section_id) {
return form.DummyValue.prototype.load.call(this, section_id) || '%s,%s,%s'.format(hm.rules_type[0][0], '', hm.preset_outbound.full[0][0]);
}
o.write = L.bind(form.AbstractValue.prototype.write, o);
o.remove = L.bind(form.AbstractValue.prototype.remove, o);
o.editable = true;
o = s.option(form.ListValue, 'type', _('Type'));
o.default = hm.rules_type[0][0];
[...hm.rules_type, ...hm.rules_logical_type].forEach((res) => {
o.value.apply(o, res);
})
o.load = function(section_id) {
return new RulesEntry(uci.get(uciconfig, section_id, 'entry')).type;
}
o.validate = function(section_id, value) {
// params only available for types other than
// https://github.com/muink/mihomo/blob/43f21c0b412b7a8701fe7a2ea6510c5b985a53d6/config/config.go#L1050
// https://github.com/muink/mihomo/blob/43f21c0b412b7a8701fe7a2ea6510c5b985a53d6/rules/parser.go#L12
if (['GEOIP', 'IP-ASN', 'IP-CIDR', 'IP-CIDR6', 'IP-SUFFIX', 'RULE-SET'].includes(value)) {
['no-resolve', 'src'].forEach((opt) => {
let UIEl = this.section.getUIElement(section_id, opt);
UIEl.node.querySelector('input').disabled = null;
});
} else {
['no-resolve', 'src'].forEach((opt) => {
let UIEl = this.section.getUIElement(section_id, opt);
UIEl.setValue('');
UIEl.node.querySelector('input').disabled = 'true';
});
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setParam('no-resolve').setParam('src').toString();
UIEl.node.previousSibling.innerText = newvalue;
UIEl.setValue(newvalue);
}
return true;
}
o.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setKey('type', value).toString();
UIEl.node.previousSibling.innerText = newvalue;
return UIEl.setValue(newvalue);
}
o.write = function() {};
o.rmempty = false;
o.modalonly = true;
renderPayload(s, Math.max(...Object.values(hm.rules_logical_payload_count)), uciconfig);
o = s.option(form.ListValue, 'detour', _('Proxy group'));
o.load = function(section_id) {
hm.loadProxyGroupLabel.call(this, hm.preset_outbound.full, section_id);
return new RulesEntry(uci.get(uciconfig, section_id, 'entry')).detour;
}
o.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setKey('detour', value).toString();
UIEl.node.previousSibling.innerText = newvalue;
return UIEl.setValue(newvalue);
}
o.write = function() {};
//o.depends('SUB-RULE', '0');
o.editable = true;
o = s.option(form.Flag, 'src', _('src'));
o.default = o.disabled;
o.load = function(section_id) {
return strToFlag(new RulesEntry(uci.get(uciconfig, section_id, 'entry')).getParam('src'));
}
o.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setParam('src', flagToStr(value)).toString();
UIEl.node.previousSibling.innerText = newvalue;
UIEl.setValue(newvalue);
}
o.write = function() {};
o.depends('SUB-RULE', '0');
o.modalonly = true;
o = s.option(form.Flag, 'no-resolve', _('no-resolve'));
o.default = o.disabled;
o.load = function(section_id) {
return strToFlag(new RulesEntry(uci.get(uciconfig, section_id, 'entry')).getParam('no-resolve'));
}
o.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setParam('no-resolve', flagToStr(value)).toString();
UIEl.node.previousSibling.innerText = newvalue;
UIEl.setValue(newvalue);
}
o.write = function() {};
o.depends('SUB-RULE', '0');
o.modalonly = true;
}
return view.extend({
load: function() {
return Promise.all([
@ -306,8 +444,8 @@ return view.extend({
o.inputstyle = 'apply';
o.onclick = L.bind(hm.handleReload, o, 'mihomo-c');
o = s.taboption('group', form.ListValue, 'default_proxy', _('Default outbound'));
o.load = L.bind(hm.loadProxyGroupLabel, o, hm.preset_outbound.direct);
o = s.taboption('group', form.Flag, 'client_enabled', _('Enable'));
o.default = o.disabled;
/* Proxy Group */
o = s.taboption('group', form.SectionValue, '_group', form.GridSection, 'proxy_group', null);
@ -521,112 +659,85 @@ return view.extend({
so.default = so.enabled;
so.editable = true;
so = ss.option(form.DummyValue, 'entry', _('Entry'));
so.load = function(section_id) {
return form.DummyValue.prototype.load.call(this, section_id) || '%s,%s,%s'.format(hm.rules_type[0][0], '', hm.preset_outbound.full[0][0]);
}
so.write = L.bind(form.AbstractValue.prototype.write, so);
so.remove = L.bind(form.AbstractValue.prototype.remove, so);
so.editable = true;
renderRules(ss, data[0]);
so = ss.option(form.ListValue, 'type', _('Type'));
so.default = hm.rules_type[0][0];
[...hm.rules_type, ...hm.rules_logical_type].forEach((res) => {
so.value.apply(so, res);
})
so = ss.option(form.Flag, 'SUB-RULE', _('SUB-RULE'));
so.default = so.disabled;
so.load = function(section_id) {
return new RulesEntry(uci.get(data[0], section_id, 'entry')).type;
return strToFlag(new RulesEntry(uci.get(data[0], section_id, 'entry')).subrule ? 'true' : 'false');
}
so.validate = function(section_id, value) {
// params only available for types other than
// https://github.com/muink/mihomo/blob/43f21c0b412b7a8701fe7a2ea6510c5b985a53d6/config/config.go#L1050
// https://github.com/muink/mihomo/blob/43f21c0b412b7a8701fe7a2ea6510c5b985a53d6/rules/parser.go#L12
if (['GEOIP', 'IP-ASN', 'IP-CIDR', 'IP-CIDR6', 'IP-SUFFIX', 'RULE-SET'].includes(value)) {
this.section.getUIElement(section_id, 'no-resolve').node.querySelector('input').disabled = null;
this.section.getUIElement(section_id, 'src').node.querySelector('input').disabled = null;
} else {
var UIEl = this.section.getUIElement(section_id, 'entry');
value = this.formvalue(section_id);
var newvalue = new RulesEntry(UIEl.getValue()).setParam('no-resolve').setParam('src').toString();
UIEl.node.previousSibling.innerText = newvalue;
UIEl.setValue(newvalue);
['no-resolve', 'src'].forEach((opt) => {
let UIEl = this.section.getUIElement(section_id, opt);
UIEl.setValue('');
UIEl.node.querySelector('input').disabled = 'true';
});
}
this.section.getUIElement(section_id, 'detour').node.querySelector('select').disabled = (value === '1') ? 'true' : null;
return true;
}
so.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setKey('type', value).toString();
var newvalue = new RulesEntry(UIEl.getValue()).setKey('subrule', value === '1' ? ' ' : false).toString();
UIEl.node.previousSibling.innerText = newvalue;
return UIEl.setValue(newvalue);
}
so.write = function() {};
so.modalonly = true;
so = ss.option(form.ListValue, 'sub_rule', _('Sub rule'));
so.load = function(section_id) {
hm.loadSubRuleGroup.call(this, section_id);
return new RulesEntry(uci.get(data[0], section_id, 'entry')).subrule || '';
}
so.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setKey('subrule', value).toString();
UIEl.node.previousSibling.innerText = newvalue;
return UIEl.setValue(newvalue);
}
so.rmempty = false;
so.modalonly = true;
renderPayload(ss, Math.max(...Object.values(hm.rules_logical_payload_count)), data[0]);
// dev: Features under development
// SUB-RULE
so = ss.option(form.ListValue, 'detour', _('Proxy group'));
so.load = function(section_id) {
hm.loadProxyGroupLabel.call(this, hm.preset_outbound.full, section_id);
return new RulesEntry(uci.get(data[0], section_id, 'entry')).detour;
}
so.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setKey('detour', value).toString();
UIEl.node.previousSibling.innerText = newvalue;
return UIEl.setValue(newvalue);
}
so.write = function() {};
so.editable = true;
so = ss.option(form.Flag, 'src', _('src'));
so.default = so.disabled;
so.load = function(section_id) {
return strToFlag(new RulesEntry(uci.get(data[0], section_id, 'entry')).getParam('src'));
}
so.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setParam('src', flagToStr(value)).toString();
UIEl.node.previousSibling.innerText = newvalue;
UIEl.setValue(newvalue);
}
so.write = function() {};
so.modalonly = true;
so = ss.option(form.Flag, 'no-resolve', _('no-resolve'));
so.default = so.disabled;
so.load = function(section_id) {
return strToFlag(new RulesEntry(uci.get(data[0], section_id, 'entry')).getParam('no-resolve'));
}
so.onchange = function(ev, section_id, value) {
var UIEl = this.section.getUIElement(section_id, 'entry');
var newvalue = new RulesEntry(UIEl.getValue()).setParam('no-resolve', flagToStr(value)).toString();
UIEl.node.previousSibling.innerText = newvalue;
UIEl.setValue(newvalue);
}
so.write = function() {};
so.depends('SUB-RULE', '1');
so.modalonly = true;
/* Routing rules END */
/* Sub rules START */
s.tab('subrules', _('Sub rule'));
/* Sub rules */
o = s.taboption('subrules', form.SectionValue, '_subrules', form.GridSection, 'subrules', null);
ss = o.subsection;
var prefmt = { 'prefix': '', 'suffix': '_subhost' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('Sub rule'), _('Add a sub rule'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, false);
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
so = ss.option(form.Value, 'label', _('Label'));
so.load = L.bind(hm.loadDefaultLabel, so);
so.validate = L.bind(hm.validateUniqueValue, so);
so.modalonly = true;
so = ss.option(form.Flag, 'enabled', _('Enable'));
so.default = so.enabled;
so.editable = true;
so = ss.option(form.Value, 'group', _('Sub rule group'));
so.value('sub-rule1');
so.rmempty = false;
so.validate = L.bind(hm.validateAuthUsername, so);
so.editable = true;
renderRules(ss, data[0]);
/* Sub rules END */
/* DNS settings START */
s.tab('dns', _('DNS settings'));

View File

@ -259,6 +259,9 @@ return view.extend({
so = ss.option(form.DummyValue, '_geosite_version', _('GeoSite version'));
so.cfgvalue = function() { return renderResVersion.call(this, null, 'geosite') };
so = ss.option(form.DummyValue, '_asn_version', _('ASN version'));
so.cfgvalue = function() { return renderResVersion.call(this, null, 'asn') };
so = ss.option(form.DummyValue, '_china_ip4_version', _('China IPv4 list version'));
so.cfgvalue = function() { return renderResVersion.call(this, null, 'china_ip4') };

View File

@ -76,6 +76,10 @@ msgstr "API TLS 私钥"
msgid "API secret"
msgstr "API 令牌"
#: htdocs/luci-static/resources/view/fchomo/global.js:262
msgid "ASN version"
msgstr "ASN 版本"
#: htdocs/luci-static/resources/view/fchomo/global.js:562
#: htdocs/luci-static/resources/view/fchomo/global.js:612
msgid "Access Control"
@ -93,6 +97,10 @@ msgstr "新增 DNS 服务器"
msgid "Add a Node"
msgstr "新增 节点"
#: htdocs/luci-static/resources/view/fchomo/client.js:717
msgid "Add a sub rule"
msgstr "新增 子规则"
#: htdocs/luci-static/resources/view/fchomo/node.js:67
msgid "Add a provider"
msgstr "新增 供应商"
@ -1519,6 +1527,18 @@ msgstr "堆栈"
msgid "Strategy"
msgstr "策略"
#: htdocs/luci-static/resources/view/fchomo/client.js:646
msgid "SUB-RULE"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/client.js:664
msgid "Sub rule"
msgstr "子规则"
#: htdocs/luci-static/resources/view/fchomo/client.js:731
msgid "Sub rule group"
msgstr "子规则组"
#: htdocs/luci-static/resources/view/fchomo/ruleset.js:140
msgid "Successfully imported %s rule-set of total %s."
msgstr "已成功导入 %s 个规则集 (共 %s 个)。"

View File

@ -77,8 +77,8 @@
const dnsmasq_hijacked = uci.get('dhcp', '@dnsmasq[0]', 'dns_redirect') || '0',
dnsmasq_port = uci.get('dhcp', '@dnsmasq[0]', 'port') || '53';
let default_proxy, routing_tcpport, routing_udpport, routing_mode, routing_domain;
default_proxy = uci.get(cfgname, 'routing', 'default_proxy') || null,
let client_enabled, routing_tcpport, routing_udpport, routing_mode, routing_domain;
client_enabled = uci.get(cfgname, 'routing', 'client_enabled') || '0',
routing_tcpport = uci.get(cfgname, 'routing', 'routing_tcpport') || null;
routing_udpport = uci.get(cfgname, 'routing', 'routing_udpport') || null;
routing_mode = uci.get(cfgname, 'routing', 'routing_mode') || null;

View File

@ -8,11 +8,11 @@
uci.load(cfgname);
const proxy_mode = uci.get(cfgname, 'inbound', 'proxy_mode') || 'redir_tproxy';
let default_proxy, tun_name;
let client_enabled, tun_name;
if (match(proxy_mode, /tun/)) {
default_proxy = uci.get(cfgname, 'routing', 'default_proxy') || null;
client_enabled = uci.get(cfgname, 'routing', 'client_enabled') || '0';
if (default_proxy)
if (client_enabled === '1')
tun_name = uci.get(cfgname, 'config', 'tun_name') || 'hmtun0';
}
-%}

View File

@ -40,7 +40,8 @@ const ucisniff = 'sniff',
ucipgrp = 'proxy_group',
uciprov = 'provider',
ucirule = 'ruleset',
ucirout = 'rules';
ucirout = 'rules',
ucisubro = 'subrules';
/* Hardcode options */
const common_tcpport = uci.get(uciconf, ucifchm, 'common_tcpport') || '20-21,22,53,80,110,143,443,465,853,873,993,995,8080,8443,9418',
@ -68,7 +69,7 @@ const listen_interfaces = uci.get(uciconf, uciroute, 'listen_interfaces') || nul
lan_proxy_ipv6_ips = uci.get(uciconf, uciroute, 'lan_proxy_ipv6_ips') || null,
lan_proxy_mac_addrs = uci.get(uciconf, uciroute, 'lan_proxy_mac_addrs') || null,
proxy_router = (uci.get(uciconf, uciroute, 'proxy_router') === '0') ? null : true,
default_proxy = uci.get(uciconf, uciroute, 'default_proxy') || null,
client_enabled = uci.get(uciconf, uciroute, 'client_enabled') || '0',
routing_tcpport = uci.get(uciconf, uciroute, 'routing_tcpport') || null,
routing_udpport = uci.get(uciconf, uciroute, 'routing_udpport') || null,
routing_mode = uci.get(uciconf, uciroute, 'routing_mode') || null,
@ -154,6 +155,24 @@ function get_nameserver(cfg, detour) {
return servers;
}
function parse_entry(cfg) {
if (isEmpty(cfg))
return null;
let arr = split(cfg, ',');
if (arr[0] === 'MATCH') {
arr[1] = get_proxygroup(arr[1]);
} else if (arr[0] === 'SUB-RULE') {
arr[1] = replace(arr[1], /|/g, ','); // U+A4F9 | U+201A
arr[2] = replace(arr[2], /|/g, ','); // U+A4F9 | U+201A
} else {
arr[1] = replace(arr[1], /|/g, ','); // U+A4F9 | U+201A
arr[2] = get_proxygroup(arr[2]);
}
return join(',', arr);
}
/* Config helper END */
/* Main */
@ -529,14 +548,21 @@ uci.foreach(uciconf, ucirout, (cfg) => {
if (cfg.enabled === '0')
return null;
push(config.rules, function(arr) {
arr[1] = replace(arr[1], /|/g, ','); // U+A4F9 | U+201A
arr[2] = get_proxygroup(arr[2]);
return join(',', arr);
}(split(cfg.entry, ','))
);
push(config.rules, parse_entry(cfg.entry));
});
push(config.rules, 'MATCH,' + get_proxygroup(default_proxy));
/* Routing rules END */
/* Sub rules START */
/* Sub rules */
config["sub-rules"] = {};
uci.foreach(uciconf, ucisubro, (cfg) => {
if (cfg.enabled === '0')
return null;
if (!config["sub-rules"][cfg.group])
config["sub-rules"][cfg.group] = [];
push(config["sub-rules"][cfg.group], parse_entry(cfg.entry));
});
/* Sub rules END */
printf('%.J\n', removeBlankAttrs(config));

View File

@ -210,7 +210,7 @@ check_list_update() {
case "$1" in
"ALL")
# Since the VER_PATH lock is not designed, parallelism is not currently supported.
for _type in geoip geosite china_ip4 china_ip6 gfw_list china_list; do
for _type in geoip geosite asn china_ip4 china_ip6 gfw_list china_list; do
"$0" "$_type"
done
# dashboard
@ -232,6 +232,10 @@ case "$1" in
"geosite")
check_geodata_update "$1" "Loyalsoldier/v2ray-rules-dat"
;;
"asn")
check_list_update "$1" "Loyalsoldier/geoip" "release" "GeoLite2-ASN.mmdb" &&
mv -f "$RESOURCES_DIR/asn.mmdb" "$RESOURCES_DIR/../asn.mmdb"
;;
"china_ip4")
check_list_update "$1" "muink/route-list" "release" "china_ipv4.txt"
;;
@ -245,7 +249,7 @@ case "$1" in
check_list_update "$1" "muink/route-list" "release" "china_list2.txt"
;;
*)
echo -e "Usage: $0 <ALL / dashboard / geoip / geosite / china_ip4 / china_ip6 / gfw_list / china_list>"
echo -e "Usage: $0 <ALL / dashboard / geoip / geosite / asn / china_ip4 / china_ip6 / gfw_list / china_list>"
exit 1
;;
esac

View File

@ -70,19 +70,19 @@ log() {
}
start_service() {
local default_proxy server_enabled server_auto_firewall
config_get default_proxy "routing" "default_proxy" ""
local client_enabled server_enabled server_auto_firewall
config_get client_enabled "routing" "client_enabled" "0"
config_get_bool server_enabled "routing" "server_enabled" "0"
config_get_bool server_auto_firewall "routing" "server_auto_firewall" "0"
if [ -z "$default_proxy" -a "$server_enabled" = "0" ]; then
if [ "$client_enabled" = "0" -a "$server_enabled" = "0" ]; then
return 1
fi
mkdir -p "$RUN_DIR"
# Client
if [ -n "$default_proxy" ]; then
if [ "$client_enabled" = "1" ]; then
if [ -z "$1" -o "$1" = "mihomo-c" ]; then
# Generate/Validate client config
ucode -S "$HM_DIR/scripts/generate_client.uc" 2>>"$LOG_PATH" | yq -Poy | yq \
@ -317,7 +317,7 @@ start_service() {
# Setup firewall
utpl -S "$HM_DIR/scripts/firewall_pre.ut" > "$RUN_DIR/fchomo_pre.nft"
# Setup Nftables rules
if [ -n "$default_proxy" ]; then
if [ "$client_enabled" = "1" ]; then
[ -z "$1" -o "$1" = "mihomo-c" ] && utpl -S "$HM_DIR/scripts/firewall_post.ut" > "$RUN_DIR/fchomo_post.nft"
fi
fw4 reload >"/dev/null" 2>&1

View File

@ -0,0 +1,15 @@
#!/bin/sh
default_proxy=$(uci -q get fchomo.routing.default_proxy)
if [ -n "$default_proxy" ]; then
uci -q batch <<-EOF >"/dev/null"
delete fchomo.routing.default_proxy
set fchomo.routing.client_enabled="1"
set fchomo.autogened_final_host="rules"
set fchomo.autogened_final_host.label="Auto Generated Final"
set fchomo.autogened_final_host.entry="MATCH,$default_proxy"
commit fchomo
EOF
fi
exit 0

View File

@ -8,8 +8,8 @@ USE_PROCD=1
. "$IPKG_INSTROOT/etc/mihomo/scripts/constants.sh"
boot() {
# init log
init_log
# prepare log
prepare_log
# load config
config_load mihomo
# start delay
@ -25,8 +25,8 @@ boot() {
}
start_service() {
# clear log
clear_log
# prepare log
prepare_log
# load config
config_load mihomo
# check if enabled
@ -480,15 +480,20 @@ cleanup() {
/etc/init.d/cron restart
}
init_log() {
mkdir "$LOG_DIR"
touch "$APP_LOG_PATH"
touch "$CORE_LOG_PATH"
}
clear_log() {
echo -n > "$APP_LOG_PATH"
echo -n > "$CORE_LOG_PATH"
prepare_log() {
if [ ! -d "$LOG_DIR" ]; then
mkdir -p "$LOG_DIR"
fi
if [ ! -f "$APP_LOG_PATH" ]; then
touch "$APP_LOG_PATH"
else
echo -n > "$APP_LOG_PATH"
fi
if [ ! -f "$CORE_LOG_PATH" ]; then
touch "$CORE_LOG_PATH"
else
echo -n > "$CORE_LOG_PATH"
fi
}
log() {