🎉 Sync 2026-07-14 20:29:41

This commit is contained in:
github-actions[bot] committed 2026-07-14 20:29:41 +08:00
1 parent 062ce0dff0
commit 40d4011279
15 files changed
+3478 -3132

No files matched your search

@@ -0,0 +1,41 @@
#!/bin/sh
# Migration script for fchomo inbound
# Used to migrate LuCI application inbound option.
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
CONF=fchomo
config_load "$CONF"
# isDefined <section> <option>
isDefined() {
local opt=CONFIG_${1}_${2};
eval "[ -n \"\${$opt+x}\" ] && return 0 || return 1"
}
migrate() {
# tuic_max_idle_time -> max_idle_time
if isDefined "$1" tuic_max_idle_time; then
local tuic_max_idle_time
config_get tuic_max_idle_time "$1" tuic_max_idle_time ""
uci_remove "$CONF" "$1" tuic_max_idle_time
uci_set "$CONF" "$1" max_idle_time "$tuic_max_idle_time"
fi
# plugin -> plugin_type
if isDefined "$1" plugin; then
local plugin
config_get plugin "$1" plugin ""
uci_set "$CONF" "$1" plugin "1"
uci_set "$CONF" "$1" plugin_type "$plugin"
fi
}
config_foreach migrate inbound
uci_commit "$CONF"
exit 0
@@ -50,6 +50,22 @@ migrate() {
uci_remove "$CONF" "$1" masque_congestion_controller
uci_set "$CONF" "$1" congestion_controller "$masque_congestion_controller"
fi
# tuic_max_open_streams -> max_open_streams
if isDefined "$1" tuic_max_open_streams; then
local tuic_max_open_streams
config_get tuic_max_open_streams "$1" tuic_max_open_streams ""
uci_remove "$CONF" "$1" tuic_max_open_streams
uci_set "$CONF" "$1" max_open_streams "$tuic_max_open_streams"
fi
# plugin -> plugin_type
if isDefined "$1" plugin; then
local plugin
config_get plugin "$1" plugin ""
uci_set "$CONF" "$1" plugin "1"
uci_set "$CONF" "$1" plugin_type "$plugin"
fi
}
config_foreach migrate node
@@ -24,6 +24,22 @@ migrate() {
uci_remove "$CONF" "$1" tuic_congestion_controller
uci_set "$CONF" "$1" congestion_controller "$tuic_congestion_controller"
fi
# tuic_max_idle_time -> max_idle_time
if isDefined "$1" tuic_max_idle_time; then
local tuic_max_idle_time
config_get tuic_max_idle_time "$1" tuic_max_idle_time ""
uci_remove "$CONF" "$1" tuic_max_idle_time
uci_set "$CONF" "$1" max_idle_time "$tuic_max_idle_time"
fi
# plugin -> plugin_type
if isDefined "$1" plugin; then
local plugin
config_get plugin "$1" plugin ""
uci_set "$CONF" "$1" plugin "1"
uci_set "$CONF" "$1" plugin_type "$plugin"
fi
}
config_foreach migrate server
@@ -121,7 +121,7 @@ function parse_filter(cfg) {
return cfg;
}
function get_proxy(cfg, pass_undefined) {
function get_proxy(cfg, no_verify) {
if (isEmpty(cfg))
return null;
@@ -130,7 +130,7 @@ function get_proxy(cfg, pass_undefined) {
const label = uci.get(uciconf, cfg, 'label');
if (isEmpty(label)) {
if (pass_undefined)
if (no_verify)
return cfg;
else
die(sprintf("%s's label is missing, please check your configuration.", cfg));
@@ -343,7 +343,16 @@ uci.foreach(uciconf, uciinbd, (cfg) => {
if (cfg.enabled === '0')
return;
push(config.listeners, parseListener(cfg, true, get_proxy(cfg.proxy)));
const listener = parseListener(cfg);
listener.proxy = get_proxy(listener.proxy);
if (listener["res-tls"])
listener["res-tls"].proxy = get_proxy(listener["res-tls"].proxy);
if (listener["jls-config"])
listener["jls-config"].proxy = get_proxy(listener["jls-config"].proxy);
if (listener["jls-upstream"])
listener["jls-upstream"].proxy = get_proxy(listener["jls-upstream"].proxy);
push(config.listeners, listener);
});
/* Tun settings */
if (match(proxy_mode, /tun/))
@@ -490,7 +499,7 @@ 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 / ShadowQUIC / WireGuard / Masque */
username: cfg.username,
uuid: cfg.vmess_uuid || cfg.uuid,
cipher: cfg.vmess_chipher || cfg.shadowsocks_chipher,
@@ -558,14 +567,11 @@ uci.foreach(uciconf, ucinode, (cfg) => {
/* TUIC */
ip: cfg.tuic_ip,
"udp-relay-mode": cfg.tuic_udp_relay_mode,
"udp-over-stream": strToBool(cfg.tuic_udp_over_stream),
"udp-over-stream-version": cfg.tuic_udp_over_stream_version,
"max-udp-relay-packet-size": strToInt(cfg.tuic_max_udp_relay_packet_size) || null,
"fast-open": strToBool(cfg.tuic_fast_open),
"reduce-rtt": strToBool(cfg.tuic_reduce_rtt),
"heartbeat-interval": strToInt(cfg.tuic_heartbeat) || null,
"request-timeout": strToInt(cfg.tuic_request_timeout) || null,
"max-open-streams": strToInt(cfg.tuic_max_open_streams) || null,
/* Hysteria / Hysteria2 */
ports: isEmpty(cfg.hysteria_ports) ? null : join(',', cfg.hysteria_ports),
@@ -591,6 +597,15 @@ uci.foreach(uciconf, ucinode, (cfg) => {
//"private-key"
} : null,
/* ShadowQUIC */
"quic-versions": cfg.shadowquic_quic_versions,
"zero-rtt": strToBool(cfg.shadowquic_zero_rtt),
// @# cwnd: 10 # default: 32,
// @# max-datagram-frame-size: 1400,
// @# recv-window-conn: 0,
// @# recv-window: 0,
// @# disable-mtu-discovery: false,
/* TrustTunnel */
"health-check": cfg.type === 'trusttunnel' ? (cfg.trusttunnel_health_check === '0' ? false : true) : null,
quic: strToBool(cfg.trusttunnel_quic),
@@ -609,12 +624,25 @@ uci.foreach(uciconf, ucinode, (cfg) => {
"host-key-algorithms": cfg.ssh_host_key_algorithms,
"host-key": cfg.ssh_host_key,
/* Extra fields */
"udp-over-stream": strToBool(cfg.shadowquic_udp_over_stream || cfg.tuic_udp_over_stream),
"heartbeat-interval": strToInt(cfg.tuic_heartbeat) || null,
"keep-alive-interval": strToInt(cfg.shadowquic_heartbeat) || null,
"congestion-controller": cfg.congestion_controller,
"bbr-profile": cfg.bbr_profile,
"max-open-streams": strToInt(cfg.max_open_streams) || null,
"handshake-timeout": strToInt(cfg.handshake_timeout),
udp: strToBool(cfg.udp),
"udp-over-tcp": strToBool(cfg.uot),
"udp-over-tcp-version": cfg.uot_version,
/* Plugin fields */
...(cfg.plugin ? (
...(cfg.plugin === '1' ? (
cfg.type === 'snell' ? {
// snell
"obfs-opts": {
mode: cfg.plugin in ['shadow-tls'] ? cfg.plugin : cfg.plugin_opts_obfsmode,
mode: cfg.plugin_type === 'shadow-tls' ? cfg.plugin_type : cfg.plugin_opts_obfsmode,
host: cfg.plugin_opts_host,
password: cfg.plugin_opts_thetlspassword,
version: strToInt(cfg.plugin_opts_shadowtls_version),
@@ -622,10 +650,11 @@ uci.foreach(uciconf, ucinode, (cfg) => {
}
} : {
// others
plugin: cfg.plugin,
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,
version: strToInt(cfg.plugin_opts_shadowtls_version),
alpn: cfg.tls_alpn, // Array
@@ -635,21 +664,14 @@ uci.foreach(uciconf, ucinode, (cfg) => {
}
) : {}),
/* Extra fields */
"congestion-controller": cfg.congestion_controller,
"bbr-profile": cfg.bbr_profile,
"handshake-timeout": strToInt(cfg.handshake_timeout),
udp: strToBool(cfg.udp),
"udp-over-tcp": strToBool(cfg.uot),
"udp-over-tcp-version": cfg.uot_version,
/* SSH / WireGuard / Masque */
/* TLS fields */
tls: (cfg.type in ['trojan', 'anytls', 'hysteria', 'hysteria2', 'tuic', 'trusttunnel']) ? null : strToBool(cfg.tls),
tls: (cfg.type in ['trojan', 'anytls', 'tuic', 'hysteria', 'hysteria2', 'shadowquic', 'trusttunnel']) ? null : strToBool(cfg.tls),
"disable-sni": strToBool(cfg.tls_disable_sni),
...arrToObj([[(cfg.type in ['vmess', 'vless']) ? 'servername' : 'sni', cfg.tls_sni]]),
fingerprint: cfg.tls_fingerprint,
alpn: cfg.plugin in ['shadow-tls'] ? null : cfg.tls_alpn, // Array
alpn: cfg.plugin_type in ['shadow-tls', 'jls'] ? null : cfg.tls_alpn, // Array
"name-cert-verify": cfg.tls_name_cert_verify,
"skip-cert-verify": strToBool(cfg.tls_skip_cert_verify),
certificate: cfg.tls_cert_path, // mTLS
"private-key": cfg.masque_private_key || cfg.wireguard_private_key || cfg.ssh_priv_key || cfg.tls_key_path, // mTLS/SSH/WireGuard/Masque
@@ -827,11 +849,13 @@ uci.foreach(uciconf, uciprov, (cfg) => {
"udp-over-tcp": strToBool(cfg.override_uot),
up: cfg.override_up ? cfg.override_up + ' Mbps' : null,
down: cfg.override_down ? cfg.override_down + ' Mbps' : null,
"name-cert-verify": cfg.override_name_cert_verify,
"skip-cert-verify": cfg.override_skip_cert_verify ? strToBool(cfg.override_skip_cert_verify) || false : null,
"dialer-proxy": dialerproxy[cfg['.name']]?.detour,
"interface-name": cfg.override_interface_name,
"routing-mark": strToInt(cfg.override_routing_mark) || null,
"ip-version": cfg.override_ip_version
"ip-version": cfg.override_ip_version,
"override-expr": cfg.override_expr
},
/* General fields */
filter: parse_filter(cfg.filter),
@@ -53,7 +53,7 @@ uci.foreach(uciconf, uciserver, (cfg) => {
if (cfg.enabled === '0')
return;
push(config.listeners, parseListener(cfg, false));
push(config.listeners, parseListener(cfg));
});
/* Inbound END */
+52 -21
View File
@@ -211,23 +211,21 @@ export function parseVlessEncryption(payload, side) {
(isEmpty(content.keypairs) ? '' : '.' + join('.', map(content.keypairs, e => e[side]))); // Required
};
export function parseListener(cfg, isClient, label) {
export function parseListener(cfg) {
return {
name: cfg['.name'],
type: cfg.type,
listen: cfg.listen || '::',
port: strToInt(cfg.port),
...(isClient ? {
"routing-mark": strToInt(cfg.routing_mark) || null,
rule: cfg.rule,
proxy: label,
} : {}),
"routing-mark": strToInt(cfg.routing_mark) || null,
rule: cfg.rule,
proxy: cfg.proxy, // raw data need post-processing
/* HTTP / SOCKS / VMess / VLESS / Trojan / AnyTLS / Tuic / Hysteria2 */
users: (cfg.type in ['http', 'socks', 'mixed', 'vmess', 'vless', 'trojan', 'trusttunnel']) ? [
/* HTTP / SOCKS / Mieru / VMess / VLESS / Trojan / AnyTLS / Tuic / Hysteria2 / ShadowQUIC / TrustTunnel */
users: (cfg.type in ['http', 'socks', 'mixed', 'vmess', 'vless', 'trojan', 'shadowquic', 'trusttunnel']) ? [
(cfg.username || cfg.vmess_uuid) ? {
/* HTTP / SOCKS */
/* HTTP / SOCKS / Trojan / ShadowQUIC / TrustTunnel */
username: cfg.username,
password: cfg.password,
@@ -291,7 +289,6 @@ export function parseListener(cfg, isClient, label) {
"padding-scheme": cfg.anytls_padding_scheme,
/* Tuic */
"max-idle-time": durationToSecond(cfg.tuic_max_idle_time),
"authentication-timeout": durationToSecond(cfg.tuic_authentication_timeout),
"max-udp-relay-packet-size": strToInt(cfg.tuic_max_udp_relay_packet_size),
@@ -326,14 +323,38 @@ export function parseListener(cfg, isClient, label) {
"trusted-proxy-header": cfg.hysteria2_realmserver_trusted_proxy_header,
"realm-name-pattern": cfg.hysteria2_realmserver_realm_name_pattern,
/* ShadowQUIC */
"quic-versions": cfg.shadowquic_quic_versions,
"zero-rtt": strToBool(cfg.shadowquic_zero_rtt),
"jls-upstream": cfg.type === 'shadowquic' ? {
addr: cfg.plugin_opts_handshake_dest,
sni: cfg.tls_sni,
proxy: cfg.plugin_opts_dest_proxy, // raw data need post-processing
"rate-limit": strToInt(cfg.plugin_opts_rate_limit),
"quic-version-probe": strToBool(cfg.plugin_opts_quic_version_probe)
} : null,
// @# cwnd: 10 # default: 32,
// @# max-datagram-frame-size: 1400,
// @# recv-window-conn: 0,
// @# recv-window: 0,
// @# disable-mtu-discovery: false,
/* TrustTunnel */
/* Tunnel */
target: cfg.tunnel_target,
/* Extra fields */
"congestion-controller": cfg.congestion_controller,
"bbr-profile": cfg.bbr_profile,
"max-idle-time": durationToSecond(cfg.max_idle_time),
network: cfg.network,
udp: cfg.udp === '0' ? false : true,
/* Plugin fields */
...(cfg.plugin ? (
cfg.plugin === 'obfs' ? (
...(cfg.plugin === '1' ? (
cfg.plugin_type === 'obfs' ? (
// obfs-simple
cfg.type === 'snell' ? {
// snell
@@ -348,7 +369,7 @@ export function parseListener(cfg, isClient, label) {
mode: cfg.plugin_opts_obfsmode
}
}
) : cfg.plugin === 'shadow-tls' ? {
) : cfg.plugin_type === 'shadow-tls' ? {
// shadow-tls
"shadow-tls": {
enable: true,
@@ -365,7 +386,7 @@ export function parseListener(cfg, isClient, label) {
dest: cfg.plugin_opts_handshake_dest
}
}
} : cfg.plugin === 'restls' ? {
} : cfg.plugin_type === 'restls' ? {
// restls
"res-tls": {
enable: true,
@@ -373,17 +394,27 @@ export function parseListener(cfg, isClient, label) {
password: cfg.plugin_opts_thetlspassword,
"restls-script": cfg.plugin_opts_restls_script,
//"min-record-len": 0,
//proxy: ""
proxy: cfg.plugin_opts_dest_proxy // raw data need post-processing
}
} : cfg.plugin_type === 'jls' ? {
// jls
"jls-config": {
enable: true,
users: [
{
username: cfg.plugin_opts_thetlsusername,
password: cfg.plugin_opts_thetlspassword
}
],
dest: cfg.plugin_opts_handshake_dest,
sni: cfg.tls_sni,
alpn: cfg.tls_alpn,
proxy: cfg.plugin_opts_dest_proxy, // raw data need post-processing
"rate-limit": strToInt(cfg.plugin_opts_rate_limit)
}
} : {}
) : {}),
/* Extra fields */
"congestion-controller": cfg.congestion_controller,
"bbr-profile": cfg.bbr_profile,
network: cfg.network,
udp: cfg.udp === '0' ? false : true,
/* TLS fields */
...(cfg.allow_insecure === '1' ? { "allow-insecure": true } : cfg.tls === '1' ? {
alpn: cfg.tls_alpn,