mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-30 13:35:13 +08:00
🐤 Sync 2026-10-03 00:12:36
This commit is contained in:
1 parent
ce3df55b24
commit
cb1d978497
58 files changed
+1627
-1018
No files matched your search
@@ -44,20 +44,15 @@ gen_set_definition() {
|
||||
[ -n "$uci_elems" ] && { [ -n "$elems" ] && elems="${elems}, "; elems="${elems}${uci_elems}"; }
|
||||
|
||||
file_path=$(uci -q get "$CONFIG.$section.file_path")
|
||||
download_url=$(uci -q get "$CONFIG.$section.download_url")
|
||||
if [ -n "$download_url" ] && [ -n "$file_path" ]; then
|
||||
if [ ! -f "$file_path" ]; then
|
||||
echo "Downloading $section data from $download_url to $file_path..." >&2
|
||||
wget -q -O "$file_path" "$download_url" --timeout=10 --no-check-certificate
|
||||
[ $? -ne 0 ] && { echo "Failed to download $section data" >&2; rm -f "$file_path"; }
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$file_path" ] && [ -f "$file_path" ]; then
|
||||
local file_elems=$(get_file_elements "$file_path")
|
||||
if [ -n "$file_elems" ]; then
|
||||
[ -n "$elems" ] && elems="${elems}, "
|
||||
elems="${elems}${file_elems}"
|
||||
if [ -n "$file_path" ]; then
|
||||
if [ -f "$file_path" ]; then
|
||||
local file_elems=$(get_file_elements "$file_path")
|
||||
if [ -n "$file_elems" ]; then
|
||||
[ -n "$elems" ] && elems="${elems}, "
|
||||
elems="${elems}${file_elems}"
|
||||
fi
|
||||
else
|
||||
log_debug "Set file $file_path not found, continuing without file elements"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -183,15 +178,19 @@ TCP_ENABLED=$(uci -q get "$CONFIG.global.tcp_enabled" || echo "1")
|
||||
UDP_ENABLED=$(uci -q get "$CONFIG.global.udp_enabled" || echo "1")
|
||||
TRAFFIC_MARK=$(uci -q get "$CONFIG.global.traffic_mark" || echo "0x666")
|
||||
PROXY_SERVER_IP_ADDR=$(uci -q get "$CONFIG.global.proxy_server_ip_addr")
|
||||
INTERFACE=$(uci -q get "$CONFIG.global.interface")
|
||||
[ -z "$INTERFACE" ] && INTERFACE="br-lan"
|
||||
|
||||
if [ "$TCP_ENABLED" = "1" ]; then
|
||||
cat >> "$OUTPUT_FILE" << EOF
|
||||
chain LAN_MARKFLOW_TCP {
|
||||
type filter hook prerouting priority mangle; policy accept;
|
||||
iifname != "$INTERFACE" return
|
||||
fib daddr type { unspec, local, anycast, multicast } counter return
|
||||
EOF
|
||||
if [ -n "$PROXY_SERVER_IP_ADDR" ]; then
|
||||
echo " ip saddr $PROXY_SERVER_IP_ADDR ip protocol tcp counter return" >> "$OUTPUT_FILE"
|
||||
echo " ip saddr $PROXY_SERVER_IP_ADDR counter return" >> "$OUTPUT_FILE"
|
||||
echo " ip daddr $PROXY_SERVER_IP_ADDR counter return" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
for s in $SECTIONS_TCP; do process_rule "$s" "tcp" >> "$OUTPUT_FILE"; done
|
||||
echo " ip protocol tcp counter meta mark set $TRAFFIC_MARK" >> "$OUTPUT_FILE"
|
||||
@@ -202,10 +201,12 @@ if [ "$UDP_ENABLED" = "1" ]; then
|
||||
cat >> "$OUTPUT_FILE" << EOF
|
||||
chain LAN_MARKFLOW_UDP {
|
||||
type filter hook prerouting priority mangle; policy accept;
|
||||
iifname != "$INTERFACE" return
|
||||
fib daddr type { unspec, local, anycast, multicast } counter return
|
||||
EOF
|
||||
if [ -n "$PROXY_SERVER_IP_ADDR" ]; then
|
||||
echo " ip saddr $PROXY_SERVER_IP_ADDR ip protocol udp counter return" >> "$OUTPUT_FILE"
|
||||
echo " ip saddr $PROXY_SERVER_IP_ADDR counter return" >> "$OUTPUT_FILE"
|
||||
echo " ip daddr $PROXY_SERVER_IP_ADDR counter return" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
for s in $SECTIONS_UDP; do process_rule "$s" "udp" >> "$OUTPUT_FILE"; done
|
||||
echo " ip protocol udp counter meta mark set $TRAFFIC_MARK" >> "$OUTPUT_FILE"
|
||||
|
||||
@@ -13,11 +13,6 @@
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "flowproxy" ],
|
||||
"file": {
|
||||
"/usr/bin/wget": [ "exec" ],
|
||||
"/usr/bin/wc": [ "exec" ],
|
||||
"/usr/share/flowproxy/generate_nft.sh": [ "exec" ]
|
||||
},
|
||||
"ubus": {
|
||||
"luci.flowproxy": [ "*" ]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import { access, readfile, writefile, stat } from 'fs';
|
||||
import { access, readfile, writefile, stat, popen } from 'fs';
|
||||
import { cursor } from 'uci';
|
||||
import { connect } from 'ubus';
|
||||
|
||||
@@ -9,6 +9,7 @@ const STATE_FILE = '/var/run/flowproxy.running';
|
||||
const IP_CACHE = '/tmp/flowproxy/lan_ip.cache';
|
||||
const LOG_FILE = '/var/log/flowproxy.log';
|
||||
const NFT_TABLE = 'flowproxy';
|
||||
const DNS_DROPIN_FILE = '/tmp/dnsmasq.d/flowproxy.conf';
|
||||
|
||||
// 辅助函数:安全 trim
|
||||
function safe_trim(str) {
|
||||
@@ -18,10 +19,10 @@ function safe_trim(str) {
|
||||
const methods = {
|
||||
get_status: {
|
||||
call: function() {
|
||||
// 1. 快速探测
|
||||
// 1. 快速探测标记文件
|
||||
let is_running = access(STATE_FILE, 'f');
|
||||
|
||||
// 2. 自愈:检查内核状态并同步标记文件
|
||||
// 2. 自愈:检查内核状态 (nft 链与策略路由)
|
||||
let tcp_active = (system('nft list chain inet ' + NFT_TABLE + ' LAN_MARKFLOW_TCP >/dev/null 2>&1') === 0);
|
||||
let udp_active = (system('nft list chain inet ' + NFT_TABLE + ' LAN_MARKFLOW_UDP >/dev/null 2>&1') === 0);
|
||||
let real_running = (tcp_active || udp_active);
|
||||
@@ -40,7 +41,6 @@ const methods = {
|
||||
if (ubus_conn) {
|
||||
let ifaces = ubus_conn.call('network.interface', 'dump');
|
||||
if (type(ifaces?.interface) === 'array') {
|
||||
// 优先寻找名为 'lan' 的接口,或者寻找拥有 ipv4 地址的第一个非回环接口
|
||||
let fallback_ip = '';
|
||||
for (let iface in ifaces.interface) {
|
||||
if (iface.interface === 'lan' && iface['ipv4-address']?.[0]?.address) {
|
||||
@@ -64,9 +64,8 @@ const methods = {
|
||||
}
|
||||
|
||||
let uci_cursor = cursor();
|
||||
|
||||
let proxy_server_ip_addr = uci_cursor.get(UCI_CONFIG, 'global', 'proxy_server_ip_addr') || '';
|
||||
let dns_running = (uci_cursor.get(UCI_CONFIG, 'dns_backup') ? 1 : 0);
|
||||
let dns_running = access(DNS_DROPIN_FILE, 'f') ? 1 : 0;
|
||||
|
||||
return {
|
||||
running: real_running ? 1 : 0,
|
||||
@@ -114,6 +113,67 @@ const methods = {
|
||||
}
|
||||
},
|
||||
|
||||
get_dataset_info: {
|
||||
args: { file_path: 'string' },
|
||||
call: function(request) {
|
||||
let file_path = request.args?.file_path || '/usr/share/flowproxy/chnroute.txt';
|
||||
if (!match(file_path, /^\/(usr\/share\/flowproxy|tmp\/flowproxy)\/[a-zA-Z0-9_.-]+$/)) {
|
||||
return { error: 'Invalid path' };
|
||||
}
|
||||
if (!access(file_path, 'r')) {
|
||||
return { exists: false, lines: 0, size: 0 };
|
||||
}
|
||||
let s = stat(file_path);
|
||||
let lines = 0;
|
||||
let fd = popen(sprintf("wc -l '%s' 2>/dev/null", file_path));
|
||||
if (fd) {
|
||||
let out = fd.read('all');
|
||||
fd.close();
|
||||
if (out) {
|
||||
let parts = split(trim(out), /\s+/);
|
||||
lines = int(parts[0]) || 0;
|
||||
}
|
||||
}
|
||||
return { exists: true, lines: lines, size: s ? s.size : 0 };
|
||||
}
|
||||
},
|
||||
|
||||
update_dataset: {
|
||||
args: { url: 'string', file_path: 'string' },
|
||||
call: function(request) {
|
||||
let url = request.args?.url;
|
||||
let file_path = request.args?.file_path || '/usr/share/flowproxy/chnroute.txt';
|
||||
if (!url || !match(url, /^https?:\/\/[A-Za-z0-9_.\/:~%#?&=+-]+$/)) {
|
||||
return { success: false, error: 'Invalid URL' };
|
||||
}
|
||||
if (!match(file_path, /^\/(usr\/share\/flowproxy|tmp\/flowproxy)\/[a-zA-Z0-9_.-]+$/)) {
|
||||
return { success: false, error: 'Invalid target file path' };
|
||||
}
|
||||
let tmp_file = file_path + '.tmp';
|
||||
let cmd = sprintf("wget -q -O '%s' '%s' --timeout=15 --no-check-certificate 2>&1", tmp_file, url);
|
||||
let rc = system(cmd);
|
||||
if (rc === 0 && access(tmp_file, 'f')) {
|
||||
let s = stat(tmp_file);
|
||||
if (s && s.size > 0) {
|
||||
system(sprintf("mv -f '%s' '%s'", tmp_file, file_path));
|
||||
let lines = 0;
|
||||
let fd = popen(sprintf("wc -l '%s' 2>/dev/null", file_path));
|
||||
if (fd) {
|
||||
let out = fd.read('all');
|
||||
fd.close();
|
||||
if (out) {
|
||||
let parts = split(trim(out), /\s+/);
|
||||
lines = int(parts[0]) || 0;
|
||||
}
|
||||
}
|
||||
return { success: true, lines: lines };
|
||||
}
|
||||
}
|
||||
system(sprintf("rm -f '%s'", tmp_file));
|
||||
return { success: false, error: 'Download failed or file empty' };
|
||||
}
|
||||
},
|
||||
|
||||
generate_nft_config: {
|
||||
call: function() {
|
||||
system('mkdir -p /tmp/flowproxy');
|
||||
@@ -125,19 +185,18 @@ const methods = {
|
||||
get_runtime_config: {
|
||||
call: function() {
|
||||
let res_file = '/tmp/flowproxy/runtime.tmp';
|
||||
let dns_file = '/tmp/flowproxy/dns_runtime.tmp';
|
||||
|
||||
system('mkdir -p /tmp/flowproxy');
|
||||
system('/usr/share/flowproxy/generate_nft.sh runtime > ' + res_file + ' 2>&1');
|
||||
let nft_runtime = readfile(res_file) || "(failed)";
|
||||
system('rm -f ' + res_file);
|
||||
|
||||
system('uci show dhcp.@dnsmasq[0] | grep -E "noresolv|dns_redirect|server" | sed -E "s/^dhcp\\.[^.]*\\.([^=]*)=(.*)/\\1: \\2/; s/\\x27//g; s/#/:/g" > ' + dns_file + ' 2>&1');
|
||||
let dns_out = readfile(dns_file);
|
||||
system('rm -f ' + dns_file);
|
||||
|
||||
let dns_runtime = "\n--- [ DNSmasq Runtime Configuration ] ---\n";
|
||||
dns_runtime += (dns_out || "(no active dnsmasq overrides)");
|
||||
let dns_runtime = "\n--- [ DNSmasq Drop-in Runtime Configuration ] ---\n";
|
||||
let dns_content = readfile(DNS_DROPIN_FILE);
|
||||
if (dns_content) {
|
||||
dns_runtime += dns_content;
|
||||
} else {
|
||||
dns_runtime += "(no active dnsmasq drop-in overrides)";
|
||||
}
|
||||
|
||||
return { runtime: safe_trim(nft_runtime + dns_runtime) };
|
||||
}
|
||||
@@ -149,7 +208,6 @@ const methods = {
|
||||
try {
|
||||
let ubus_conn = connect();
|
||||
if (ubus_conn) {
|
||||
// 使用 network.device status 以获取所有物理设备 (包括 eth0 等 bridge 成员)
|
||||
let dev_status = ubus_conn.call('network.device', 'status');
|
||||
if (dev_status) {
|
||||
for (let name in dev_status) {
|
||||
|
||||
Reference in new issue
Block a user