mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-09 05:27:59 +08:00
⛄ Sync 2026-07-31 00:26:24
This commit is contained in:
1 parent
47d0743808
commit
b44a4364c4
125 files changed
+3954
-140418
No files matched your search
@@ -8,7 +8,14 @@
|
||||
'use strict';
|
||||
|
||||
import { cursor } from 'uci';
|
||||
import { isEmpty, parseURL, validation } from 'homeproxy';
|
||||
import { executeCommand, isEmpty, parseURL, validation } from 'homeproxy';
|
||||
import {
|
||||
format_controller,
|
||||
is_portable_bind_host,
|
||||
local_ipv4_addresses,
|
||||
normalize_local_controller_option,
|
||||
parse_controller
|
||||
} from '/etc/homeproxy/scripts/clash_api.uc';
|
||||
|
||||
const uci = cursor();
|
||||
|
||||
@@ -25,8 +32,37 @@ const uciinfra = 'infra',
|
||||
ucirouting = 'routing',
|
||||
uciroutingnode = 'routing_node',
|
||||
uciroutingrule = 'routing_rule',
|
||||
ucisubscription = 'subscription',
|
||||
uciserver = 'server';
|
||||
|
||||
/* Generate a random 256-bit hex secret for the Clash API. Returns null when no
|
||||
* usable randomness source is available, in which case the caller leaves the
|
||||
* secret unset rather than installing a predictable value. */
|
||||
function generateClashSecret() {
|
||||
let secret = trim(executeCommand("head -c 32 /dev/urandom | hexdump -v -e '1/1 \"%02x\"'")?.stdout || '');
|
||||
if (!match(secret, /^[a-f0-9]{64}$/))
|
||||
secret = trim(executeCommand('tr -dc a-f0-9 < /dev/urandom | head -c 64')?.stdout || '');
|
||||
|
||||
return match(secret, /^[a-f0-9]{32,}$/) ? secret : null;
|
||||
}
|
||||
|
||||
function normalizeLocalControllerOptions() {
|
||||
let local_addresses = local_ipv4_addresses((command) => executeCommand(command)?.stdout || ''),
|
||||
fallback_host = local_addresses[0];
|
||||
|
||||
if (isEmpty(fallback_host))
|
||||
return;
|
||||
|
||||
/* clash_api_external_controller is intentionally pinned to loopback (see
|
||||
* below) and must NOT be rewritten to the LAN address. Only the LAN-facing
|
||||
* display proxy is bound to a reachable local address here. */
|
||||
for (let item in [
|
||||
[ 'clash_api_proxy_external_controller', 9091, true ]
|
||||
])
|
||||
normalize_local_controller_option(uci, uciconfig, ucimain,
|
||||
local_addresses, fallback_host, item[0], item[1], item[2]);
|
||||
}
|
||||
|
||||
/* chinadns-ng has been removed */
|
||||
if (uci.get(uciconfig, uciinfra, 'china_dns_port'))
|
||||
uci.delete(uciconfig, uciinfra, 'china_dns_port');
|
||||
@@ -75,6 +111,56 @@ if (isEmpty(uci.get(uciconfig, ucimain, 'log_level')))
|
||||
if (isEmpty(uci.get(uciconfig, uciserver, 'log_level')))
|
||||
uci.set(uciconfig, uciserver, 'log_level', 'warn');
|
||||
|
||||
if (isEmpty(uci.get(uciconfig, ucisubscription, 'allow_unsupported_tls_pin_fallback')))
|
||||
uci.set(uciconfig, ucisubscription, 'allow_unsupported_tls_pin_fallback', '0');
|
||||
|
||||
/* Clash API dashboard integration */
|
||||
if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_enabled')))
|
||||
uci.set(uciconfig, ucimain, 'clash_api_enabled', '1');
|
||||
|
||||
/* Bind sing-box's own Clash API controller to loopback so it is never
|
||||
* reachable directly from the LAN; dashboards reach it only through the
|
||||
* filtering display proxy. Existing LAN-bound controllers are migrated to
|
||||
* 127.0.0.1 once (port preserved); a later deliberate change is left alone. */
|
||||
const clash_external = uci.get(uciconfig, ucimain, 'clash_api_external_controller');
|
||||
if (isEmpty(clash_external)) {
|
||||
uci.set(uciconfig, ucimain, 'clash_api_external_controller', '127.0.0.1:9090');
|
||||
} else if (isEmpty(uci.get(uciconfig, ucimigration, 'clash_api_localhost'))) {
|
||||
const clash_controller = parse_controller(clash_external, 9090);
|
||||
if (!is_portable_bind_host(clash_controller.host))
|
||||
uci.set(uciconfig, ucimain, 'clash_api_external_controller',
|
||||
format_controller('127.0.0.1', clash_controller.port || 9090));
|
||||
}
|
||||
uci.set(uciconfig, ucimigration, 'clash_api_localhost', '1');
|
||||
|
||||
/* sing-box's Clash API performs NO authentication when the secret is empty,
|
||||
* and the LAN-facing display proxy forwards to it, so anyone able to reach the
|
||||
* proxy could otherwise control the proxy without credentials. Generate a
|
||||
* random secret when none is configured. */
|
||||
if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_secret'))) {
|
||||
const clash_secret = generateClashSecret();
|
||||
if (!isEmpty(clash_secret))
|
||||
uci.set(uciconfig, ucimain, 'clash_api_secret', clash_secret);
|
||||
}
|
||||
|
||||
normalizeLocalControllerOptions();
|
||||
|
||||
if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_default_mode')))
|
||||
uci.set(uciconfig, ucimain, 'clash_api_default_mode', 'Rule');
|
||||
|
||||
if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_allow_origin'))) {
|
||||
uci.add_list(uciconfig, ucimain, 'clash_api_allow_origin', 'https://metacubex.github.io');
|
||||
uci.add_list(uciconfig, ucimain, 'clash_api_allow_origin', 'https://metacubexd.pages.dev');
|
||||
uci.add_list(uciconfig, ucimain, 'clash_api_allow_origin', 'http://d.metacubex.one');
|
||||
uci.add_list(uciconfig, ucimain, 'clash_api_allow_origin', 'https://yacd.metacubex.one');
|
||||
}
|
||||
|
||||
if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_allow_private_network')))
|
||||
uci.set(uciconfig, ucimain, 'clash_api_allow_private_network', '1');
|
||||
|
||||
if (isEmpty(uci.get(uciconfig, ucimain, 'metacubexd_url')))
|
||||
uci.set(uciconfig, ucimain, 'metacubexd_url', 'https://metacubexd.pages.dev/#/overview');
|
||||
|
||||
/* empty value defaults to all ports now */
|
||||
if (uci.get(uciconfig, ucimain, 'routing_port') === 'all')
|
||||
uci.delete(uciconfig, ucimain, 'routing_port');
|
||||
|
||||
Reference in new issue
Block a user