🌈 Sync 2026-07-19 23:47:22

This commit is contained in:
github-actions[bot] 2026-07-19 23:47:22 +08:00
parent c0107db2e8
commit ac831f0b74
9 changed files with 91 additions and 76 deletions

View File

@ -652,12 +652,16 @@ function renderListeners(s, uciconfig, isClient) {
const type = this.section.getOption('type').formvalue(section_id);
if (value) {
if (type === 'snell' && !['obfs', 'shadow-tls'].includes(value)) {
if (type === 'snell' && !['obfs', 'shadow-tls', 'restls', 'jls'].includes(value)) {
return _('Expecting: Only support %s.').format(_('obfs-simple') +
' / ' + _('ShadowTLS'));
' / ' + _('ShadowTLS') +
' / ' + _('Restls') +
' / ' + _('JLS'));
}
if (['vmess', 'vless', 'trojan', 'anytls'].includes(type) && !['jls'].includes(value)) {
return _('Expecting: Only support %s.').format(_('JLS'));
if (['vmess', 'vless', 'trojan', 'anytls'].includes(type) && !['shadow-tls', 'restls', 'jls'].includes(value)) {
return _('Expecting: only support %s.').format(_('ShadowTLS') +
' / ' + _('Restls') +
' / ' + _('JLS'));
}
}
@ -726,7 +730,7 @@ function renderListeners(s, uciconfig, isClient) {
...hm.loadLabelValues(this.config, 'proxy_group')
], section_id);
}
o.depends({plugin_type: /^(restls|jls)$/});
o.depends({plugin_type: /^(shadow-tls|restls|jls)$/});
o.depends({type: 'shadowquic'});
o.modalonly = true;
}
@ -1033,8 +1037,8 @@ function renderListeners(s, uciconfig, isClient) {
o = s.taboption('field_tls', form.Value, 'tls_sni', _('TLS SNI'),
_('Hostname that the client attempts to connect to at the start of the TLS handshake process.'));
o.depends('plugin_type', 'jls');
o.depends({tls: '1', type: 'shadowquic'});
o.depends('plugin_type', 'jls');
o.modalonly = true;
o = s.taboption('field_tls', form.DynamicList, 'tls_alpn', _('TLS ALPN'),
@ -1092,9 +1096,11 @@ function renderListeners(s, uciconfig, isClient) {
const plugin_type = this.section.getOption('plugin_type').formvalue(section_id);
const tls_reality = this.section.getOption('tls_reality').formvalue(section_id);
if (plugin_type === 'jls' || tls_reality == 1) {
if (['shadow-tls', 'restls', 'jls'].includes(plugin_type) || tls_reality == 1) {
if (value)
return _('Expecting: Keep empty when %s is enabled.').format(_('JLS') +
return _('Expecting: Keep empty when %s is enabled.').format(_('ShadowTLS') +
' / ' + _('Restls') +
' / ' + _('JLS') +
' / ' + _('REALITY'));
} else if (!value) {
return _('Expecting: Cannot be empty.');
@ -1207,8 +1213,10 @@ function renderListeners(s, uciconfig, isClient) {
const plugin_type = this.section.getOption('plugin_type').formvalue(section_id);
value = this.formvalue(section_id);
if (value == 1 && plugin_type === 'jls')
return _('Expecting: Cannot be enabled when %s is enabled.').format(_('JLS'));
if (value == 1 && ['shadow-tls', 'restls', 'jls'].includes(plugin_type))
return _('Expecting: cannot be enabled when %s is enabled.').format(_('ShadowTLS') +
' / ' + _('Restls') +
' / ' + _('JLS'));
return true;
}

View File

@ -104,7 +104,7 @@ const parseProviderYaml = hm.parseYaml.extend({
if (!cfg.type)
return null;
// key mapping // 2026/07/12
// key mapping // 2026/07/18
let config = hm.removeBlankAttrs({
id: this.id,
label: this.label,
@ -968,6 +968,7 @@ return view.extend({
so = ss.taboption('field_general', form.Flag, 'plugin', _('Plugin'));
so.default = so.disabled;
so.depends({type: /^(ss|snell)$/});
so.depends({type: /^(vmess|vless|trojan|anytls)$/});
so.modalonly = true;
so = ss.taboption('field_plugin', form.ListValue, 'plugin_type', _('Plugin type'));
@ -982,9 +983,16 @@ return view.extend({
const type = this.section.getOption('type').formvalue(section_id);
if (value) {
if (type === 'snell' && !['obfs', 'shadow-tls'].includes(value)) {
if (type === 'snell' && !['obfs', 'shadow-tls', 'restls', 'jls'].includes(value)) {
return _('Expecting: Only support %s.').format(_('obfs-simple') +
' / ' + _('ShadowTLS'));
' / ' + _('ShadowTLS') +
' / ' + _('Restls') +
' / ' + _('JLS'));
}
if (['vmess', 'vless', 'trojan', 'anytls'].includes(type) && !['shadow-tls', 'restls', 'jls'].includes(value)) {
return _('Expecting: only support %s.').format(_('ShadowTLS') +
' / ' + _('Restls') +
' / ' + _('JLS'));
}
}
@ -1028,6 +1036,8 @@ return view.extend({
so = ss.taboption('field_plugin', form.Value, 'plugin_opts_restls_versionhint', _('Version hint'));
so.default = 'tls13';
so.value('tls12', _('tls12'));
so.value('tls13', _('tls13'));
so.rmempty = false;
so.depends({plugin_type: 'restls'});
so.modalonly = true;
@ -1167,14 +1177,6 @@ return view.extend({
so = ss.taboption('field_tls', form.Value, 'tls_sni', _('TLS SNI'),
_('Hostname that the client attempts to connect to at the start of the TLS handshake process.'));
so.validate = function(section_id, value) {
const tls_jls = this.section.getOption('tls_jls').formvalue(section_id);
if (tls_jls == 1 && !value)
return _('Expecting: %s cannot be empty when %s is enabled.').format(_('TLS SNI'), _('JLS'));
return true;
};
so.depends({tls: '1', type: /^(http|vmess|vless|trojan|anytls|hysteria|hysteria2|shadowquic|trusttunnel|masque)$/});
so.depends({tls: '1', type: /^(tuic)$/, tls_disable_sni: '0'});
so.modalonly = true;
@ -1222,8 +1224,8 @@ return view.extend({
return true;
}
so.depends({tls: '1', type: /^(vmess|vless|trojan|anytls|tuic|hysteria|hysteria2|shadowquic|trusttunnel)$/});
so.depends({type: /^(ss|snell)$/, plugin_type: 'shadow-tls'});
so.depends({type: 'ss', plugin_type: 'jls'});
so.depends({type: 'ss', plugin_type: /^(shadow-tls|jls)$/});
so.depends({type: 'snell', plugin_type: 'shadow-tls'});
so.modalonly = true;
so = ss.taboption('field_tls', form.Value, 'tls_fingerprint', _('Cert fingerprint'),
@ -1305,28 +1307,23 @@ return view.extend({
so.value.apply(so, res);
})
so.depends({tls: '1', type: /^(vmess|vless|trojan|anytls|trusttunnel)$/});
so.depends({type: /^(ss|snell)$/, plugin_type: /^(shadow-tls|restls)$/});
so.depends({type: 'ss', plugin_type: 'jls'});
so.modalonly = true;
so = ss.taboption('field_tls', form.Flag, 'tls_jls', _('JLS'));
so.default = so.disabled;
so.depends({tls: '1', type: /^(vmess|vless|trojan|anytls)$/});
so.modalonly = true;
so = ss.taboption('field_tls', form.Value, 'tls_jls_username', _('JLS username'));
so.rmempty = false;
so.depends('tls_jls', '1');
so.modalonly = true;
so = ss.taboption('field_tls', form.Value, 'tls_jls_password', _('JLS password'));
so.rmempty = false;
so.depends('tls_jls', '1');
so.depends({type: /^(ss|snell)$/, plugin_type: /^(shadow-tls|restls|jls)$/});
so.modalonly = true;
so = ss.taboption('field_tls', form.Flag, 'tls_reality', _('REALITY'));
so.default = so.disabled;
so.depends({tls: '1', tls_jls: '0', type: /^(vmess|vless|trojan)$/});
so.validate = function(section_id, value) {
const plugin_type = this.section.getOption('plugin_type').formvalue(section_id);
value = this.formvalue(section_id);
if (value == 1 && ['shadow-tls', 'restls', 'jls'].includes(plugin_type))
return _('Expecting: cannot be enabled when %s is enabled.').format(_('ShadowTLS') +
' / ' + _('Restls') +
' / ' + _('JLS'));
return true;
}
so.depends({tls: '1', type: /^(vmess|vless|trojan)$/});
so.modalonly = true;
so = ss.taboption('field_tls', form.Value, 'tls_reality_public_key', _('REALITY public key'));
@ -1985,7 +1982,7 @@ return view.extend({
so = ss.taboption('field_override', form.DynamicList, 'override_expr', _('Programmable replacement'),
_('For format see <a target="_blank" href="%s" rel="noreferrer noopener">%s</a>.')
.format('https://wiki.metacubex.one/config/proxy-providers/#override_expr', _('override.override-expr')));
.format('https://wiki.metacubex.one/config/proxy-providers/#overrideoverride-expr', _('override.override-expr')));
so.placeholder = '.name = "[provider1] " + .name';
so.depends({type: 'inline', '!reverse': true});
so.modalonly = true;

View File

@ -50,7 +50,7 @@ migrate() {
fi
# plugin -> plugin_type
if isDefined "$1" plugin; then
if isDefined "$1" plugin && ! isDefined "$1" plugin_type; then
local plugin
config_get plugin "$1" plugin ""
uci_set "$CONF" "$1" plugin "1"

View File

@ -76,7 +76,7 @@ migrate() {
fi
# plugin -> plugin_type
if isDefined "$1" plugin; then
if isDefined "$1" plugin && ! isDefined "$1" plugin_type; then
local plugin
config_get plugin "$1" plugin ""
uci_set "$CONF" "$1" plugin "1"

View File

@ -58,7 +58,7 @@ migrate() {
fi
# plugin -> plugin_type
if isDefined "$1" plugin; then
if isDefined "$1" plugin && ! isDefined "$1" plugin_type; then
local plugin
config_get plugin "$1" plugin ""
uci_set "$CONF" "$1" plugin "1"

View File

@ -345,6 +345,8 @@ uci.foreach(uciconf, uciinbd, (cfg) => {
const listener = parseListener(cfg);
listener.proxy = get_proxy(listener.proxy);
if (listener["shadow-tls"])
listener["shadow-tls"].handshake.proxy = get_proxy(listener["shadow-tls"].handshake.proxy);
if (listener["res-tls"])
listener["res-tls"].proxy = get_proxy(listener["res-tls"].proxy);
if (listener["jls-config"])
@ -541,7 +543,7 @@ uci.foreach(uciconf, ucinode, (cfg) => {
/* Snell */
psk: cfg.snell_psk,
version: cfg.snell_version,
version: strToInt(cfg.snell_version),
reuse: strToBool(cfg.snell_reuse),
/* VMess / VLESS */
@ -641,38 +643,49 @@ uci.foreach(uciconf, ucinode, (cfg) => {
/* Plugin fields */
...(cfg.plugin === '1' ? (
cfg.type === 'snell' ? {
// snell
"obfs-opts": {
mode: cfg.plugin_type === 'shadow-tls' ? cfg.plugin_type : cfg.plugin_opts_obfsmode,
host: cfg.plugin_opts_host,
password: cfg.plugin_opts_thetlspassword,
cfg.type in ['vmess', 'vless', 'trojan', 'anytls'] ? {
...arrToObj([[(cfg.type in ['vmess', 'vless']) ? 'servername' : 'sni', cfg.plugin_opts_host]]),
// shadow-tls
"shadow-tls-opts": cfg.plugin_type === 'shadow-tls' ? {
version: strToInt(cfg.plugin_opts_shadowtls_version),
alpn: cfg.tls_alpn // Array
}
} : {
// others
plugin: cfg.plugin_type,
"plugin-opts": {
mode: cfg.plugin_opts_obfsmode,
host: cfg.plugin_opts_host,
username: cfg.plugin_opts_thetlsusername,
password: cfg.plugin_opts_thetlspassword
} : null,
// restls
"restls-opts": cfg.plugin_type === 'restls' ? {
password: cfg.plugin_opts_thetlspassword,
version: strToInt(cfg.plugin_opts_shadowtls_version),
alpn: cfg.tls_alpn, // Array
"version-hint": cfg.plugin_opts_restls_versionhint,
"restls-script": cfg.plugin_opts_restls_script
}
} : null,
// jls
"jls-opts": cfg.plugin_type === 'jls' ? {
username: cfg.plugin_opts_thetlsusername,
password: cfg.plugin_opts_thetlspassword
} : null,
} : {
// snell / shadowsocks
plugin: cfg.type === 'snell' ? null : cfg.plugin_type,
...arrToObj([[cfg.type === 'snell' ? "obfs-opts" : "plugin-opts",
{
mode: (cfg.type === 'snell' && cfg.plugin_type !== 'obfs') ? cfg.plugin_type : cfg.plugin_opts_obfsmode,
host: cfg.plugin_opts_host,
username: cfg.plugin_opts_thetlsusername,
password: cfg.plugin_opts_thetlspassword,
version: strToInt(cfg.plugin_opts_shadowtls_version),
alpn: cfg.tls_alpn, // Array
"version-hint": cfg.plugin_opts_restls_versionhint,
"restls-script": cfg.plugin_opts_restls_script
}
]])
}
) : {}),
/* SSH / WireGuard / Masque */
/* TLS fields */
tls: (cfg.type in ['trojan', 'anytls', 'tuic', 'hysteria', 'hysteria2', 'shadowquic', 'trusttunnel']) ? null : strToBool(cfg.tls),
tls: (cfg.type in ['trojan', 'anytls', 'tuic', 'hysteria', 'hysteria2', 'shadowquic', 'trusttunnel', 'masque']) ? null : strToBool(cfg.tls),
"disable-sni": strToBool(cfg.tls_disable_sni),
...arrToObj([[(cfg.type in ['vmess', 'vless']) ? 'servername' : 'sni', cfg.tls_sni]]),
...(cfg.tls_sni ? arrToObj([[(cfg.type in ['vmess', 'vless']) ? 'servername' : 'sni', cfg.tls_sni]]) : {}),
fingerprint: cfg.tls_fingerprint,
alpn: cfg.plugin_type in ['shadow-tls', 'jls'] ? null : cfg.tls_alpn, // Array
alpn: cfg.tls === '1' ? cfg.tls_alpn : null, // Array
"name-cert-verify": cfg.tls_name_cert_verify,
"skip-cert-verify": strToBool(cfg.tls_skip_cert_verify),
certificate: cfg.tls_cert_path, // mTLS
@ -684,10 +697,6 @@ uci.foreach(uciconf, ucinode, (cfg) => {
config: cfg.tls_ech_config,
"query-server-name": cfg.tls_ech_query_server_name
} : null,
"jls-opts": cfg.tls_jls === '1' ? {
"username": cfg.tls_jls_username,
"password": cfg.tls_jls_password
} : null,
"reality-opts": cfg.tls_reality === '1' ? {
"public-key": cfg.tls_reality_public_key,
"short-id": cfg.tls_reality_short_id,

View File

@ -385,7 +385,8 @@ export function parseListener(cfg) {
],
} : { password: cfg.plugin_opts_thetlspassword }),
handshake: {
dest: cfg.plugin_opts_handshake_dest
dest: cfg.plugin_opts_handshake_dest,
proxy: cfg.plugin_opts_dest_proxy // raw data need post-processing
}
}
} : cfg.plugin_type === 'restls' ? {

View File

@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mihomo
PKG_VERSION:=1.19.28
PKG_RELEASE:=30
PKG_VERSION:=1.19.29
PKG_RELEASE:=31
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/metacubex/mihomo/tar.gz/v$(PKG_VERSION)?

View File

@ -8,11 +8,11 @@ PKG_NAME:=go-stun
PKG_UPSTREAM_VERSION:=0.1.4
PKG_UPSTREAM_GITHASH:=d32c135f5e509d278e95ba9945849903f966a91f
PKG_VERSION:=$(PKG_UPSTREAM_VERSION)~$(call version_abbrev,$(PKG_UPSTREAM_GITHASH))
PKG_RELEASE:=5
PKG_RELEASE:=6
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/ccding/go-stun.git
PKG_SOURCE_VERSION:=c6f6521d99a27227538c3bd8a7729f8b2f2a69dd
PKG_SOURCE_VERSION:=65c0568253e3a432f330b346d5ecad938d35d5aa
PKG_MIRROR_HASH:=skip
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION)