🎉 Sync 2026-08-04 00:17:08

This commit is contained in:
github-actions[bot] committed 2026-08-04 00:17:08 +08:00
1 parent 6e23f4416b
commit e03a23fe6b
18 files changed
+352 -171

No files matched your search

+3 -3
View File
@@ -5,10 +5,10 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dae
PKG_VERSION:=2026.08.02
PKG_RELEASE:=29
PKG_VERSION:=2026.08.03
PKG_RELEASE:=30
PKG_SOURCE:=dae-src-2026.08.02-82d4db4266d3.tar.gz
PKG_SOURCE:=dae-src-2026.08.03-354bb6787b4e.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=skip
+3 -3
View File
@@ -5,10 +5,10 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=daed
PKG_VERSION:=2026.08.02
PKG_RELEASE:=39
PKG_VERSION:=2026.08.03
PKG_RELEASE:=40
PKG_SOURCE:=daed-src-2026.08.02-9233e4ccf701.tar.gz
PKG_SOURCE:=daed-src-2026.08.03-5f7939adc12a.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=skip
+1
View File
@@ -64,6 +64,7 @@ endef
define Package/luci-app-fchomo/prerm
#!/bin/sh
/etc/init.d/fchomo stop 2>/dev/null
uci delete firewall.fchomo_pre
uci delete firewall.fchomo_post
uci commit firewall
@@ -204,8 +204,8 @@ const outbound_type = [
['hysteria2', _('Hysteria2') + ' - ' + _('UDP')],
['shadowquic', _('ShadowQUIC') + ' - ' + _('UDP')],
['trusttunnel', _('TrustTunnel') + ' - ' + _('TCP/UDP')],
['wireguard', _('WireGuard') + ' - ' + _('UDP')],
['masque', _('Masque') + ' - ' + _('UDP')], // https://blog.cloudflare.com/post-quantum-warp/
['wireguard', _('WireGuard') + ' - ' + _('UDP')], // Endpoint
['masque', _('Masque') + ' - ' + _('UDP')], // Endpoint // https://blog.cloudflare.com/post-quantum-warp/
['ssh', _('SSH') + ' - ' + _('TCP')]
];
@@ -1806,7 +1806,7 @@ function validateCommonPort(section_id, value) {
for (let custom of arr) {
if (!routing_port_type.map(e => e[0]).includes(custom)) {
let ports = [];
for (let i of custom.split(',')) {
for (let i of custom.split(this.hm_separator ?? ',')) {
if (!stubValidator.apply('port', i) && !stubValidator.apply('portrange', i))
return _('Expecting: %s').format(_('valid port value'));
if (ports.includes(i))
@@ -151,11 +151,11 @@ function renderListeners(s, uciconfig, isClient) {
o.placeholder = '::';
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'port', _('Listen port') + ' / ' + _('Ports pool'));
o.datatype = 'or(port, portrange)';
//o.placeholder = '1080,2079-2080,3080'; // @fw4 does not support port lists with commas
o = s.taboption('field_general', form.Value, 'listen_port', _('Listen port') + ' / ' + _('Ports pool'));
//o.datatype = 'or(port, portrange)'; // ⬇️ migrated to validate
o.placeholder = '1080,2079-2080,3080';
o.rmempty = false;
//o.validate = hm.validateCommonPort; // @fw4 does not support port lists with commas
o.validate = hm.validateCommonPort;
/* HTTP / SOCKS fields */
/* hm.validateAuth */
@@ -595,11 +595,23 @@ function renderPayload(s, total, uciconfig) {
initPayload(o, n, 'factor', uciconfig);
o = s.option(form.Value, prefix + 'port', _('Factor') + ` ${n+1}`);
o.datatype = 'or(port, portrange)';
//o.datatype = 'or(port, portrange)'; // ⬇️ migrated to validate
o.placeholder = '1080/2079-2080/3080';
if (n === 0)
o.depends({type: /\bPORT\b/});
o.depends(Object.fromEntries([[prefix + 'type', /\bPORT\b/]]));
initPayload(o, n, 'factor', uciconfig);
// if validate is already defined in initPayload
const port_old_validate = o.validate;
o.validate = function(section_id, value) {
const result = port_old_validate.apply(this, arguments);
if (result === true) {
this.hm_separator = '/';
return hm.validateCommonPort.apply(this, arguments);
}
return result;
}
o = s.option(form.ListValue, prefix + 'l4', _('Factor') + ` ${n+1}`);
o.value('udp', _('UDP'));
@@ -1919,7 +1931,7 @@ return view.extend({
_('Lazy query.'));
so.default = so.disabled;
so.validate = function(section_id, value) {
let desc = this.getUIElement(section_id).node.nextSibling;
const desc = this.getUIElement(section_id).node.nextSibling;
value = this.formvalue(section_id);
if (value == 1)
@@ -823,7 +823,7 @@ return view.extend({
_('As the TOP upstream of dnsmasq.'));
so.default = so.disabled;
so.validate = function(section_id, value) {
let desc = this.getUIElement(section_id).node.nextSibling;
const desc = this.getUIElement(section_id).node.nextSibling;
value = this.formvalue(section_id);
if (value == 1)
@@ -238,6 +238,7 @@ return view.extend({
ss.tab('field_vless_encryption', _('Vless Encryption fields'));
ss.tab('field_hysteria2_realm', _('Hysteria2 Realm fields'));
ss.tab('field_tls', _('TLS fields'));
ss.tab('field_vpn', _('VPN fields'));
ss.tab('field_transport', _('Transport fields'));
ss.tab('field_multiplex', _('Multiplex fields'));
ss.tab('field_dial', _('Dial fields'));
@@ -782,20 +783,6 @@ return view.extend({
so.modalonly = true;
/* WireGuard fields */
so = ss.taboption('field_general', form.Value, 'wireguard_ip', _('Local address'),
_('The %s address used by local machine in the Wireguard network.').format('IPv4'));
so.datatype = 'ip4addr(1)';
so.placeholder = '172.16.0.2';
so.rmempty = false;
so.depends('type', 'wireguard');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'wireguard_ipv6', _('Local IPv6 address'),
_('The %s address used by local machine in the Wireguard network.').format('IPv6'));
so.datatype = 'ip6addr(1)';
so.depends('type', 'wireguard');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'wireguard_private_key', _('Private key'),
_('WireGuard requires base64-encoded private keys.'));
so.password = true;
@@ -804,7 +791,7 @@ return view.extend({
so.depends('type', 'wireguard');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'wireguard_peer_public_key', _('Peer pubkic key'),
so = ss.taboption('field_general', form.Value, 'wireguard_peer_public_key', _('Peer public key'),
_('WireGuard peer public key.'));
so.validate = L.bind(hm.validateBase64Key, so, 44);
so.rmempty = false;
@@ -836,23 +823,6 @@ return view.extend({
so.depends('type', 'wireguard');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'wireguard_mtu', _('MTU'));
so.datatype = 'range(0,9000)';
so.placeholder = '1408';
so.depends('type', 'wireguard');
so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'wireguard_remote_dns_resolve', _('Remote DNS resolve'),
_('Force DNS remote resolution.'));
so.default = so.disabled;
so.depends('type', 'wireguard');
so.modalonly = true;
so = ss.taboption('field_general', form.DynamicList, 'wireguard_dns', _('DNS server'));
so.datatype = 'or(host, hostport)';
so.depends('wireguard_remote_dns_resolve', '1');
so.modalonly = true;
/* Masque fields */
so = ss.taboption('field_general', form.Value, 'masque_private_key', _('Private key'),
_('Base64 encoded ECDSA private key on the NIST P-256 curve.'));
@@ -862,33 +832,13 @@ return view.extend({
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_endpoint_public_key', _('Endpoint pubkic key'),
so = ss.taboption('field_general', form.Value, 'masque_endpoint_public_key', _('Endpoint public key'),
_('Base64 encoded ECDSA public key on the NIST P-256 curve.'));
so.validate = L.bind(hm.validateBase64Key, so, 124);
so.rmempty = false;
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_ip', _('Local address'),
_('The %s address used by local machine in the Cloudflare WARP network.').format('IPv4'));
so.datatype = 'ip4addr(1)';
so.placeholder = '172.16.0.2';
so.rmempty = false;
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_ipv6', _('Local IPv6 address'),
_('The %s address used by local machine in the Cloudflare WARP network.').format('IPv6'));
so.datatype = 'ip6addr(1)';
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_mtu', _('MTU'));
so.datatype = 'range(0,9000)';
so.placeholder = '1280';
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'masque_network', _('Network'));
so.default = '';
so.value('', _('h3'));
@@ -909,17 +859,6 @@ return view.extend({
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'masque_remote_dns_resolve', _('Remote DNS resolve'),
_('Force DNS remote resolution.'));
so.default = so.disabled;
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.DynamicList, 'masque_dns', _('DNS server'));
so.datatype = 'or(host, hostport)';
so.depends('masque_remote_dns_resolve', '1');
so.modalonly = true;
/* SSH fields */
so = ss.taboption('field_general', form.TextValue, 'ssh_priv_key', _('Priv-key'));
so.depends('type', 'ssh');
@@ -1375,6 +1314,92 @@ return view.extend({
// @VMess-TLSmirror fields
/* VPN fields */
so = ss.taboption('field_vpn', form.Value, 'endpoint_ip', _('Virtual address'),
_('The %s address used by local machine in the %s network.').format(_('IPv4'), _('VPN')));
so.datatype = 'or(ip4addr(1), cidr4)';
so.placeholder = '172.16.0.2';
so.validate = function(section_id, value) {
const type = this.section.getOption('type').formvalue(section_id);
const desc = this.getUIElement(section_id).node.nextSibling;
switch (type) {
case 'wireguard':
desc.innerHTML = _('The %s address used by local machine in the %s network.')
.format(_('IPv4'), _('Wireguard'));
break;
case 'masque':
desc.innerHTML = _('The %s address used by local machine in the %s network.')
.format(_('IPv4'), _('Cloudflare WARP'));
break;
}
return true;
}
so.rmempty = false;
so.depends('type', 'wireguard');
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_vpn', form.Value, 'endpoint_ipv6', _('Virtual IPv6 address'),
_('The %s address used by local machine in the %s network.').format(_('IPv6'), _('VPN')));
so.datatype = 'or(ip6addr(1), cidr6)';
so.validate = function(section_id, value) {
const type = this.section.getOption('type').formvalue(section_id);
const desc = this.getUIElement(section_id).node.nextSibling;
switch (type) {
case 'wireguard':
desc.innerHTML = _('The %s address used by local machine in the %s network.')
.format(_('IPv6'), _('Wireguard'));
break;
case 'masque':
desc.innerHTML = _('The %s address used by local machine in the %s network.')
.format(_('IPv6'), _('Cloudflare WARP'));
break;
}
return true;
}
so.depends('type', 'wireguard');
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_vpn', form.Value, 'endpoint_mtu', _('MTU'));
so.datatype = 'range(0,9000)';
so.placeholder = '1400';
so.validate = function(section_id, value) {
const type = this.section.getOption('type').formvalue(section_id);
const UIEl = this.getUIElement(section_id);
let def_mtu;
switch (type) {
case 'wireguard':
def_mtu = '1408';
break;
case 'masque':
def_mtu = '1280';
break;
}
UIEl.node.querySelector('input').placeholder = def_mtu;
return true;
}
so.depends('type', 'wireguard');
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_vpn', form.Flag, 'endpoint_remote_dns_resolve', _('Remote DNS resolve'),
_('Force DNS remote resolution.'));
so.default = so.disabled;
so.depends({type: /^(wireguard|masque)$/});
so.modalonly = true;
so = ss.taboption('field_vpn', form.DynamicList, 'endpoint_dns', _('DNS server'));
so.datatype = 'or(host, hostport)';
so.depends('endpoint_remote_dns_resolve', '1');
so.modalonly = true;
/* Transport fields */
so = ss.taboption('field_general', form.Flag, 'transport_enabled', _('Transport'));
so.default = so.disabled;
+9 -5
View File
@@ -964,7 +964,7 @@ msgid "Encryption method"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:866
msgid "Endpoint pubkic key"
msgid "Endpoint public key"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/global.js:540
@@ -1811,12 +1811,12 @@ msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:794
#: htdocs/luci-static/resources/view/fchomo/node.js:881
msgid "Local IPv6 address"
msgid "Virtual IPv6 address"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:786
#: htdocs/luci-static/resources/view/fchomo/node.js:873
msgid "Local address"
msgid "Virtual address"
msgstr ""
#: root/usr/share/luci/menu.d/luci-app-fchomo.json:70
@@ -2333,7 +2333,7 @@ msgid "Payload"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:808
msgid "Peer pubkic key"
msgid "Peer public key"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/global.js:541
@@ -3256,7 +3256,7 @@ msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:787
#: htdocs/luci-static/resources/view/fchomo/node.js:795
msgid "The %s address used by local machine in the Wireguard network."
msgid "The %s address used by local machine in the %s network."
msgstr ""
#: htdocs/luci-static/resources/fchomo/listeners.js:1152
@@ -3641,6 +3641,10 @@ msgstr ""
msgid "VMess"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:241
msgid "VPN fields"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:1835
#: htdocs/luci-static/resources/view/fchomo/node.js:2206
#: htdocs/luci-static/resources/view/fchomo/ruleset.js:328
+13 -9
View File
@@ -984,7 +984,7 @@ msgid "Encryption method"
msgstr "加密方法"
#: htdocs/luci-static/resources/view/fchomo/node.js:866
msgid "Endpoint pubkic key"
msgid "Endpoint public key"
msgstr "端点公钥"
#: htdocs/luci-static/resources/view/fchomo/global.js:540
@@ -1841,13 +1841,13 @@ msgstr "本地"
#: htdocs/luci-static/resources/view/fchomo/node.js:794
#: htdocs/luci-static/resources/view/fchomo/node.js:881
msgid "Local IPv6 address"
msgstr "本地 IPv6 地址"
msgid "Virtual IPv6 address"
msgstr "虚拟 IPv6 地址"
#: htdocs/luci-static/resources/view/fchomo/node.js:786
#: htdocs/luci-static/resources/view/fchomo/node.js:873
msgid "Local address"
msgstr "本地地址"
msgid "Virtual address"
msgstr "虚拟地址"
#: root/usr/share/luci/menu.d/luci-app-fchomo.json:70
msgid "Log"
@@ -2365,7 +2365,7 @@ msgid "Payload"
msgstr "Payload"
#: htdocs/luci-static/resources/view/fchomo/node.js:808
msgid "Peer pubkic key"
msgid "Peer public key"
msgstr "对端公钥"
#: htdocs/luci-static/resources/view/fchomo/global.js:541
@@ -3266,7 +3266,7 @@ msgstr ""
#: htdocs/luci-static/resources/fchomo/listeners.js:123
#: htdocs/luci-static/resources/view/fchomo/node.js:240
msgid "TLS fields"
msgstr "TLS字段"
msgstr "TLS 字段"
#: htdocs/luci-static/resources/fchomo.js:165
#: htdocs/luci-static/resources/fchomo.js:202
@@ -3293,8 +3293,8 @@ msgstr "Cloudflare WARP 网络中使用的本机 %s 地址。"
#: htdocs/luci-static/resources/view/fchomo/node.js:787
#: htdocs/luci-static/resources/view/fchomo/node.js:795
msgid "The %s address used by local machine in the Wireguard network."
msgstr "WireGuard 网络中使用的本机 %s 地址。"
msgid "The %s address used by local machine in the %s network."
msgstr "本机 %s 地址,用于在 %s 网络中使用。"
#: htdocs/luci-static/resources/fchomo/listeners.js:1152
#: htdocs/luci-static/resources/view/fchomo/node.js:1302
@@ -3682,6 +3682,10 @@ msgstr ""
msgid "VMess"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:241
msgid "VPN fields"
msgstr "VPN 字段"
#: htdocs/luci-static/resources/view/fchomo/node.js:1835
#: htdocs/luci-static/resources/view/fchomo/node.js:2206
#: htdocs/luci-static/resources/view/fchomo/ruleset.js:328
+13 -9
View File
@@ -984,7 +984,7 @@ msgid "Encryption method"
msgstr "加密方法"
#: htdocs/luci-static/resources/view/fchomo/node.js:866
msgid "Endpoint pubkic key"
msgid "Endpoint public key"
msgstr "端點公鑰"
#: htdocs/luci-static/resources/view/fchomo/global.js:540
@@ -1841,13 +1841,13 @@ msgstr "本地"
#: htdocs/luci-static/resources/view/fchomo/node.js:794
#: htdocs/luci-static/resources/view/fchomo/node.js:881
msgid "Local IPv6 address"
msgstr "本地 IPv6 位址"
msgid "Virtual IPv6 address"
msgstr "虛擬 IPv6 位址"
#: htdocs/luci-static/resources/view/fchomo/node.js:786
#: htdocs/luci-static/resources/view/fchomo/node.js:873
msgid "Local address"
msgstr "本地位址"
msgid "Virtual address"
msgstr "虛擬位址"
#: root/usr/share/luci/menu.d/luci-app-fchomo.json:70
msgid "Log"
@@ -2365,7 +2365,7 @@ msgid "Payload"
msgstr "Payload"
#: htdocs/luci-static/resources/view/fchomo/node.js:808
msgid "Peer pubkic key"
msgid "Peer public key"
msgstr "對端公鑰"
#: htdocs/luci-static/resources/view/fchomo/global.js:541
@@ -3266,7 +3266,7 @@ msgstr ""
#: htdocs/luci-static/resources/fchomo/listeners.js:123
#: htdocs/luci-static/resources/view/fchomo/node.js:240
msgid "TLS fields"
msgstr "TLS欄位"
msgstr "TLS 欄位"
#: htdocs/luci-static/resources/fchomo.js:165
#: htdocs/luci-static/resources/fchomo.js:202
@@ -3293,8 +3293,8 @@ msgstr "Cloudflare WARP 網路中使用的本機 %s 位址。"
#: htdocs/luci-static/resources/view/fchomo/node.js:787
#: htdocs/luci-static/resources/view/fchomo/node.js:795
msgid "The %s address used by local machine in the Wireguard network."
msgstr "WireGuard 網路中使用的本機 %s 位址。"
msgid "The %s address used by local machine in the %s network."
msgstr "本機 %s 位址,用於在 %s 網路中使用。"
#: htdocs/luci-static/resources/fchomo/listeners.js:1152
#: htdocs/luci-static/resources/view/fchomo/node.js:1302
@@ -3682,6 +3682,10 @@ msgstr ""
msgid "VMess"
msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:241
msgid "VPN fields"
msgstr "VPN 欄位"
#: htdocs/luci-static/resources/view/fchomo/node.js:1835
#: htdocs/luci-static/resources/view/fchomo/node.js:2206
#: htdocs/luci-static/resources/view/fchomo/ruleset.js:328
+16 -14
View File
@@ -47,27 +47,29 @@ opmc() { # @less_25_12
# add_firewall
add_firewall() {
local enabled auto_firewall listen port
local enabled auto_firewall listen listen_port
config_get_bool enabled "$1" "enabled" "1"
config_get_bool auto_firewall "$1" "auto_firewall" "1"
config_get listen "$1" "listen" "::"
config_get port "$1" "port"
config_get listen_port "$1" "listen_port"
[ "$enabled" = "0" ] && return 0
[ "$auto_firewall" = "0" ] && return 0
json_add_object ''
json_add_string type rule
json_add_string target ACCEPT
json_add_string name "$1"
#json_add_string family '' # '' = IPv4 and IPv6
json_add_string proto 'tcp udp'
json_add_string direction in
json_add_string src "*"
#json_add_string dest '' # '' = input
json_add_string dest_ip "$(echo "$listen" | grep -vE '^(0\.\d+\.\d+\.\d+|::)$')"
json_add_string dest_port "$port"
json_close_object
for port in ${listen_port//,/ }; do
json_add_object ''
json_add_string type rule
json_add_string target ACCEPT
json_add_string name "$1"
#json_add_string family '' # '' = IPv4 and IPv6
json_add_string proto 'tcp udp'
json_add_string direction in
json_add_string src "*"
#json_add_string dest '' # '' = input
json_add_string dest_ip "$(echo "$listen" | grep -vE '^(0\.\d+\.\d+\.\d+|::)$')"
json_add_string dest_port "$port"
json_close_object
done
}
config_load "$CONF"
@@ -56,6 +56,14 @@ migrate() {
uci_set "$CONF" "$1" plugin "1"
uci_set "$CONF" "$1" plugin_type "$plugin"
fi
# port -> listen_port
if isDefined "$1" port; then
local port
config_get port "$1" port ""
uci_remove "$CONF" "$1" port
uci_set "$CONF" "$1" listen_port "$port"
fi
}
config_foreach migrate inbound
@@ -16,6 +16,11 @@ isDefined() {
eval "[ -n \"\${$opt+x}\" ] && return 0 || return 1"
}
# add_list <value> <config> <section> <option>
add_list() {
uci_add_list "$2" "$3" "$4" "$1"
}
migrate() {
# mieru_port_range -> mieru_ports
if isDefined "$1" mieru_port_range; then
@@ -82,6 +87,82 @@ migrate() {
uci_set "$CONF" "$1" plugin "1"
uci_set "$CONF" "$1" plugin_type "$plugin"
fi
# wireguard_ip -> endpoint_ip
if isDefined "$1" wireguard_ip; then
local wireguard_ip
config_get wireguard_ip "$1" wireguard_ip ""
uci_remove "$CONF" "$1" wireguard_ip
uci_set "$CONF" "$1" endpoint_ip "$wireguard_ip"
fi
# masque_ip -> endpoint_ip
if isDefined "$1" masque_ip; then
local masque_ip
config_get masque_ip "$1" masque_ip ""
uci_remove "$CONF" "$1" masque_ip
uci_set "$CONF" "$1" endpoint_ip "$masque_ip"
fi
# wireguard_ipv6 -> endpoint_ipv6
if isDefined "$1" wireguard_ipv6; then
local wireguard_ipv6
config_get wireguard_ipv6 "$1" wireguard_ipv6 ""
uci_remove "$CONF" "$1" wireguard_ipv6
uci_set "$CONF" "$1" endpoint_ipv6 "$wireguard_ipv6"
fi
# masque_ipv6 -> endpoint_ipv6
if isDefined "$1" masque_ipv6; then
local masque_ipv6
config_get masque_ipv6 "$1" masque_ipv6 ""
uci_remove "$CONF" "$1" masque_ipv6
uci_set "$CONF" "$1" endpoint_ipv6 "$masque_ipv6"
fi
# wireguard_mtu -> endpoint_mtu
if isDefined "$1" wireguard_mtu; then
local wireguard_mtu
config_get wireguard_mtu "$1" wireguard_mtu ""
uci_remove "$CONF" "$1" wireguard_mtu
uci_set "$CONF" "$1" endpoint_mtu "$wireguard_mtu"
fi
# masque_mtu -> endpoint_mtu
if isDefined "$1" masque_mtu; then
local masque_mtu
config_get masque_mtu "$1" masque_mtu ""
uci_remove "$CONF" "$1" masque_mtu
uci_set "$CONF" "$1" endpoint_mtu "$masque_mtu"
fi
# wireguard_remote_dns_resolve -> endpoint_remote_dns_resolve
if isDefined "$1" wireguard_remote_dns_resolve; then
local wireguard_remote_dns_resolve
config_get wireguard_remote_dns_resolve "$1" wireguard_remote_dns_resolve ""
uci_remove "$CONF" "$1" wireguard_remote_dns_resolve
uci_set "$CONF" "$1" endpoint_remote_dns_resolve "$wireguard_remote_dns_resolve"
fi
# masque_remote_dns_resolve -> endpoint_remote_dns_resolve
if isDefined "$1" masque_remote_dns_resolve; then
local masque_remote_dns_resolve
config_get masque_remote_dns_resolve "$1" masque_remote_dns_resolve ""
uci_remove "$CONF" "$1" masque_remote_dns_resolve
uci_set "$CONF" "$1" endpoint_remote_dns_resolve "$masque_remote_dns_resolve"
fi
# wireguard_dns -> endpoint_dns
if isDefined "$1" wireguard_dns; then
config_list_foreach "$1" wireguard_dns add_list "$CONF" "$1" endpoint_dns
uci_remove "$CONF" "$1" wireguard_dns
fi
# masque_dns -> endpoint_dns
if isDefined "$1" masque_dns; then
config_list_foreach "$1" masque_dns add_list "$CONF" "$1" endpoint_dns
uci_remove "$CONF" "$1" masque_dns
fi
}
config_foreach migrate node
@@ -64,6 +64,14 @@ migrate() {
uci_set "$CONF" "$1" plugin "1"
uci_set "$CONF" "$1" plugin_type "$plugin"
fi
# port -> listen_port
if isDefined "$1" port; then
local port
config_get port "$1" port ""
uci_remove "$CONF" "$1" port
uci_set "$CONF" "$1" listen_port "$port"
fi
}
config_foreach migrate server
@@ -148,16 +148,21 @@ function get_nameserver(cfg, detour) {
let servers = [];
for (let k in cfg) {
if (k === 'system-dns') {
push(servers, 'system');
} else if (k === 'default-dns') {
map(wan_dns, (dns) => {
push(servers, dns + '#DIRECT');
});
} else
push(servers, replace(dnsservers[k]?.address || '', /#detour=([^&]+)/, (m, c1) => {
return '#' + urlencode(get_proxy(detour || c1));
}));
switch (k) {
case 'system-dns':
push(servers, 'system');
break;
case 'default-dns':
map(wan_dns, (dns) => {
push(servers, dns + '#DIRECT');
});
break;
default:
push(servers, replace(dnsservers[k]?.address || '', /#detour=([^&]+)/, (m, c1) => {
return '#' + urlencode(get_proxy(detour || c1));
}));
break;
}
}
return servers;
@@ -209,12 +214,16 @@ uci.foreach(uciconf, ucichain, (cfg) => {
return;
let identifier = '';
if (cfg.type === 'provider')
identifier = cfg.chain_head_sub;
else if (cfg.type === 'node')
identifier = cfg.chain_head;
else
return;
switch (cfg.type) {
case 'provider':
identifier = cfg.chain_head_sub;
break;
case 'node':
identifier = cfg.chain_head;
break;
default:
return;
}
dialerproxy[identifier] = {
detour: get_proxy(cfg.chain_tail_group) || get_proxy(cfg.chain_tail)
@@ -431,13 +440,17 @@ map([
return null;
let key;
if (cfg.type === 'domain') {
key = isEmpty(cfg.domain) ? null : join(',', cfg.domain);
} else if (cfg.type === 'geosite') {
key = isEmpty(cfg.geosite) ? null : 'geosite:' + join(',', cfg.geosite);
} else if (cfg.type === 'rule_set') {
key = isEmpty(cfg.rule_set) ? null : 'rule-set:' + join(',', cfg.rule_set);
};
switch (cfg.type) {
case 'domain':
key = isEmpty(cfg.domain) ? null : join(',', cfg.domain);
break;
case 'geosite':
key = isEmpty(cfg.geosite) ? null : 'geosite:' + join(',', cfg.geosite);
break;
case 'rule_set':
key = isEmpty(cfg.rule_set) ? null : 'rule-set:' + join(',', cfg.rule_set);
break;
}
if (!key)
return null;
@@ -501,17 +514,12 @@ uci.foreach(uciconf, ucinode, (cfg) => {
"target-rematch-name": cfg.target_rematch_name,
"target-sub-rule": cfg.target_sub_rule,
/* HTTP / SOCKS / Shadowsocks / VMess / VLESS / Trojan / TUIC / hysteria2 / WireGuard / Masque */
/* HTTP / SOCKS / Shadowsocks / VMess / VLESS / Trojan / TUIC / hysteria2 */
username: cfg.username,
uuid: cfg.vmess_uuid || cfg.uuid,
cipher: cfg.vmess_chipher || cfg.shadowsocks_chipher,
password: cfg.shadowsocks_password || cfg.password,
headers: cfg.headers ? json(cfg.headers) : null,
ip: cfg.masque_ip || cfg.wireguard_ip,
ipv6: cfg.masque_ipv6 || cfg.wireguard_ipv6,
mtu: strToInt(cfg.masque_mtu ?? cfg.wireguard_mtu) || null,
"remote-dns-resolve": strToBool(cfg.masque_remote_dns_resolve ?? cfg.wireguard_remote_dns_resolve),
dns: cfg.masque_dns || cfg.wireguard_dns,
/* Shadowsocks */
@@ -709,6 +717,13 @@ uci.foreach(uciconf, ucinode, (cfg) => {
"support-x25519mlkem768": strToBool(cfg.tls_reality_support_x25519mlkem768)
} : null,
/* VPN fields */
ip: cfg.endpoint_ip,
ipv6: cfg.endpoint_ipv6,
mtu: strToInt(cfg.endpoint_mtu) || null,
"remote-dns-resolve": strToBool(cfg.endpoint_remote_dns_resolve),
dns: cfg.endpoint_dns, // Array
/* Transport fields */
// https://github.com/muink/mihomo/blob/3e966e82c793ca99e3badc84bf3f2907b100edae/adapter/outbound/vmess.go#L74
...(cfg.transport_enabled === '1' ? {
@@ -56,12 +56,16 @@ const methods = {
let result = {};
let cmd = `generate ${type}`;
if (type === 'age-x25519') {
cmd = 'age keygen';
} else if (type === 'age-mlkem768-x25519') {
cmd = 'age keygen-pq';
} else if (type === 'age-convert') {
cmd = 'age convert';
switch (type) {
case 'age-x25519':
cmd = 'age keygen';
break;
case 'age-mlkem768-x25519':
cmd = 'age keygen-pq';
break;
case 'age-convert':
cmd = 'age convert';
break;
}
const fd = popen(`/usr/bin/mihomo ${cmd} ${shellQuote(req.args.params ?? '')}`);
+32 -19
View File
@@ -116,14 +116,20 @@ export function bytesizeToByte(str) {
let bytes = 0;
let arr = match(str, /^(\d+)(k|m|g)?b?$/);
if (arr) {
if (arr[2] === 'k') {
bytes = strToInt(arr[1]) * 1024;
} else if (arr[2] === 'm') {
bytes = strToInt(arr[1]) * 1048576;
} else if (arr[2] === 'g') {
bytes = strToInt(arr[1]) * 1073741824;
} else
bytes = strToInt(arr[1]);
switch (arr[2]) {
case 'k':
bytes = strToInt(arr[1]) * 1024;
break;
case 'm':
bytes = strToInt(arr[1]) * 1048576;
break;
case 'g':
bytes = strToInt(arr[1]) * 1073741824;
break;
default:
bytes = strToInt(arr[1]);
break;
}
}
return bytes;
@@ -135,16 +141,23 @@ export function durationToSecond(str) {
let seconds = 0;
let arr = match(str, /^(\d+)(s|m|h|d)?$/);
if (arr) {
if (arr[2] === 's') {
seconds = strToInt(arr[1]);
} else if (arr[2] === 'm') {
seconds = strToInt(arr[1]) * 60;
} else if (arr[2] === 'h') {
seconds = strToInt(arr[1]) * 3600;
} else if (arr[2] === 'd') {
seconds = strToInt(arr[1]) * 86400;
} else
seconds = strToInt(arr[1]);
switch (arr[2]) {
case 's':
seconds = strToInt(arr[1]);
break;
case 'm':
seconds = strToInt(arr[1]) * 60;
break;
case 'h':
seconds = strToInt(arr[1]) * 3600;
break;
case 'd':
seconds = strToInt(arr[1]) * 86400;
break;
default:
seconds = strToInt(arr[1]);
break;
}
}
return seconds;
@@ -217,7 +230,7 @@ export function parseListener(cfg) {
type: cfg.type,
listen: cfg.listen || '::',
port: strToInt(cfg.port),
port: strToInt(cfg.listen_port),
"routing-mark": strToInt(cfg.routing_mark) || null,
rule: cfg.rule,
proxy: cfg.proxy, // raw data need post-processing