mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 12:43:56 +08:00
🎈 Sync 2026-08-24 18:23:48
This commit is contained in:
1 parent
91bee6a90e
commit
6b8877f5e1
119 files changed
+2501
-2677
No files matched your search
+2
-2
@@ -5,8 +5,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=hysteria
|
||||
PKG_VERSION:=2.12.1
|
||||
PKG_RELEASE:=15
|
||||
PKG_VERSION:=2.12.2
|
||||
PKG_RELEASE:=16
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/apernet/hysteria/tar.gz/app/v$(PKG_VERSION)?
|
||||
|
||||
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=librespeed-common
|
||||
PKG_VERSION:=1.0.0
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
PKG_MAINTAINER:=Josef Schlehofer <pepe.schlehofer@gmail.com>
|
||||
PKG_LICENSE:=GPL-2.0-only
|
||||
@@ -21,7 +21,8 @@ define Package/librespeed-common
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=LibreSpeed measurement orchestration
|
||||
DEPENDS:=+librespeed-cli +rpcd-mod-ucode +jsonfilter
|
||||
DEPENDS:=+librespeed-cli +rpcd-mod-ucode +jsonfilter +ucode +ucode-mod-fs \
|
||||
+ucode-mod-uci +jshn
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import { open, readfile, writefile, rename, mkdir, error } from 'fs';
|
||||
import { open, readfile, rename, mkdir, unlink, error } from 'fs';
|
||||
|
||||
// Packaging checks probe every executable for these.
|
||||
if (length(ARGV) > 0) {
|
||||
@@ -176,12 +176,25 @@ const dir = replace(archive_path, /\/[^\/]+$/, '');
|
||||
if (dir != '' && dir != archive_path)
|
||||
mkdir(dir, 0o755);
|
||||
|
||||
// Atomic: a reader never sees a half-written archive. A failed write goes to
|
||||
// syslog: this runs from cron, where stderr has nowhere to go. The reason
|
||||
// comes along, since a missing mount, a read-only filesystem and a full disk
|
||||
// each want something different from whoever reads that log.
|
||||
if (writefile(tmp, out) != null)
|
||||
// Atomic: a reader never sees a half-written archive. Written by hand
|
||||
// rather than writefile(), which drops fclose()'s status and would let a
|
||||
// full disk truncate the archive in silence -- flush() is where a short
|
||||
// write surfaces. A failed write goes to syslog: this runs from cron,
|
||||
// where stderr has nowhere to go. The reason comes along, since a missing
|
||||
// mount, a read-only filesystem and a full disk each want something
|
||||
// different from whoever reads that log.
|
||||
const af = open(tmp, 'w');
|
||||
let wrote = af != null && af.write(out) == length(out);
|
||||
|
||||
if (af) {
|
||||
wrote = af.flush() != null && wrote;
|
||||
af.close();
|
||||
}
|
||||
|
||||
if (wrote)
|
||||
rename(tmp, archive_path);
|
||||
else
|
||||
else {
|
||||
system(['logger', '-t', 'librespeed',
|
||||
`aggregate: cannot write ${tmp}: ${error()}`]);
|
||||
unlink(tmp);
|
||||
}
|
||||
@@ -78,9 +78,16 @@ sampler() {
|
||||
else printf "- -"
|
||||
}')
|
||||
prx=$rx; ptx=$tx
|
||||
# The runner may die without reaching its kill (SIGKILL, a trap that
|
||||
# never ran); without this check the sampler would rewrite state.json
|
||||
# forever and mask every later run's result.
|
||||
kill -0 $$ 2>/dev/null || return 0
|
||||
# An idle second keeps the last phase: the frontend reads an empty
|
||||
# phase as "not started yet" and would collapse mid-run.
|
||||
if [ "$1" = "-" ]; then
|
||||
write_state 1 $$ "$started" "" "" "" ""
|
||||
write_state 1 $$ "$started" "" "" "$phase" ""
|
||||
else
|
||||
phase=$1
|
||||
write_state 1 $$ "$started" "" "" "$1" "$2"
|
||||
fi
|
||||
done
|
||||
@@ -184,7 +191,9 @@ write_state 1 $$ "$started"
|
||||
# stop kills our whole process group, so librespeed-cli dies with us; ash runs
|
||||
# this trap once the foreground child has exited, and it records that the run
|
||||
# was stopped rather than pretending the measurement failed.
|
||||
trap 'write_state 0 "" "" "$(date +%s)" "stopped"; exit 1' TERM
|
||||
trap '[ -n "$sampler_pid" ] && kill "$sampler_pid" 2>/dev/null
|
||||
write_state 0 "" "" "$(date +%s)" "stopped"; exit 1' TERM
|
||||
sampler_pid=
|
||||
|
||||
if [ "$stream" = 1 ]; then
|
||||
# The while runs in a subshell, so the reports cannot come back in a
|
||||
@@ -213,18 +222,23 @@ if [ "$stream" = 1 ]; then
|
||||
# stream delivered: a client that failed never emitted a result event.
|
||||
out=$(cat "$STATE_DIR/reports.json" 2>/dev/null)
|
||||
rm -f "$STATE_DIR/reports.json"
|
||||
[ -n "$out" ] || \
|
||||
fail "$(tail -n 1 "$STATE_DIR/stderr.log" 2>/dev/null || echo 'measurement failed')"
|
||||
if [ -z "$out" ]; then
|
||||
# tail succeeds on an empty file, so the substitution guards the
|
||||
# value, not the command: an empty log still reports a failure.
|
||||
err=$(tail -n 1 "$STATE_DIR/stderr.log" 2>/dev/null)
|
||||
fail "${err:-measurement failed}"
|
||||
fi
|
||||
else
|
||||
sampler_pid=""
|
||||
if [ -n "$dev" ]; then
|
||||
sampler "$dev" &
|
||||
sampler_pid=$!
|
||||
fi
|
||||
out=$("$@" 2>"$STATE_DIR/stderr.log" < /dev/null); rc=$?
|
||||
[ -n "$sampler_pid" ] && kill "$sampler_pid" 2>/dev/null
|
||||
[ "$rc" = 0 ] || \
|
||||
fail "$(tail -n 1 "$STATE_DIR/stderr.log" 2>/dev/null || echo 'measurement failed')"
|
||||
if [ "$rc" != 0 ]; then
|
||||
err=$(tail -n 1 "$STATE_DIR/stderr.log" 2>/dev/null)
|
||||
fail "${err:-measurement failed (exit $rc)}"
|
||||
fi
|
||||
fi
|
||||
|
||||
finished=$(date +%s)
|
||||
@@ -346,9 +360,12 @@ if [ "$hist_enabled" = "1" ]; then
|
||||
# a gigabyte a year through the flash instead of a few megabytes. The
|
||||
# file therefore holds somewhat more than the window, and is trimmed
|
||||
# once enough has accumulated to be worth the write.
|
||||
# jshn writes '"epoch": 175...' with a space, so the match is
|
||||
# tolerant and the digits are extracted rather than offset-counted.
|
||||
expired=$(awk -v c="$cutoff" '
|
||||
match($0, /"epoch":[0-9]+/) {
|
||||
if (substr($0, RSTART + 8, RLENGTH - 8) + 0 < c) n++
|
||||
match($0, /"epoch":[[:space:]]*[0-9]+/) {
|
||||
v = substr($0, RSTART, RLENGTH); gsub(/[^0-9]/, "", v)
|
||||
if (v + 0 < c) n++
|
||||
}
|
||||
END { print n + 0 }
|
||||
' "$hist_path")
|
||||
@@ -357,8 +374,9 @@ if [ "$hist_enabled" = "1" ]; then
|
||||
if [ "$expired" -ge 50 ] || [ "$expired" -ge $(( total / 2 )) ] && [ "$expired" -gt 0 ]; then
|
||||
tmp="$hist_path.$$"
|
||||
awk -v c="$cutoff" '
|
||||
match($0, /"epoch":[0-9]+/) {
|
||||
if (substr($0, RSTART + 8, RLENGTH - 8) + 0 < c) next
|
||||
match($0, /"epoch":[[:space:]]*[0-9]+/) {
|
||||
v = substr($0, RSTART, RLENGTH); gsub(/[^0-9]/, "", v)
|
||||
if (v + 0 < c) next
|
||||
}
|
||||
{ print }
|
||||
' "$hist_path" > "$tmp" && mv "$tmp" "$hist_path"
|
||||
|
||||
@@ -15,6 +15,26 @@ AGG=/usr/libexec/librespeed-aggregate
|
||||
# random time is drawn from, drawn here at sync time. That keeps the herd
|
||||
# apart -- every router lands on its own minute -- without any process
|
||||
# sleeping through the night, at the cost of re-drawing on every reload.
|
||||
# Every comma-separated part must be a number or an ascending range within
|
||||
# [0, max]; the caller already reduced the alphabet to digits, commas and
|
||||
# dashes.
|
||||
valid_field() {
|
||||
local val="$1" max="$2" part a b oifs="$IFS"
|
||||
IFS=','
|
||||
for part in $val; do
|
||||
IFS="$oifs"
|
||||
a=${part%-*}; b=${part#*-}
|
||||
# Each half on its own: concatenated, '5-' and '-5' hide their empty
|
||||
# side and the arithmetic below would print a shell error where the
|
||||
# caller promises a silent fallback.
|
||||
case "$a" in ''|*[!0-9]*) return 1 ;; esac
|
||||
case "$b" in ''|*[!0-9]*) return 1 ;; esac
|
||||
[ "$a" -le "$max" ] && [ "$b" -le "$max" ] && [ "$a" -le "$b" ] || return 1
|
||||
done
|
||||
IFS="$oifs"
|
||||
return 0
|
||||
}
|
||||
|
||||
cron_expr() {
|
||||
local interval="$1" days="$2" hours="$3"
|
||||
local start end m h v
|
||||
@@ -77,8 +97,16 @@ sync_cron() {
|
||||
|
||||
# These end up verbatim in root's crontab, so anything unexpected becomes
|
||||
# the harmless default rather than a cron field it was not meant to be.
|
||||
case "$days" in *[!0-9,-]*) days='*' ;; '') days='*' ;; esac
|
||||
# Values are checked as well as characters: '99' is made of digits, but
|
||||
# as an hour it would turn a daily schedule into an hourly one.
|
||||
case "$days" in *[!0-9,-]*|'') days='*' ;; esac
|
||||
if [ "$days" != '*' ] && ! valid_field "$days" 6; then
|
||||
days='*'
|
||||
fi
|
||||
case "$hours" in *[!0-9-]*) hours='' ;; esac
|
||||
if [ -n "$hours" ] && ! valid_field "$hours" 23; then
|
||||
hours=''
|
||||
fi
|
||||
|
||||
mkdir -p "${CRONTAB%/*}"
|
||||
touch "$CRONTAB"
|
||||
|
||||
@@ -78,6 +78,11 @@ function config_get(uci, section, option, fallback) {
|
||||
// browser: the schedule fires in the router's timezone, and the browser may
|
||||
// well sit in another one. Understands only the shapes librespeed.init
|
||||
// emits: numbers, ranges, ranges with a step, star, and comma lists.
|
||||
// Hoisted: ucode recompiles a regex literal on every evaluation, and these
|
||||
// two dominate cron_next's cost inside rpcd, which must never stall.
|
||||
const CRON_STEP = /^(.+)\/([0-9]+)$/;
|
||||
const CRON_RANGE = /^([0-9]+)-([0-9]+)$/;
|
||||
|
||||
function cron_next(line, count) {
|
||||
const f = split(trim(line ?? ''), /\s+/);
|
||||
|
||||
@@ -87,7 +92,7 @@ function cron_next(line, count) {
|
||||
const match_field = function(pat, val) {
|
||||
for (let part in split(pat, ',')) {
|
||||
let step = 1;
|
||||
let m = match(part, /^(.+)\/([0-9]+)$/);
|
||||
let m = match(part, CRON_STEP);
|
||||
|
||||
if (m) {
|
||||
part = m[1];
|
||||
@@ -101,7 +106,7 @@ function cron_next(line, count) {
|
||||
b = 59;
|
||||
}
|
||||
else {
|
||||
m = match(part, /^([0-9]+)-([0-9]+)$/);
|
||||
m = match(part, CRON_RANGE);
|
||||
if (m) {
|
||||
a = int(m[1]);
|
||||
b = int(m[2]);
|
||||
@@ -123,14 +128,36 @@ function cron_next(line, count) {
|
||||
let t = time();
|
||||
t -= t % 60;
|
||||
|
||||
for (let i = 0; i < 8 * 24 * 60 && length(out) < count; i++) {
|
||||
// A miss skips the rest of the day or hour instead of walking its
|
||||
// minutes; that keeps this cheap inside rpcd's event loop, and cheap
|
||||
// enough for a five-week horizon, which a weekly schedule needs to
|
||||
// fill three rows where eight days could not. The day jump aims at
|
||||
// 23:00, not midnight: it is computed in local minutes but applied as
|
||||
// real ones, and across a spring-forward that lands an hour long --
|
||||
// from 23:00 the hour branch walks the last hour and cannot overshoot
|
||||
// into minutes that were never examined.
|
||||
for (let i = 0; i < 35 * 24 * 60 && length(out) < count; ) {
|
||||
t += 60;
|
||||
const lt = localtime(t);
|
||||
let skip;
|
||||
|
||||
// % 7 folds both weekday conventions onto cron's 0-6 with Sunday 0.
|
||||
if (match_field(f[0], lt.min) && match_field(f[1], lt.hour) &&
|
||||
match_field(f[4], lt.wday % 7))
|
||||
push(out, t);
|
||||
if (!match_field(f[4], lt.wday % 7)) {
|
||||
skip = (24 - lt.hour) * 60 - lt.min - 60;
|
||||
if (skip <= 0)
|
||||
skip = 60 - lt.min;
|
||||
}
|
||||
else if (!match_field(f[1], lt.hour))
|
||||
skip = 60 - lt.min;
|
||||
else {
|
||||
if (match_field(f[0], lt.min))
|
||||
push(out, t);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
t += (skip - 1) * 60;
|
||||
i += skip;
|
||||
}
|
||||
|
||||
return out;
|
||||
@@ -182,8 +209,12 @@ const methods = {
|
||||
|
||||
if (st.pid)
|
||||
out.pid = int(st.pid);
|
||||
if (st.started)
|
||||
if (st.started) {
|
||||
out.started = int(st.started);
|
||||
// Elapsed is computed here, on the clock that stamped
|
||||
// started: the browser's clock may sit anywhere.
|
||||
out.elapsed = time() - int(st.started);
|
||||
}
|
||||
if (st.mbps != null)
|
||||
out.mbps = st.mbps + 0.0;
|
||||
if (st.progress != null)
|
||||
@@ -297,7 +328,11 @@ const methods = {
|
||||
scheme: config_get(uci, 'main', 'scheme', 'auto'),
|
||||
server_list: config_get(uci, 'main', 'server_list', ''),
|
||||
schedule: {
|
||||
enabled: config_get(uci, 'schedule', 'enabled', '0') == '1',
|
||||
// What the crontab holds, not what UCI intends: a
|
||||
// hand-set 'true' satisfies the init script's bool but
|
||||
// not a string compare, and the page would say No while
|
||||
// cron fires. The line is the one source of truth.
|
||||
enabled: cron != '',
|
||||
interval: config_get(uci, 'schedule', 'interval', '1d'),
|
||||
days: config_get(uci, 'schedule', 'days', '*'),
|
||||
hours: config_get(uci, 'schedule', 'hours', ''),
|
||||
|
||||
@@ -23,4 +23,13 @@ sh -n /etc/init.d/librespeed || fail "init script does not parse"
|
||||
ucode /usr/share/rpcd/ucode/librespeed.uc >/dev/null \
|
||||
|| fail "rpcd plugin does not load"
|
||||
|
||||
# Retention must recognise epoch as jshn actually writes it -- with a space
|
||||
# after the colon. The fixture comes from json_dump itself, so the check
|
||||
# breaks if either side changes shape.
|
||||
line=$(. /usr/share/libubox/jshn.sh; json_init; json_add_int epoch 1; json_dump) \
|
||||
|| fail "jshn not usable"
|
||||
echo "$line" | awk 'match($0, /"epoch":[[:space:]]*[0-9]+/) { ok = 1 }
|
||||
{ print }
|
||||
END { exit !ok }' || fail "retention regex does not match jshn output"
|
||||
|
||||
echo "librespeed-common: installed files OK"
|
||||
@@ -12,7 +12,7 @@ PKG_ARCH_LINKEASE:=$(ARCH)
|
||||
PKG_NAME:=linkease-common-bin
|
||||
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
|
||||
PKG_SOURCE_DATE:=1.7.5
|
||||
PKG_RELEASE:=13
|
||||
PKG_RELEASE:=14
|
||||
|
||||
ARCH_HEXCODE:=
|
||||
ifeq ($(ARCH),x86_64)
|
||||
@@ -28,7 +28,7 @@ else ifeq ($(ARCH),mipsel)
|
||||
ARCH_HEXCODE=1b0c
|
||||
endif
|
||||
|
||||
PKG_SOURCE_VERSION:=70c21864a1e95ece2ae6e4b144ce2d7a68d0405f
|
||||
PKG_SOURCE_VERSION:=2036fce819b5a44574d07cca9927eae73da43efc
|
||||
PKG_SOURCE:=linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE)
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ PKG_ARCH_LINKEASE:=$(ARCH)
|
||||
PKG_NAME:=linkease
|
||||
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
|
||||
PKG_SOURCE_DATE:=1.7.5
|
||||
PKG_RELEASE:=16
|
||||
PKG_RELEASE:=17
|
||||
|
||||
ARCH_HEXCODE:=
|
||||
ifeq ($(ARCH),x86_64)
|
||||
@@ -28,7 +28,7 @@ else ifeq ($(ARCH),mipsel)
|
||||
ARCH_HEXCODE=1b0c
|
||||
endif
|
||||
|
||||
PKG_SOURCE_VERSION:=70c21864a1e95ece2ae6e4b144ce2d7a68d0405f
|
||||
PKG_SOURCE_VERSION:=2036fce819b5a44574d07cca9927eae73da43efc
|
||||
PKG_SOURCE:=linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE)
|
||||
|
||||
@@ -11,7 +11,7 @@ PKG_ARCH_LINKEASE:=$(ARCH)
|
||||
PKG_NAME:=linkeasefull
|
||||
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
|
||||
PKG_SOURCE_DATE:=3.0.12
|
||||
PKG_RELEASE:=15
|
||||
PKG_RELEASE:=16
|
||||
|
||||
ARCH_HEXCODE:=
|
||||
ifeq ($(ARCH),x86_64)
|
||||
@@ -24,7 +24,7 @@ LINKEASE_RUNTIME_ARCH:=arm64
|
||||
PKG_HASH:=skip
|
||||
endif
|
||||
|
||||
PKG_SOURCE_VERSION:=70c21864a1e95ece2ae6e4b144ce2d7a68d0405f
|
||||
PKG_SOURCE_VERSION:=2036fce819b5a44574d07cca9927eae73da43efc
|
||||
PKG_SOURCE:=linkease-runtime-$(PKG_SOURCE_DATE)-linux-$(LINKEASE_RUNTIME_ARCH).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkeasefull-runtime-v$(PKG_SOURCE_DATE)/
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-runtime-$(PKG_SOURCE_DATE)-linux-$(LINKEASE_RUNTIME_ARCH)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.0-r20260804
|
||||
PKG_RELEASE:=5
|
||||
PKG_VERSION:=1.0.0-r20260824
|
||||
PKG_RELEASE:=6
|
||||
|
||||
LUCI_TITLE:=LuCI support for arcadia
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -8,10 +8,9 @@ local m, s, o
|
||||
|
||||
m = taskd.docker_map("arcadia", "arcadia", "/usr/libexec/istorec/arcadia.sh",
|
||||
translate("Arcadia"),
|
||||
translate("Arcadia one-stop code operation and maintenance platform.")
|
||||
translate("Arcadia · One-Stop Code Automation & DevOps Platform.")
|
||||
.. translate("Official website:") .. ' <a href=\"https://arcadia.cool\" target=\"_blank\">https://arcadia.cool</a>'
|
||||
.. "<dl><dt>" .. translate("Arcadia is mainly aimed at scripting language programming and operation and maintenance, supports scheduled task scheduling, has a complete file system and underlying CLI command design, and is suitable for the development and operation and maintenance environment of small and medium-sized teams and individuals.") .. "</dt>"
|
||||
.. "<dt>" .. translate("The project is based on TypeScript full-stack development and adopts many cutting-edge technologies. Vue + Vite is used on the front end, and Node.js + Express + Prisma ORM is used on the back end.") .. "</dt>"
|
||||
.. "<dl><dt>" .. translate("Arcadia is designed for script-based programming and operations scenarios. It provides capabilities including scheduled task scheduling, multi-language code execution, a comprehensive file system, and well-designed underlying CLI commands. It is suitable for individual developers and small to medium-sized teams who seek to improve development and operations efficiency through automated scripting.") .. "</dt>"
|
||||
.. "<dt>" .. translate("The initial username and password are 'useradmin' and 'passwd' respectively.") .. "</dt>"
|
||||
.. "</dl>")
|
||||
|
||||
@@ -27,11 +26,11 @@ s.anonymous=true
|
||||
o = s:option(Value, "image", translate("Docker Image"))
|
||||
o.datatype = "string"
|
||||
o:value("", translate("Default"))
|
||||
o:value("supermanito/arcadia:beta", "supermanito/arcadia:beta")
|
||||
o:value("registry.cn-hangzhou.aliyuncs.com/supermanito/arcadia:beta", "registry.cn-hangzhou.aliyuncs.com/supermanito/arcadia:beta")
|
||||
o:value("docker.m.daocloud.io/supermanito/arcadia:beta", "docker.m.daocloud.io/supermanito/arcadia:beta")
|
||||
o:value("docker.1ms.run/supermanito/arcadia:beta", "docker.1ms.run/supermanito/arcadia:beta")
|
||||
o:value("docker.xuanyuan.me/supermanito/arcadia:beta", "docker.xuanyuan.me/supermanito/arcadia:beta")
|
||||
o:value("supermanito/arcadia", "supermanito/arcadia")
|
||||
o:value("registry.cn-hangzhou.aliyuncs.com/supermanito/arcadia", "registry.cn-hangzhou.aliyuncs.com/supermanito/arcadia")
|
||||
o:value("docker.m.daocloud.io/supermanito/arcadia", "docker.m.daocloud.io/supermanito/arcadia")
|
||||
o:value("docker.1ms.run/supermanito/arcadia", "docker.1ms.run/supermanito/arcadia")
|
||||
o:value("docker.xuanyuan.me/supermanito/arcadia", "docker.xuanyuan.me/supermanito/arcadia")
|
||||
|
||||
o = s:option(Flag, "hostnet", translate("Host network"), translate("Arcadia running in host network, port is always 5678 if enabled"))
|
||||
o.default = 0
|
||||
|
||||
@@ -4,17 +4,14 @@ msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
msgid "Official website:"
|
||||
msgstr "官方网站:"
|
||||
|
||||
msgid "Arcadia one-stop code operation and maintenance platform."
|
||||
msgstr "Arcadia 一站式代码运维平台。"
|
||||
msgid "Arcadia · One-Stop Code Automation & DevOps Platform."
|
||||
msgstr "Arcadia 一站式代码自动化运维平台。"
|
||||
|
||||
msgid "Arcadia is mainly aimed at scripting language programming and operation and maintenance, supports scheduled task scheduling, has a complete file system and underlying CLI command design, and is suitable for the development and operation and maintenance environment of small and medium-sized teams and individuals."
|
||||
msgstr "Arcadia 主要面向于脚本语言编程与运维,支持定时任务调度,有着完善的文件系统和底层CLI命令设计,适用于中小型团队与个人的开发与运维环境。"
|
||||
|
||||
msgid "The project is based on TypeScript full-stack development and adopts many cutting-edge technologies. Vue + Vite is used on the front end, and Node.js + Express + Prisma ORM is used on the back end."
|
||||
msgstr "项目基于 TypeScript 全栈开发,采用了众多前沿技术,前端使用 Vue + Vite,后端使用 Node.js + Express + Prisma ORM。"
|
||||
msgid "Arcadia is designed for script-based programming and operations scenarios. It provides capabilities including scheduled task scheduling, multi-language code execution, a comprehensive file system, and well-designed underlying CLI commands. It is suitable for individual developers and small to medium-sized teams who seek to improve development and operations efficiency through automated scripting."
|
||||
msgstr "Arcadia 平台面向脚本语言编程与运维场景,提供定时任务调度、多语言代码执行、完善的文件系统与底层 CLI 命令设计等能力,适用于希望借助自动化脚本提升开发运维效率的个人开发者与中小型团队。"
|
||||
|
||||
msgid "The initial username and password are 'useradmin' and 'passwd' respectively."
|
||||
msgstr "初始的用户名和密码分别是'useradmin'和'passwd'。"
|
||||
msgstr "初始的用户名和密码分别是 'useradmin' 和 'passwd'。"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
@@ -11,7 +11,7 @@ IMAGE_NAME='default'
|
||||
get_image() {
|
||||
IMAGE_NAME=`uci get arcadia.@arcadia[0].image 2>/dev/null`
|
||||
if [ -z "$IMAGE_NAME" -o "$IMAGE_NAME" == "default" ]; then
|
||||
IMAGE_NAME="supermanito/arcadia:beta"
|
||||
IMAGE_NAME="supermanito/arcadia"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ do_install_detail() {
|
||||
|
||||
[ -z "$port" ] && port=5678
|
||||
|
||||
local cmd="docker run --restart=unless-stopped -d -v \"$config/config:/arcadia/config\" -v \"$config/log:/arcadia/log\" -v \"$config/scripts:/arcadia/scripts\" -v \"$config/repo:/arcadia/repo\" -v \"$config/raw:/arcadia/raw\" -v \"$config/tgbot:/arcadia/tgbot\" "
|
||||
local cmd="docker run --restart=unless-stopped -d --cap-add SYS_PTRACE -v \"$config/config:/arcadia/config\" -v \"$config/log:/arcadia/log\" -v \"$config/scripts:/arcadia/scripts\" -v \"$config/repo:/arcadia/repo\" -v \"$config/raw:/arcadia/raw\" -v \"$config/tgbot:/arcadia/tgbot\" "
|
||||
if [ "$hostnet" = 1 ]; then
|
||||
cmd="$cmd\
|
||||
--dns=127.0.0.1 \
|
||||
|
||||
@@ -46,10 +46,6 @@ function download(name, mime, text) {
|
||||
window.URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
/* Bumped whenever librespeed.css changes, so a routine page load picks the
|
||||
* new stylesheet up instead of pairing new views with a cached old one. */
|
||||
const CSS_VERSION = '18';
|
||||
|
||||
function metricOf(key) {
|
||||
return METRICS.find(m => m[0] == key);
|
||||
}
|
||||
@@ -142,46 +138,79 @@ return baseclass.extend({
|
||||
GROUPS: GROUPS,
|
||||
RANGES: RANGES,
|
||||
|
||||
/* The app stylesheet, cache-busted by its own version: LuCI's resource
|
||||
* version only changes when luci-base does, which is not when we do. */
|
||||
/* Linked plainly, the way the other applications do: uhttpd serves
|
||||
* static resources with ETag revalidation, so an upgraded stylesheet
|
||||
* reaches the browser without a cache-busting version to maintain. */
|
||||
cssLink() {
|
||||
return E('link', {
|
||||
'rel': 'stylesheet',
|
||||
'href': L.resource('librespeed/librespeed.css') + '?v=' + CSS_VERSION
|
||||
'href': L.resource('librespeed/librespeed.css')
|
||||
});
|
||||
},
|
||||
|
||||
/* One token->label table for the schedule intervals: Settings builds
|
||||
* its choices from it and the Test page looks the status label up, so
|
||||
* the two cannot drift. The init script accepts more shapes than these
|
||||
* six, so readers must fall back to the raw token. */
|
||||
INTERVALS: {
|
||||
'15m': _('Every 15 minutes'),
|
||||
'30m': _('Every 30 minutes'),
|
||||
'1h': _('Hourly'),
|
||||
'6h': _('Every 6 hours'),
|
||||
'12h': _('Every 12 hours'),
|
||||
'1d': _('Daily')
|
||||
},
|
||||
|
||||
/* Exported alongside the chart: every timestamp a page prints should
|
||||
* come through here, or the date-only guard gets lost in a copy. */
|
||||
chartStampFull: chartStampFull,
|
||||
|
||||
/* Plain figures of one series: what is normal, how much it wobbles, and
|
||||
* where it stands now. The story sentences are built from these. */
|
||||
seriesStats(entries, metric) {
|
||||
* where it stands now. The story sentences are built from these. On
|
||||
* daily aggregates the extremes come from the _min/_max columns the
|
||||
* chart also draws -- min/max of the daily means would understate the
|
||||
* spread and contradict the band directly above the sentence. */
|
||||
seriesStats(entries, metric, resolution) {
|
||||
const vals = (entries || []).map(e => e[metric]).filter(v => typeof v == 'number');
|
||||
|
||||
if (!vals.length)
|
||||
return null;
|
||||
|
||||
const avg = vals.reduce((a, b) => a + b, 0) / vals.length;
|
||||
const lows = (resolution == '1d')
|
||||
? (entries || []).map(e => typeof e[metric + '_min'] == 'number'
|
||||
? e[metric + '_min'] : e[metric]).filter(v => typeof v == 'number')
|
||||
: vals;
|
||||
const highs = (resolution == '1d')
|
||||
? (entries || []).map(e => typeof e[metric + '_max'] == 'number'
|
||||
? e[metric + '_max'] : e[metric]).filter(v => typeof v == 'number')
|
||||
: vals;
|
||||
|
||||
return {
|
||||
count: vals.length,
|
||||
avg: avg,
|
||||
min: Math.min.apply(null, vals),
|
||||
max: Math.max.apply(null, vals),
|
||||
min: Math.min.apply(null, lows),
|
||||
max: Math.max.apply(null, highs),
|
||||
current: vals[vals.length - 1]
|
||||
};
|
||||
},
|
||||
|
||||
/* A row of toggle buttons; the active one is highlighted. */
|
||||
switcher(view, items, current, onpick) {
|
||||
return E('div', {}, items.map(it =>
|
||||
E('button', {
|
||||
'class': it[0] == current ? 'cbi-button cbi-button-action' : 'cbi-button',
|
||||
'style': 'margin-right:.3em',
|
||||
'click': ui.createHandlerFn(view, function() {
|
||||
return onpick.call(view, it[0]);
|
||||
})
|
||||
/* Callers hand in display-ready labels: a runtime _() here
|
||||
* would both miss the extractor and translate twice. */
|
||||
}, [ it[1] != null ? it[1] : it[0] ])));
|
||||
/* A row of toggle buttons; the active one is highlighted. The state is
|
||||
* also spoken: colour alone says nothing to a screen reader, so each
|
||||
* button carries aria-pressed and the group a name for what it picks. */
|
||||
switcher(view, items, current, onpick, label) {
|
||||
return E('div', { 'role': 'group', 'aria-label': label || null },
|
||||
items.map(it =>
|
||||
E('button', {
|
||||
'class': it[0] == current ? 'cbi-button cbi-button-action' : 'cbi-button',
|
||||
'style': 'margin-right:.3em',
|
||||
'aria-pressed': it[0] == current ? 'true' : 'false',
|
||||
'click': ui.createHandlerFn(view, function() {
|
||||
return onpick.call(view, it[0]);
|
||||
})
|
||||
/* Callers hand in display-ready labels: a runtime _() here
|
||||
* would both miss the extractor and translate twice. */
|
||||
}, [ it[1] != null ? it[1] : it[0] ])));
|
||||
},
|
||||
|
||||
/* The one chart component: hand-built SVG, the way the realtime status
|
||||
@@ -254,8 +283,9 @@ return baseclass.extend({
|
||||
const avg = valid.reduce((a, p) => a + p[2], 0) / valid.length;
|
||||
body += '<line class="librespeed-avgline librespeed-stroke-%d" x1="%d" y1="%f" x2="%d" y2="%f"/>'
|
||||
.format(ci, L, sc.ys(avg), W - R, sc.ys(avg));
|
||||
body += '<text x="%d" y="%f" font-size="9" fill="currentColor" fill-opacity=".55" text-anchor="end">avg %s</text>'
|
||||
.format(W - R, sc.ys(avg) - 4, avg.toFixed(avg >= 100 ? 0 : 1));
|
||||
body += '<text x="%d" y="%f" font-size="9" fill="currentColor" fill-opacity=".55" text-anchor="end">%h %s</text>'
|
||||
.format(W - R, sc.ys(avg) - 4, _('avg'),
|
||||
avg.toFixed(avg >= 100 ? 0 : 1));
|
||||
|
||||
body += (valid.length > 1)
|
||||
? '<polyline class="librespeed-line librespeed-stroke-%d" points="%s"/>'.format(ci, pts)
|
||||
@@ -314,7 +344,7 @@ return baseclass.extend({
|
||||
|
||||
opts.legend.all.forEach(k => {
|
||||
const m = metricOf(k);
|
||||
const st = this.seriesStats(entries, k);
|
||||
const st = this.seriesStats(entries, k, opts.resolution);
|
||||
const cb = E('input', { 'type': 'checkbox' });
|
||||
|
||||
cb.checked = opts.series.indexOf(k) >= 0;
|
||||
@@ -426,7 +456,8 @@ return baseclass.extend({
|
||||
if (typeof e[k] != 'number')
|
||||
return;
|
||||
let txt = fmtVal(e[k], m[2]);
|
||||
if (typeof e[k + '_min'] == 'number')
|
||||
if (typeof e[k + '_min'] == 'number' &&
|
||||
typeof e[k + '_max'] == 'number')
|
||||
txt += ' (%s – %s)'.format(
|
||||
e[k + '_min'].toFixed(m[2] == 'Mbps' ? 0 : 1),
|
||||
e[k + '_max'].toFixed(m[2] == 'Mbps' ? 0 : 1));
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/* The theme's accent where the theme publishes one: --primary-color-medium
|
||||
* exists only in luci-theme-bootstrap. Every other in-tree theme sees the
|
||||
* fallback, which must clear 3:1 against a light page -- the arc and the
|
||||
* history line are the only graphical encoding of the data. */
|
||||
:root {
|
||||
--librespeed-accent: var(--primary-color-medium, #3c8dbc);
|
||||
}
|
||||
|
||||
/* Dark is an attribute in LuCI, not a media preference: bootstrap stamps
|
||||
* data-darkmode on the root and pins it for its light/dark variants, while
|
||||
* the themes that actually reach the fallback have no dark mode at all --
|
||||
* an OS-level preference must not darken their light pages. */
|
||||
:root[data-darkmode="true"] {
|
||||
--librespeed-accent: var(--primary-color-medium, #6ab0de);
|
||||
}
|
||||
|
||||
/* The one piece of CSS this application owns: layout and type scale. Colors,
|
||||
* borders, buttons and spacing inside sections stay with the theme. */
|
||||
|
||||
@@ -55,31 +71,31 @@
|
||||
max-width: 20em;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
accent-color: var(--primary-color-medium, #5bc0de);
|
||||
accent-color: var(--librespeed-accent);
|
||||
}
|
||||
|
||||
/* The chart takes its color from the theme where one is exposed, and falls
|
||||
* back to a neutral accent where none is. */
|
||||
.librespeed-chart-line {
|
||||
stroke: var(--primary-color-medium, #5bc0de);
|
||||
stroke: var(--librespeed-accent);
|
||||
fill: none;
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
|
||||
.librespeed-chart-fill {
|
||||
fill: var(--primary-color-medium, #5bc0de);
|
||||
fill: var(--librespeed-accent);
|
||||
fill-opacity: .1;
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
.librespeed-chart-band {
|
||||
fill: var(--primary-color-medium, #5bc0de);
|
||||
fill: var(--librespeed-accent);
|
||||
fill-opacity: .18;
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
.librespeed-chart-dot {
|
||||
fill: var(--primary-color-medium, #5bc0de);
|
||||
fill: var(--librespeed-accent);
|
||||
}
|
||||
|
||||
.librespeed-toolbar {
|
||||
@@ -138,7 +154,7 @@
|
||||
|
||||
.librespeed-gauge-fill {
|
||||
fill: none;
|
||||
stroke: var(--primary-color-medium, #5bc0de);
|
||||
stroke: var(--librespeed-accent);
|
||||
stroke-width: 12;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
@@ -219,17 +235,17 @@
|
||||
/* One theme color for every series: the second one differs by pattern, not
|
||||
* by a hardcoded hue -- a dashed line and a striped swatch survive any theme
|
||||
* and read for color-blind users too. */
|
||||
.librespeed-stroke-0 { stroke: var(--primary-color-medium, #5bc0de); }
|
||||
.librespeed-stroke-1 { stroke: var(--primary-color-medium, #5bc0de); }
|
||||
.librespeed-stroke-0 { stroke: var(--librespeed-accent); }
|
||||
.librespeed-stroke-1 { stroke: var(--librespeed-accent); }
|
||||
polyline.librespeed-stroke-1 { stroke-dasharray: 6 3; }
|
||||
.librespeed-avgline.librespeed-stroke-1 { stroke-dasharray: 2 4; }
|
||||
.librespeed-fill-0 { fill: var(--primary-color-medium, #5bc0de); }
|
||||
.librespeed-fill-1 { fill: var(--primary-color-medium, #5bc0de); }
|
||||
.librespeed-fill-0 { fill: var(--librespeed-accent); }
|
||||
.librespeed-fill-1 { fill: var(--librespeed-accent); }
|
||||
circle.librespeed-fill-1 { fill-opacity: .55; }
|
||||
.librespeed-bg-0 { background: var(--primary-color-medium, #5bc0de); }
|
||||
.librespeed-bg-0 { background: var(--librespeed-accent); }
|
||||
.librespeed-bg-1 {
|
||||
background: repeating-linear-gradient(90deg,
|
||||
var(--primary-color-medium, #5bc0de) 0 4px, transparent 4px 7px);
|
||||
var(--librespeed-accent) 0 4px, transparent 4px 7px);
|
||||
}
|
||||
|
||||
.librespeed-legend {
|
||||
@@ -266,8 +282,8 @@ circle.librespeed-fill-1 { fill-opacity: .55; }
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.librespeed-fg-0 { color: var(--primary-color-medium, #5bc0de); }
|
||||
.librespeed-fg-1 { color: var(--primary-color-medium, #5bc0de); }
|
||||
.librespeed-fg-0 { color: var(--librespeed-accent); }
|
||||
.librespeed-fg-1 { color: var(--librespeed-accent); }
|
||||
|
||||
.librespeed-cards {
|
||||
display: flex;
|
||||
@@ -283,15 +299,17 @@ circle.librespeed-fill-1 { fill-opacity: .55; }
|
||||
padding: .45em .9em;
|
||||
min-width: 11em;
|
||||
cursor: pointer;
|
||||
opacity: .5;
|
||||
/* Dim, still legible: .5 with the muted name inside multiplied down to
|
||||
* an unreadable third. */
|
||||
opacity: .78;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.librespeed-metric-card-on { opacity: 1; }
|
||||
.librespeed-metric-card:hover { border-color: rgba(128, 128, 128, .45); }
|
||||
|
||||
.librespeed-accent-0 { border-top-color: var(--primary-color-medium, #5bc0de); }
|
||||
.librespeed-accent-1 { border-top-color: var(--primary-color-medium, #5bc0de); border-top-style: dashed; }
|
||||
.librespeed-accent-0 { border-top-color: var(--librespeed-accent); }
|
||||
.librespeed-accent-1 { border-top-color: var(--librespeed-accent); border-top-style: dashed; }
|
||||
|
||||
.librespeed-card-value {
|
||||
font-size: 1.3em;
|
||||
@@ -313,3 +331,14 @@ circle.librespeed-fill-1 { fill-opacity: .55; }
|
||||
text-align: left;
|
||||
font-size: .95em;
|
||||
}
|
||||
|
||||
/* Off-screen but reachable: the live region announcing the running phase,
|
||||
* and the gauge figures repeated as plain text for browse mode. */
|
||||
.librespeed-visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -14,6 +14,12 @@
|
||||
* second fetch, since the entries are in memory anyway. */
|
||||
const pageSize = 50;
|
||||
|
||||
const callConfig = rpc.declare({
|
||||
object: 'librespeed',
|
||||
method: 'config',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
const callHistory = rpc.declare({
|
||||
object: 'librespeed',
|
||||
method: 'history',
|
||||
@@ -61,7 +67,13 @@ return view.extend({
|
||||
speed: lscommon.GROUPS.speed.slice(),
|
||||
latency: lscommon.GROUPS.latency.slice()
|
||||
};
|
||||
return this.fetch();
|
||||
/* The config rides along for one purpose: with history keeping off,
|
||||
* the empty state must not send the user to run a test that will
|
||||
* never produce an entry. */
|
||||
return Promise.all([
|
||||
this.fetch(),
|
||||
callConfig().then(c => { this.config = c; }, () => {})
|
||||
]);
|
||||
},
|
||||
|
||||
/* The server/interface filters narrow the fetched range on the client;
|
||||
@@ -107,8 +119,8 @@ return view.extend({
|
||||
|
||||
lscommon.GROUPS[this.group].forEach(L.bind(function(k, ki) {
|
||||
const m = lscommon.METRICS.find(x => x[0] == k),
|
||||
st = lscommon.seriesStats(entries, k),
|
||||
ps = lscommon.seriesStats(prev, k),
|
||||
st = lscommon.seriesStats(entries, k, this.resolution),
|
||||
ps = lscommon.seriesStats(prev, k, this.prevResolution),
|
||||
on = act.indexOf(k) >= 0;
|
||||
|
||||
let diff = ' ';
|
||||
@@ -146,7 +158,9 @@ return view.extend({
|
||||
(on ? ' librespeed-metric-card-on' : ''),
|
||||
'title': on ? _('Hide this series') : _('Show this series')
|
||||
}, [
|
||||
E('div', { 'class': 'librespeed-muted librespeed-caps' },
|
||||
/* Not muted: the card's own off-state opacity already dims
|
||||
* it, and two factors multiply into illegibility. */
|
||||
E('div', { 'class': 'librespeed-caps' },
|
||||
[ cb, ' ', m[1] ]),
|
||||
E('div', { 'class': 'librespeed-card-value' }, [
|
||||
st ? '%.1f'.format(st.avg) + ' ' + m[2] : '–',
|
||||
@@ -189,10 +203,24 @@ return view.extend({
|
||||
const noneAtAll = !this.entries.length;
|
||||
|
||||
if (!entries.length) {
|
||||
this.emptyText.textContent = noneAtAll
|
||||
? _('Run a speed test to start building your connection history.')
|
||||
: _('No measurements match the current filters.');
|
||||
/* Strict, matching test.js: the backend emits a real boolean
|
||||
* (derived from UCI, never its raw '0'/'1'), and an absent or
|
||||
* failed config must read as "history on", not off. */
|
||||
const histOff = noneAtAll && this.config &&
|
||||
this.config.history && this.config.history.enabled === false;
|
||||
|
||||
/* With history keeping off, a test would never write an entry:
|
||||
* the way out is Settings, not the Start button. */
|
||||
this.emptyText.textContent = histOff
|
||||
? _('History keeping is switched off, so measurements are not recorded.')
|
||||
: (noneAtAll
|
||||
? _('Run a speed test to start building your connection history.')
|
||||
: _('No measurements match the current filters.'));
|
||||
this.emptyStart.style.display = noneAtAll ? '' : 'none';
|
||||
this.emptyStart.href = histOff
|
||||
? L.url('admin', 'network', 'librespeed', 'settings')
|
||||
: L.url('admin', 'network', 'librespeed', 'test');
|
||||
this.emptyStart.textContent = histOff ? _('Open settings') : _('Start test');
|
||||
this.emptyNode.style.display = '';
|
||||
this.dataNode.style.display = 'none';
|
||||
return;
|
||||
@@ -220,17 +248,12 @@ return view.extend({
|
||||
this.chartNode.appendChild(E('p', { 'class': 'librespeed-muted' },
|
||||
[ _('Daily minimum, average and maximum.') ]));
|
||||
|
||||
const num = v => (typeof v == 'number') ? v : -1;
|
||||
/* The sort key carries the same decimal count as the display half:
|
||||
* ui.Table stringifies the whole cell and compares digit runs one by
|
||||
* one, so ragged fractions would put 94.4 above 94.35. */
|
||||
const num = (v, d) => (typeof v == 'number') ? v.toFixed(d) : '';
|
||||
const fmtNum = (v, d) => (typeof v == 'number') ? v.toFixed(d) : '–';
|
||||
const when = e => {
|
||||
if (!e.timestamp)
|
||||
return '?';
|
||||
if (this.resolution == '1d' || e.timestamp.indexOf('T') < 0)
|
||||
return e.timestamp;
|
||||
const d = new Date(e.timestamp);
|
||||
/* A garbled timestamp shows as itself, never as "Invalid Date". */
|
||||
return isNaN(d.getTime()) ? e.timestamp : d.toLocaleString();
|
||||
};
|
||||
const when = e => lscommon.chartStampFull(e, this.resolution);
|
||||
|
||||
/* One column carries both what the packets were (IPv4/IPv6) and how
|
||||
* they travelled (HTTPS/HTTP); either half may be unknown. */
|
||||
@@ -244,15 +267,19 @@ return view.extend({
|
||||
* cell, and ui.Table only ever orders the rows it was handed, so
|
||||
* paging first would turn the headers into a per-page sort while the
|
||||
* count below still speaks for every measurement. */
|
||||
/* Every display half is a node: ui.Table writes bare strings into
|
||||
* innerHTML, and the server name comes from a downloaded list --
|
||||
* text must stay text. The sort key stays the first element. */
|
||||
const cell = t => E('span', {}, [ t ]);
|
||||
let rows = entries.slice().reverse().map(e => [
|
||||
[ e.epoch ?? 0, when(e) ],
|
||||
(e.server && e.server.name) || '–',
|
||||
e.interface || '–',
|
||||
protoCell(e),
|
||||
[ num(e.download_mbps), fmtNum(e.download_mbps, 2) ],
|
||||
[ num(e.upload_mbps), fmtNum(e.upload_mbps, 2) ],
|
||||
[ num(e.ping_ms), fmtNum(e.ping_ms, 1) ],
|
||||
[ num(e.jitter_ms), fmtNum(e.jitter_ms, 1) ]
|
||||
[ e.epoch ?? 0, cell(when(e)) ],
|
||||
cell((e.server && e.server.name) || '–'),
|
||||
cell(e.interface || '–'),
|
||||
cell(protoCell(e)),
|
||||
[ num(e.download_mbps, 2), cell(fmtNum(e.download_mbps, 2)) ],
|
||||
[ num(e.upload_mbps, 2), cell(fmtNum(e.upload_mbps, 2)) ],
|
||||
[ num(e.ping_ms, 1), cell(fmtNum(e.ping_ms, 1)) ],
|
||||
[ num(e.jitter_ms, 1), cell(fmtNum(e.jitter_ms, 1)) ]
|
||||
]);
|
||||
|
||||
const sorting = this.table.getActiveSortState();
|
||||
@@ -274,7 +301,6 @@ return view.extend({
|
||||
|
||||
this.renderPager(rows.length, pages);
|
||||
this.table.update(rows.slice(this.page * pageSize, (this.page + 1) * pageSize));
|
||||
|
||||
},
|
||||
|
||||
/* Shown only when there is more than one page; the count is always
|
||||
@@ -286,7 +312,7 @@ return view.extend({
|
||||
}, this);
|
||||
|
||||
const nav = [ E('span', { 'class': 'librespeed-muted' },
|
||||
[ _('%d measurements').format(total) ]) ];
|
||||
[ N_(total, '%d measurement', '%d measurements').format(total) ]) ];
|
||||
|
||||
if (pages > 1) {
|
||||
nav.push(E('button', {
|
||||
@@ -341,7 +367,7 @@ return view.extend({
|
||||
const renderControls = L.bind(function() {
|
||||
const groups = lscommon.switcher(this,
|
||||
[ [ 'speed', _('Speed') ], [ 'latency', _('Latency') ] ], this.group,
|
||||
function(v) { this.group = v; renderControls(); this.redraw(); });
|
||||
function(v) { this.group = v; renderControls(); this.redraw(); }, _('Series'));
|
||||
const ranges = lscommon.switcher(this,
|
||||
lscommon.RANGES.map(r => [ String(r[1]), r[0] ]), String(this.range),
|
||||
function(v) {
|
||||
@@ -352,7 +378,7 @@ return view.extend({
|
||||
renderControls();
|
||||
this.redraw();
|
||||
}, this));
|
||||
});
|
||||
}, _('Range'));
|
||||
|
||||
ranges.classList.add('librespeed-push');
|
||||
|
||||
@@ -367,6 +393,17 @@ return view.extend({
|
||||
ifaces.push(e.interface);
|
||||
});
|
||||
|
||||
/* The freshly fetched window may no longer contain the chosen
|
||||
* server or interface -- daily aggregates carry neither field at
|
||||
* all. The widget would then quietly repaint as "All" while the
|
||||
* model kept filtering everything out, with no control on screen
|
||||
* able to clear it; reconcile the model here, where the choice
|
||||
* lists are built. */
|
||||
if (this.server && servers.indexOf(this.server) < 0)
|
||||
this.server = '';
|
||||
if (this.iface && ifaces.indexOf(this.iface) < 0)
|
||||
this.iface = '';
|
||||
|
||||
const filters = E('div', { 'class': 'librespeed-toolbar' }, [
|
||||
this.filterSelect(_('Server'), servers.sort(), this.server,
|
||||
function(v) { this.server = v; this.page = 0; this.redraw(); }),
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
'require form';
|
||||
'require rpc';
|
||||
'require tools.widgets as widgets';
|
||||
'require librespeed.common as lscommon';
|
||||
|
||||
const callConfig = rpc.declare({
|
||||
object: 'librespeed',
|
||||
@@ -59,12 +60,10 @@ return view.extend({
|
||||
_('Runs a measurement from cron at the chosen interval. Note that a measurement saturates the connection while it runs.'));
|
||||
|
||||
o = s.option(form.ListValue, 'interval', _('Interval'));
|
||||
o.value('15m', _('Every 15 minutes'));
|
||||
o.value('30m', _('Every 30 minutes'));
|
||||
o.value('1h', _('Hourly'));
|
||||
o.value('6h', _('Every 6 hours'));
|
||||
o.value('12h', _('Every 12 hours'));
|
||||
o.value('1d', _('Daily'));
|
||||
/* From the shared table, so the Test page's status label and these
|
||||
* choices cannot drift apart. */
|
||||
Object.keys(lscommon.INTERVALS).forEach(k =>
|
||||
o.value(k, lscommon.INTERVALS[k]));
|
||||
o.default = '1d';
|
||||
o.depends('enabled', '1');
|
||||
|
||||
@@ -163,8 +162,11 @@ return view.extend({
|
||||
]));
|
||||
}
|
||||
|
||||
node.appendChild(box);
|
||||
return node;
|
||||
/* A sibling of the form, not a child: Map.render() replaces its
|
||||
* own root on every Save and Reset, and would take the schedule
|
||||
* preview with it. The preview reads the applied crontab, so it
|
||||
* is correct to keep it as it is until Apply. */
|
||||
return E([], [ node, box ]);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -220,7 +220,8 @@ return view.extend({
|
||||
|
||||
this.recentNode.innerHTML = '';
|
||||
this.recentCount.textContent = entries.length
|
||||
? _('%d measurements').format(entries.length) : '';
|
||||
? N_(entries.length, '%d measurement', '%d measurements')
|
||||
.format(entries.length) : '';
|
||||
|
||||
/* The active button names the metric, so the subtitle only carries
|
||||
* the window. */
|
||||
@@ -232,12 +233,12 @@ return view.extend({
|
||||
function(v) {
|
||||
this.recentMetric = v;
|
||||
this.renderRecent(this.recentData);
|
||||
}).childNodes);
|
||||
}, _('Metric')).childNodes);
|
||||
|
||||
/* The stability story of the last day, told in one sentence and four
|
||||
* figures: what is normal, how much it wobbles, where it is now. */
|
||||
const metric = this.recentMetric || 'download_mbps';
|
||||
const st = lscommon.seriesStats(entries, metric);
|
||||
const st = lscommon.seriesStats(entries, metric, data && data.resolution);
|
||||
|
||||
if (st && st.count > 1) {
|
||||
const varPct = (st.max - st.min) / st.avg * 100,
|
||||
@@ -297,20 +298,26 @@ return view.extend({
|
||||
}
|
||||
|
||||
const fmtNum = (v, d) => (typeof v == 'number') ? v.toFixed(d) : '–';
|
||||
const when = e => {
|
||||
const d = new Date(e.timestamp);
|
||||
return isNaN(d.getTime()) ? String(e.timestamp || '?') : d.toLocaleString();
|
||||
};
|
||||
/* The shared formatter carries the date-only guard: a daily
|
||||
* aggregate's bare date fed to new Date() is read as UTC midnight
|
||||
* and shifts a calendar day in negative offsets. */
|
||||
const when = e => lscommon.chartStampFull(e, data && data.resolution);
|
||||
|
||||
const num = v => (typeof v == 'number') ? v : -1;
|
||||
/* The sort key carries the same decimal count as the display half:
|
||||
* ui.Table stringifies the whole cell and compares digit runs one by
|
||||
* one, so ragged fractions would put 94.4 above 94.35. */
|
||||
const num = (v, d) => (typeof v == 'number') ? v.toFixed(d) : '';
|
||||
|
||||
/* Nodes, not strings: ui.Table writes bare strings into innerHTML
|
||||
* and the server name comes from a downloaded list. */
|
||||
const cell = t => E('span', {}, [ t ]);
|
||||
this.recentTable.update(entries.slice(-recentRows).reverse().map(e => [
|
||||
[ e.epoch ?? 0, when(e) ],
|
||||
(e.server && e.server.name) || '–',
|
||||
[ num(e.download_mbps), fmtNum(e.download_mbps, 2) ],
|
||||
[ num(e.upload_mbps), fmtNum(e.upload_mbps, 2) ],
|
||||
[ num(e.ping_ms), fmtNum(e.ping_ms, 1) ],
|
||||
[ num(e.jitter_ms), fmtNum(e.jitter_ms, 1) ]
|
||||
[ e.epoch ?? 0, cell(when(e)) ],
|
||||
cell((e.server && e.server.name) || '–'),
|
||||
[ num(e.download_mbps, 2), cell(fmtNum(e.download_mbps, 2)) ],
|
||||
[ num(e.upload_mbps, 2), cell(fmtNum(e.upload_mbps, 2)) ],
|
||||
[ num(e.ping_ms, 1), cell(fmtNum(e.ping_ms, 1)) ],
|
||||
[ num(e.jitter_ms, 1), cell(fmtNum(e.jitter_ms, 1)) ]
|
||||
]));
|
||||
this.recentNode.appendChild(this.recentTableNode);
|
||||
|
||||
@@ -374,6 +381,17 @@ return view.extend({
|
||||
this.resultHeading.textContent = (!status.running && status.last_error)
|
||||
? _('Last successful measurement') : '';
|
||||
|
||||
/* One quiet live region, outside the tree that is rebuilt every
|
||||
* poll: announcing the rebuilt gauge SVG would read the whole dial
|
||||
* out several times a run. Set only on change, so it speaks once
|
||||
* per phase step. */
|
||||
const announce = status.running
|
||||
? (PHASES.find(p => p[0] == status.phase) || [])[3] || _('Connecting to the test server…')
|
||||
: '';
|
||||
|
||||
if (this.liveNode.textContent != announce)
|
||||
this.liveNode.textContent = announce;
|
||||
|
||||
if (status.running) {
|
||||
const rows = [];
|
||||
|
||||
@@ -385,7 +403,10 @@ return view.extend({
|
||||
PHASES.map((p, i) => E('span', {
|
||||
'class': 'librespeed-step' +
|
||||
(i == phaseIdx ? ' librespeed-step-active' :
|
||||
(phaseIdx >= 0 && i < phaseIdx ? ' librespeed-step-done' : ''))
|
||||
(phaseIdx >= 0 && i < phaseIdx ? ' librespeed-step-done' : '')),
|
||||
/* Spoken as well as dimmed: opacity is invisible to a
|
||||
* screen reader. */
|
||||
'aria-current': i == phaseIdx ? 'step' : null
|
||||
}, [ p[3] ]))));
|
||||
|
||||
/* The dial range is frozen at the start of the run -- a familiar
|
||||
@@ -404,13 +425,20 @@ return view.extend({
|
||||
rows.push(E('p', { 'class': 'spinning', 'style': 'margin-top:.75em' },
|
||||
[ _('Connecting to the test server…') ]));
|
||||
else {
|
||||
const holder = E('div', {});
|
||||
/* The dial is hidden from assistive tech -- its ten tick
|
||||
* labels are noise there -- so the one figure it carries,
|
||||
* the running rate, is repeated as plain hidden text that
|
||||
* browse mode can still reach. */
|
||||
const holder = E('div', { 'aria-hidden': 'true' });
|
||||
holder.innerHTML = gauge(
|
||||
(typeof status.mbps == 'number' && status.mbps > 0)
|
||||
? status.mbps : null,
|
||||
this.runTop,
|
||||
status.phase == 'upload' ? 1 : 0);
|
||||
rows.push(holder);
|
||||
if (typeof status.mbps == 'number' && status.mbps > 0)
|
||||
rows.push(E('span', { 'class': 'librespeed-visually-hidden' },
|
||||
[ '%.2f Mbps'.format(status.mbps) ]));
|
||||
}
|
||||
|
||||
/* Completion is a different number than the rate on the arc, so
|
||||
@@ -422,8 +450,13 @@ return view.extend({
|
||||
rows.push(E('div', { 'class': 'librespeed-muted' },
|
||||
[ overall + ' %' ]));
|
||||
|
||||
const elapsed = status.started
|
||||
? fmtElapsed(Date.now() / 1000 - status.started) : '';
|
||||
/* The backend counts on the clock that stamped the start; the
|
||||
* difference of two unrelated clocks can be negative. The old
|
||||
* subtraction stays as a fallback for an updating router. */
|
||||
const elapsed = typeof status.elapsed == 'number'
|
||||
? fmtElapsed(status.elapsed)
|
||||
: (status.started
|
||||
? fmtElapsed(Date.now() / 1000 - status.started) : '');
|
||||
|
||||
if (elapsed)
|
||||
rows.push(E('div', { 'class': 'librespeed-muted' },
|
||||
@@ -439,7 +472,15 @@ return view.extend({
|
||||
else
|
||||
this.wasRunning = false;
|
||||
|
||||
if (!status.running && status.last_error) {
|
||||
if (!status.running && status.last_error == 'stopped') {
|
||||
/* Stopping is something the user did, not something that went
|
||||
* wrong; a red banner would turn their own click into an error. */
|
||||
this.alertNode.appendChild(E('p', { 'class': 'librespeed-muted' }, [
|
||||
_('The last measurement was stopped.'),
|
||||
status.last_finished ? ' · ' + fmtTime(status.last_finished) : ''
|
||||
]));
|
||||
}
|
||||
else if (!status.running && status.last_error) {
|
||||
/* Compact, and above the figures: the failure is news, the last
|
||||
* good result is still the substance of the page. */
|
||||
this.alertNode.appendChild(E('div', {
|
||||
@@ -553,6 +594,11 @@ return view.extend({
|
||||
this.resultHeading = E('div', { 'class': 'librespeed-muted', 'style': 'margin-top:.35em' });
|
||||
this.resultNode = E('div', {});
|
||||
this.recentNode = E('div', {});
|
||||
this.liveNode = E('div', {
|
||||
'role': 'status',
|
||||
'aria-live': 'polite',
|
||||
'class': 'librespeed-visually-hidden'
|
||||
});
|
||||
this.recentCount = E('span', { 'class': 'librespeed-muted' });
|
||||
this.recentSubtitle = E('div', { 'class': 'librespeed-muted' },
|
||||
[ _('last 24 hours') ]);
|
||||
@@ -624,10 +670,15 @@ return view.extend({
|
||||
* well sit in another one, so it only formats the epoch. */
|
||||
const sched = config.schedule || {};
|
||||
const next = sched.next_runs || [];
|
||||
const schedRows = [ [ _('Enabled'), sched.enabled ? _('Yes') : _('No') ] ];
|
||||
/* Strict, matching history.js: the backend derives this from the
|
||||
* crontab and emits a real boolean, never UCI's '0'/'1'. */
|
||||
const schedRows = [ [ _('Enabled'), sched.enabled === true ? _('Yes') : _('No') ] ];
|
||||
|
||||
if (sched.enabled) {
|
||||
schedRows.push([ _('Interval'), sched.interval || '1d' ]);
|
||||
if (sched.enabled === true) {
|
||||
/* The shared table translates the six tokens the UI offers; the
|
||||
* init script accepts more, so the raw token is the fallback. */
|
||||
schedRows.push([ _('Interval'),
|
||||
lscommon.INTERVALS[sched.interval || '1d'] || sched.interval ]);
|
||||
if (next.length)
|
||||
schedRows.push([ _('Next run'), new Date(next[0] * 1000).toLocaleString() ]);
|
||||
}
|
||||
@@ -660,6 +711,7 @@ return view.extend({
|
||||
|
||||
const main = E('div', { 'class': 'cbi-section librespeed-center', 'style': 'margin:0' }, [
|
||||
this.alertNode,
|
||||
this.liveNode,
|
||||
this.statusNode,
|
||||
this.resultHeading,
|
||||
this.resultNode,
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:288
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:315
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:223
|
||||
msgid "%d measurements"
|
||||
msgstr ""
|
||||
msgid "%d measurement"
|
||||
msgid_plural "%d measurements"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:430
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:463
|
||||
msgid "%s elapsed"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:124
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:136
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:123
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:135
|
||||
msgid "1 year"
|
||||
msgstr ""
|
||||
|
||||
@@ -19,7 +21,7 @@ msgstr ""
|
||||
msgid "1y"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:137
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:136
|
||||
msgid "2 years"
|
||||
msgstr ""
|
||||
|
||||
@@ -27,7 +29,7 @@ msgstr ""
|
||||
msgid "24h"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:122
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:121
|
||||
msgid "30 days"
|
||||
msgstr ""
|
||||
|
||||
@@ -35,7 +37,7 @@ msgstr ""
|
||||
msgid "30d"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:121
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:120
|
||||
msgid "7 days"
|
||||
msgstr ""
|
||||
|
||||
@@ -43,23 +45,23 @@ msgstr ""
|
||||
msgid "7d"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:123
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:135
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:122
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:134
|
||||
msgid "90 days"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:157
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:156
|
||||
msgid ""
|
||||
"A daily measurement runs at a time drawn when the schedule is applied; "
|
||||
"saving draws it anew."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:31
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:82
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:94
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:95
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:94
|
||||
msgid ""
|
||||
"An hour window on the 24-hour clock, such as 2-5 for 02:00–05:59. A daily "
|
||||
"measurement runs at a random time inside it, drawn when the schedule is "
|
||||
@@ -67,99 +69,100 @@ msgid ""
|
||||
"window across midnight is not supported."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:128
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:127
|
||||
msgid "Archive path"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:134
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:133
|
||||
msgid "Archive retention"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:521
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:562
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:129
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:128
|
||||
msgid ""
|
||||
"Completed days are reduced to daily minimum, average and maximum and "
|
||||
"appended here once a day, so measurements since the last flush may be lost "
|
||||
"after an unexpected power loss. Leave empty to keep no persistent history."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:405
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:389
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:426
|
||||
msgid "Connecting to the test server…"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:327
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:334
|
||||
msgid "Could not start the measurement: %s"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:67
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:161
|
||||
msgid "Daily"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:221
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:249
|
||||
msgid "Daily minimum, average and maximum."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:71
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:70
|
||||
msgid "Days"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:251
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:252
|
||||
msgid "Declining — the last measurement is %d%% below the 24-hour average."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:11
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:92
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:491
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:532
|
||||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:328
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:563
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:609
|
||||
msgid "Download [Mbps]"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:58
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:59
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:627
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:675
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:651
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:702
|
||||
msgid ""
|
||||
"Encrypted transfers, which on hardware without AES acceleration may bound "
|
||||
"the result."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:66
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:160
|
||||
msgid "Every 12 hours"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:62
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:156
|
||||
msgid "Every 15 minutes"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:63
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:157
|
||||
msgid "Every 30 minutes"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:65
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:159
|
||||
msgid "Every 6 hours"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:405
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:443
|
||||
msgid "Export CSV"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:408
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:446
|
||||
msgid "Export JSON"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:77
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:76
|
||||
msgid "Friday"
|
||||
msgstr ""
|
||||
|
||||
@@ -167,243 +170,263 @@ msgstr ""
|
||||
msgid "Grant access to LibreSpeed measurements"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:646
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:697
|
||||
msgid "HTTP (forced)"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:645
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:696
|
||||
msgid "HTTPS (forced)"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:147
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:159
|
||||
msgid "Hide this series"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:110
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:109
|
||||
#: applications/luci-app-librespeed/root/usr/share/luci/menu.d/luci-app-librespeed.json:25
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:116
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:215
|
||||
msgid "History keeping is switched off, so measurements are not recorded."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:115
|
||||
msgid "History stored in /tmp is lost when the router reboots."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:64
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:158
|
||||
msgid "Hourly"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:94
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:93
|
||||
msgid "Hours"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:327
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:372
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:25
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:509
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:641
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:354
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:410
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:26
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:550
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:692
|
||||
msgid "Interface"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:61
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:630
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:62
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:680
|
||||
msgid "Interval"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:14
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:499
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:540
|
||||
msgid "Jitter"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:328
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:563
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:609
|
||||
msgid "Jitter [ms]"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:112
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:111
|
||||
msgid "Keep history"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:449
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:490
|
||||
msgid "Last measurement failed"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:375
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:382
|
||||
msgid "Last successful measurement"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:342
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:369
|
||||
msgid "Latency"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:72
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:71
|
||||
msgid "Leave empty to run every day."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:686
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:738
|
||||
#: applications/luci-app-librespeed/root/usr/share/luci/menu.d/luci-app-librespeed.json:3
|
||||
msgid "LibreSpeed"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:417
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:455
|
||||
msgid "LibreSpeed – History"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:21
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:22
|
||||
msgid "LibreSpeed – Settings"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:26
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:27
|
||||
msgid "Logical interface the measurement is bound to."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:23
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:24
|
||||
msgid "Measurement"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:400
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:438
|
||||
msgid "Measurements"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:689
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:741
|
||||
msgid "Measures the internet connection from this router."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:73
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:236
|
||||
msgid "Metric"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:72
|
||||
msgid "Monday"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:36
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:37
|
||||
msgid "Must be a server id or 'auto'"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:46
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:47
|
||||
msgid "Must be an http(s) URL"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:302
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:329
|
||||
msgid "Next"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:632
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:683
|
||||
msgid "Next run"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:627
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:675
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:218
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:246
|
||||
msgid "No data for the selected metric."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:278
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:279
|
||||
msgid "No data in the last 24 hours."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:466
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:507
|
||||
msgid "No measurement yet."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:194
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:218
|
||||
msgid "No measurements match the current filters."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:392
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:430
|
||||
msgid "No measurements yet"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:162
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:161
|
||||
msgid ""
|
||||
"No schedule is active. Enable it above and apply to draw the measurement "
|
||||
"time."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:31
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:32
|
||||
msgid ""
|
||||
"Numeric server id from the LibreSpeed server list, or 'auto' to pick the "
|
||||
"closest."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:50
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:51
|
||||
msgid ""
|
||||
"On routers without AES acceleration, TLS itself can bound the result — "
|
||||
"forcing plain HTTP then measures the line rather than the cipher."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:297
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:223
|
||||
msgid "Open settings"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:324
|
||||
msgid "Page %d of %d"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:115
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:114
|
||||
msgid "Path"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:13
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:91
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:498
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:539
|
||||
msgid "Ping"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:328
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:563
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:609
|
||||
msgid "Ping [ms]"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:295
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:322
|
||||
msgid "Previous"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:327
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:49
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:518
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:644
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:354
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:50
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:559
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:695
|
||||
msgid "Protocol"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:674
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:381
|
||||
msgid "Range"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:726
|
||||
msgid "Recent history"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:120
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:119
|
||||
msgid "Retention"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:687
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:739
|
||||
msgid "Router speed test"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:193
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:217
|
||||
msgid "Run a speed test to start building your connection history."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:59
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:60
|
||||
msgid ""
|
||||
"Runs a measurement from cron at the chosen interval. Note that a measurement "
|
||||
"saturates the connection while it runs."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:78
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:77
|
||||
msgid "Saturday"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:656
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:707
|
||||
msgid "Schedule status"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:56
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:57
|
||||
msgid "Scheduled measurements"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:327
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:370
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:30
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:507
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:562
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:642
|
||||
msgid "Series"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:354
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:408
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:31
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:548
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:608
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:693
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:39
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:40
|
||||
msgid "Server list URL"
|
||||
msgstr ""
|
||||
|
||||
@@ -411,33 +434,34 @@ msgstr ""
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:147
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:159
|
||||
msgid "Show this series"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:342
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:369
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:175
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:189
|
||||
msgid "Stable over the selected period."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:257
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:258
|
||||
msgid "Stable — averaged %d Mbps, ranging from %d to %d Mbps."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:386
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:349
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:573
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:223
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:424
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:356
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:619
|
||||
msgid "Start test"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:349
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:356
|
||||
msgid "Stop test"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:79
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:78
|
||||
msgid "Sunday"
|
||||
msgstr ""
|
||||
|
||||
@@ -445,28 +469,32 @@ msgstr ""
|
||||
msgid "Test"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:639
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:690
|
||||
msgid "Test configuration"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:106
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:479
|
||||
msgid "The last measurement was stopped."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:105
|
||||
msgid "The window must not cross midnight"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:76
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:75
|
||||
msgid "Thursday"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:327
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:562
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:354
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:608
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:74
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:73
|
||||
msgid "Tuesday"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:40
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:41
|
||||
msgid ""
|
||||
"URL of a LibreSpeed server list in JSON, from a self-hosted deployment: "
|
||||
"either a static file such as https://example.org/servers.json or a generator "
|
||||
@@ -474,120 +502,121 @@ msgid ""
|
||||
"official list."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:649
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:700
|
||||
msgid "Unencrypted transfers, so the line is measured rather than the cipher."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:150
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:149
|
||||
msgid "Upcoming measurements"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:12
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:93
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:492
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:533
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:328
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:563
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:355
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:609
|
||||
msgid "Upload [Mbps]"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:104
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:103
|
||||
msgid "Use an hour (0-23) or a range like 2-5"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:254
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:255
|
||||
msgid "Variable — ranged from %d to %d Mbps."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:319
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:326
|
||||
msgid "View full history »"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:540
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:581
|
||||
msgid "View result"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:75
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:74
|
||||
msgid "Wednesday"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:652
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:703
|
||||
msgid "Whichever scheme the server list provides."
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:627
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:675
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:643
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:694
|
||||
msgid "automatic (nearest)"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:293
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:294
|
||||
msgid "average"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:328
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:154
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:287
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/librespeed/common.js:358
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:168
|
||||
msgid "avg"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:294
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:295
|
||||
msgid "best"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:292
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:293
|
||||
msgid "current"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:165
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:179
|
||||
msgid "declining"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:516
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:557
|
||||
msgid "encrypted (HTTPS)"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:53
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:54
|
||||
msgid "force HTTP"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:52
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:53
|
||||
msgid "force HTTPS"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:165
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:179
|
||||
msgid "highly variable"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:558
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:604
|
||||
msgid "last 24 hours"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:516
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:557
|
||||
msgid "plain HTTP"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:360
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:367
|
||||
msgid "server %s"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:51
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:647
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/settings.js:52
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:698
|
||||
msgid "server default"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:165
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:172
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:179
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:186
|
||||
msgid "stable"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:122
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/history.js:134
|
||||
msgid "vs previous period"
|
||||
msgstr ""
|
||||
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:295
|
||||
#: applications/luci-app-librespeed/htdocs/luci-static/resources/view/librespeed/test.js:296
|
||||
msgid "worst"
|
||||
msgstr ""
|
||||
@@ -3,15 +3,40 @@
|
||||
"description": "Grant access to LibreSpeed measurements",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"librespeed": [ "status", "result", "history", "config" ]
|
||||
"librespeed": [
|
||||
"status",
|
||||
"result",
|
||||
"history",
|
||||
"config"
|
||||
],
|
||||
"network.interface": [
|
||||
"dump"
|
||||
],
|
||||
"network": [
|
||||
"get_proto_handlers"
|
||||
],
|
||||
"luci-rpc": [
|
||||
"getBoardJSON",
|
||||
"getNetworkDevices",
|
||||
"getWirelessDevices"
|
||||
]
|
||||
},
|
||||
"uci": [ "librespeed" ]
|
||||
"uci": [
|
||||
"librespeed",
|
||||
"network",
|
||||
"wireless"
|
||||
]
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"librespeed": [ "start", "stop" ]
|
||||
"librespeed": [
|
||||
"start",
|
||||
"stop"
|
||||
]
|
||||
},
|
||||
"uci": [ "librespeed" ]
|
||||
"uci": [
|
||||
"librespeed"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-mosdns
|
||||
PKG_VERSION:=1.7.7
|
||||
PKG_RELEASE:=14
|
||||
PKG_VERSION:=1.7.8
|
||||
PKG_RELEASE:=15
|
||||
|
||||
LUCI_TITLE:=LuCI Support for mosdns
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -152,7 +152,7 @@ msgstr "自动保存缓存"
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:323
|
||||
msgid "Cache Prefetching"
|
||||
msgstr "缓存预读"
|
||||
msgstr "缓存预取"
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/update.js:150
|
||||
msgid "Check And Update"
|
||||
@@ -577,7 +577,7 @@ msgstr "覆盖最小 TTL 值(默认 0)"
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:336
|
||||
msgid ""
|
||||
"Minimum cache hits required since the last refresh to trigger a prefetch."
|
||||
msgstr "触发预读所需的最小缓存命中次数(自上次刷新起)"
|
||||
msgstr "触发预取所需的最小缓存命中次数(自上次刷新起)"
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:366
|
||||
msgid ""
|
||||
@@ -630,19 +630,19 @@ msgstr "请稍候,这可能需要一点时间..."
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:329
|
||||
msgid "Prefetch Before Expire"
|
||||
msgstr "预读触发阈值"
|
||||
msgstr "预取触发阈值"
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:335
|
||||
msgid "Prefetch Min Hits"
|
||||
msgstr "预读最小命中次数"
|
||||
msgstr "预取最小命中次数"
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:341
|
||||
msgid "Prefetch Scan Interval"
|
||||
msgstr "预读扫描周期"
|
||||
msgstr "预取扫描周期"
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:330
|
||||
msgid "Prefetch when the remaining TTL is less than this value (in seconds)."
|
||||
msgstr "当剩余 TTL 小于此值(秒)时触发预读"
|
||||
msgstr "当剩余 TTL 小于此值(秒)时触发预取"
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:301
|
||||
msgid "Prevent DNS Leaks"
|
||||
@@ -651,7 +651,7 @@ msgstr "防止 DNS 泄漏"
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:324
|
||||
msgid ""
|
||||
"Proactively refresh hot cache entries in the background before they expire."
|
||||
msgstr "在缓存到期前,后台主动预读并刷新高频访问的 DNS 记录"
|
||||
msgstr "在缓存到期前,后台主动预取并刷新高频访问的 DNS 记录"
|
||||
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:227
|
||||
#: luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js:244
|
||||
|
||||
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.8.19
|
||||
PKG_RELEASE:=238
|
||||
PKG_RELEASE:=239
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -149,7 +149,8 @@ end
|
||||
|
||||
o = s:taboption("Main", Value, "node_socks_port", translate("Node") .. " Socks " .. translate("Listen Port"))
|
||||
o.default = 1070
|
||||
o.datatype = "port"
|
||||
o.datatype = "range(1,65535)"
|
||||
o.rmempty = false
|
||||
o:depends({ node = "", ["!reverse"] = true })
|
||||
--[[
|
||||
if has_singbox or has_xray then
|
||||
@@ -687,7 +688,16 @@ s2.addremove = true
|
||||
s2.extedit = api.url("socks_config", "%s")
|
||||
function s2.create(e, t)
|
||||
local uid = "socks_" .. api.gen_random_char(5)
|
||||
local n = 1
|
||||
m:foreach("socks", function(s)
|
||||
if s[".name"] == section then
|
||||
return false
|
||||
end
|
||||
n = n + 1
|
||||
end)
|
||||
TypedSection.create(e, uid)
|
||||
m:set(uid, "port", 1080 + n)
|
||||
m:set(uid, "http_port", 0)
|
||||
luci.http.redirect(e.extedit:format(uid))
|
||||
end
|
||||
function s2.remove(e, t)
|
||||
@@ -730,12 +740,6 @@ function s2.remove(e, t)
|
||||
TypedSection.remove(e, t)
|
||||
end
|
||||
|
||||
o = s2:option(DummyValue, "status", translate("Status"))
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
return string.format('<div class="_status" socks_id="%s"></div>', n)
|
||||
end
|
||||
|
||||
---- Enable
|
||||
o = s2:option(Flag, "enabled", translate("Enable"))
|
||||
o.default = 1
|
||||
@@ -757,26 +761,19 @@ o.cfgvalue = function(_, n)
|
||||
end
|
||||
end
|
||||
|
||||
local n = 1
|
||||
m:foreach("socks", function(s)
|
||||
if s[".name"] == section then
|
||||
return false
|
||||
end
|
||||
n = n + 1
|
||||
end)
|
||||
|
||||
o = s2:option(Value, "port", "Socks " .. translate("Listen Port"))
|
||||
o.default = n + 1080
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
|
||||
--[[
|
||||
if has_singbox or has_xray then
|
||||
o = s2:option(Value, "http_port", "HTTP " .. translate("Listen Port"))
|
||||
o.default = 0
|
||||
o.datatype = "port"
|
||||
o = s2:option(DummyValue, "port_status", translate("Port Status"))
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
local socks = m:get(n, "port") or "0"
|
||||
local http = m:get(n, "http_port") or "0"
|
||||
return string.format([[
|
||||
<div class="_socks_status" socks_id="%s">
|
||||
<span class="_socks"></span> SOCKS: %s
|
||||
<br>
|
||||
<span class="_http"></span> HTTP: %s
|
||||
</div>
|
||||
]], n, socks, http)
|
||||
end
|
||||
]]--
|
||||
|
||||
local o_node = s.fields["node"]
|
||||
local o_socks = s2.fields["node"]
|
||||
|
||||
@@ -46,8 +46,9 @@ o:depends("console_auth", true)
|
||||
|
||||
---- Console Port
|
||||
o = s:option(Value, "console_port", translate("Console Port"), translate("In the browser input routing IP plus port access, such as:192.168.1.1:1188"))
|
||||
o.datatype = "port"
|
||||
o.default = 1188
|
||||
o.datatype = "range(1,65535)"
|
||||
o.rmempty = false
|
||||
o:depends("balancing_enable", true)
|
||||
|
||||
o = s:option(Flag, "bind_local", translate("Haproxy Port") .. " " .. translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
@@ -151,8 +152,8 @@ end
|
||||
|
||||
---- Haproxy Port
|
||||
o = s:option(Value, "haproxy_port", translate("Haproxy Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 1181
|
||||
o.datatype = "range(1,65535)"
|
||||
o.rmempty = false
|
||||
|
||||
---- Node Weight
|
||||
|
||||
@@ -63,7 +63,7 @@ end)
|
||||
|
||||
o = s:option(Value, "port", "Socks " .. translate("Listen Port"))
|
||||
o.default = n + 1080
|
||||
o.datatype = "port"
|
||||
o.datatype = "range(1,65535)"
|
||||
o.rmempty = false
|
||||
|
||||
if has_singbox or has_xray then
|
||||
|
||||
@@ -30,6 +30,16 @@ for i, v in ipairs(user_list) do
|
||||
end
|
||||
o:depends({ auth = true })
|
||||
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "log", translate("Log"))
|
||||
o.default = "1"
|
||||
|
||||
|
||||
@@ -456,9 +456,16 @@ if singbox_tags:find("with_wireguard") then
|
||||
o:depends({ protocol = "wireguard" })
|
||||
end
|
||||
|
||||
o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false, is_endpoint = "" })
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "accept_lan", translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
|
||||
o.default = "0"
|
||||
|
||||
@@ -468,10 +468,17 @@ o = s:option(DummyValue, "gen_wireguard_key")
|
||||
o.template = m:template_path("/server/gen_wireguard_key")
|
||||
o:depends({ protocol = "wireguard" })
|
||||
|
||||
o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "accept_lan", translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
@@ -72,6 +72,17 @@ o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "log", translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
@@ -103,6 +103,17 @@ o = s:option(Flag, "udp_forward", translate("UDP Forward"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "log", translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
@@ -147,6 +147,17 @@ o.validate = function(self, value, t)
|
||||
end
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "log", translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
@@ -8,16 +8,10 @@ local jsonc = api.jsonc
|
||||
|
||||
local CONFIG = api.s_config
|
||||
local CONFIG_PATH = api.S_TMP_PATH
|
||||
local NFT_INCLUDE_FILE = CONFIG_PATH .. "/" .. CONFIG .. ".nft"
|
||||
local LOG_APP_FILE = "/tmp/log/" .. CONFIG .. ".log"
|
||||
local TMP_BIN_PATH = CONFIG_PATH .. "/bin"
|
||||
local require_dir = "luci.passwall."
|
||||
|
||||
local ipt_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ipt_bin)")
|
||||
local ip6t_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ip6t_bin)")
|
||||
|
||||
local nft_flag = api.is_finded("fw4") and "1" or "0"
|
||||
|
||||
local function log(...)
|
||||
local f, err = io.open(LOG_APP_FILE, "a")
|
||||
if f and err == nil then
|
||||
@@ -31,18 +25,6 @@ local function cmd(cmd)
|
||||
sys.call(cmd)
|
||||
end
|
||||
|
||||
local function ipt(arg)
|
||||
if ipt_bin and #ipt_bin > 0 then
|
||||
cmd(ipt_bin .. " -w " .. arg)
|
||||
end
|
||||
end
|
||||
|
||||
local function ip6t(arg)
|
||||
if ip6t_bin and #ip6t_bin > 0 then
|
||||
cmd(ip6t_bin .. " -w " .. arg)
|
||||
end
|
||||
end
|
||||
|
||||
local function ln_run(s, d, command, output)
|
||||
if not output then
|
||||
output = "/dev/null"
|
||||
@@ -52,37 +34,6 @@ local function ln_run(s, d, command, output)
|
||||
return string.format("%s >%s 2>&1 &", d .. " " .. command, output)
|
||||
end
|
||||
|
||||
local function gen_include()
|
||||
cmd(string.format("echo '#!/bin/sh' > %s.include", CONFIG_PATH))
|
||||
local function extract_rules(n, a)
|
||||
local _ipt = ipt_bin
|
||||
if n == "6" then
|
||||
_ipt = ip6t_bin
|
||||
end
|
||||
local result = "*" .. a
|
||||
result = result .. "\n" .. sys.exec(_ipt .. '-save -t ' .. a .. ' | grep "PSW-SERVER" | sed -e "s/^-A \\(INPUT\\)/-I \\1 1/"')
|
||||
result = result .. "COMMIT"
|
||||
return result
|
||||
end
|
||||
local f, err = io.open(CONFIG_PATH .. ".include", "a")
|
||||
if f and err == nil then
|
||||
if nft_flag == "0" then
|
||||
f:write(ipt_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n")
|
||||
f:write(ipt_bin .. '-restore -n <<-EOT' .. "\n")
|
||||
f:write(extract_rules("4", "filter") .. "\n")
|
||||
f:write("EOT" .. "\n")
|
||||
f:write(ip6t_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n")
|
||||
f:write(ip6t_bin .. '-restore -n <<-EOT' .. "\n")
|
||||
f:write(extract_rules("6", "filter") .. "\n")
|
||||
f:write("EOT" .. "\n")
|
||||
f:close()
|
||||
else
|
||||
f:write("nft -f " .. NFT_INCLUDE_FILE .. "\n")
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function start()
|
||||
local enabled = tonumber(api.uci_get_s("@global[0]", "enable") or 0)
|
||||
if enabled == nil or enabled == 0 then
|
||||
@@ -90,18 +41,7 @@ local function start()
|
||||
end
|
||||
cmd(string.format("mkdir -p %s %s", CONFIG_PATH, TMP_BIN_PATH))
|
||||
cmd(string.format("touch %s", LOG_APP_FILE))
|
||||
if nft_flag == "0" then
|
||||
ipt("-N PSW-SERVER")
|
||||
ipt("-I INPUT -j PSW-SERVER")
|
||||
ip6t("-N PSW-SERVER")
|
||||
ip6t("-I INPUT -j PSW-SERVER")
|
||||
else
|
||||
nft_file, err = io.open(NFT_INCLUDE_FILE, "w")
|
||||
nft_file:write('#!/usr/sbin/nft -f\n')
|
||||
nft_file:write('add chain inet fw4 PSW-SERVER\n')
|
||||
nft_file:write('flush chain inet fw4 PSW-SERVER\n')
|
||||
nft_file:write('insert rule inet fw4 input position 0 jump PSW-SERVER comment "PSW-SERVER"\n')
|
||||
end
|
||||
local firewall_num = 0
|
||||
api.uci_foreach_s("server", function(server)
|
||||
local id = server[".name"]
|
||||
local enable = server.enable
|
||||
@@ -207,48 +147,38 @@ local function start()
|
||||
cmd(bin)
|
||||
end
|
||||
|
||||
local bind_local = server.bind_local or 0
|
||||
if bind_local and tonumber(bind_local) ~= 1 and port then
|
||||
if nft_flag == "0" then
|
||||
ipt(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
|
||||
ip6t(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
|
||||
if udp_forward == 1 then
|
||||
ipt(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
|
||||
ip6t(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
|
||||
end
|
||||
else
|
||||
nft_file:write(string.format('add rule inet fw4 PSW-SERVER meta l4proto tcp tcp dport {%s} counter accept comment "%s"\n', port, remarks))
|
||||
if udp_forward == 1 then
|
||||
nft_file:write(string.format('add rule inet fw4 PSW-SERVER meta l4proto udp udp dport {%s} counter accept comment "%s"\n', port, remarks))
|
||||
end
|
||||
end
|
||||
local firewall_allow = server.firewall_allow
|
||||
if firewall_allow == "1" then
|
||||
firewall_num = firewall_num + 1
|
||||
local uid = CONFIG .. "_" .. id
|
||||
uci:section("firewall", "rule", uid)
|
||||
uci:set("firewall", uid, "name", uid)
|
||||
uci:set("firewall", uid, "src", server.firewall_allow_src or "wan")
|
||||
uci:set("firewall", uid, "dest_port", port)
|
||||
uci:set("firewall", uid, "target", "ACCEPT")
|
||||
end
|
||||
end
|
||||
end)
|
||||
if nft_flag == "1" then
|
||||
nft_file:write("add rule inet fw4 PSW-SERVER return\n")
|
||||
nft_file:close()
|
||||
cmd("nft -f " .. NFT_INCLUDE_FILE)
|
||||
if firewall_num > 0 then
|
||||
api.uci_save(uci, "firewall", true, true)
|
||||
end
|
||||
gen_include()
|
||||
end
|
||||
|
||||
local function stop()
|
||||
cmd(string.format("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/' | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1", CONFIG_PATH))
|
||||
if nft_flag == "0" then
|
||||
ipt("-D INPUT -j PSW-SERVER 2>/dev/null")
|
||||
ipt("-F PSW-SERVER 2>/dev/null")
|
||||
ipt("-X PSW-SERVER 2>/dev/null")
|
||||
ip6t("-D INPUT -j PSW-SERVER 2>/dev/null")
|
||||
ip6t("-F PSW-SERVER 2>/dev/null")
|
||||
ip6t("-X PSW-SERVER 2>/dev/null")
|
||||
else
|
||||
local nft_cmd = "handles=$(nft -a list chain inet fw4 input | grep -E \"PSW-SERVER\" | awk -F '# handle ' '{print$2}')\n for handle in $handles; do\n nft delete rule inet fw4 input handle ${handle} 2>/dev/null\n done"
|
||||
cmd(nft_cmd)
|
||||
cmd("nft flush chain inet fw4 PSW-SERVER 2>/dev/null")
|
||||
cmd("nft delete chain inet fw4 PSW-SERVER 2>/dev/null")
|
||||
if true then
|
||||
local num = 0
|
||||
uci:foreach("firewall", "rule", function(rule)
|
||||
if rule[".name"]:find(CONFIG) == 1 then
|
||||
num = num + 1
|
||||
uci:delete("firewall", rule[".name"])
|
||||
end
|
||||
end)
|
||||
if num > 0 then
|
||||
api.uci_save(uci, "firewall", true, true)
|
||||
end
|
||||
end
|
||||
cmd(string.format("rm -rf %s %s %s", CONFIG_PATH, LOG_APP_FILE, CONFIG_PATH .. ".include"))
|
||||
cmd(string.format("rm -rf %s %s", CONFIG_PATH, LOG_APP_FILE))
|
||||
end
|
||||
|
||||
if action then
|
||||
|
||||
@@ -762,7 +762,7 @@ function gen_config_server(node)
|
||||
local inbound = {
|
||||
type = node.protocol,
|
||||
tag = "inbound",
|
||||
listen = (node.bind_local == "1") and "127.0.0.1" or "::",
|
||||
listen = "::",
|
||||
listen_port = tonumber(node.port),
|
||||
}
|
||||
|
||||
|
||||
@@ -669,7 +669,7 @@ function gen_config_server(node)
|
||||
-- 传入连接
|
||||
inbounds = {
|
||||
{
|
||||
listen = (node.bind_local == "1") and "127.0.0.1" or nil,
|
||||
listen = "::",
|
||||
port = tonumber(node.port),
|
||||
protocol = node.protocol,
|
||||
settings = settings,
|
||||
|
||||
@@ -24,16 +24,6 @@ local sid = "@global[0]"
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1152px) {
|
||||
#cbi-<%=appname%>-socks input[id*=".<%=appname%>."][id$=".port"],
|
||||
#cbi-<%=appname%>-socks input[id*=".<%=appname%>."][id$=".http_port"] {
|
||||
width: 100px !important;
|
||||
min-width: unset !important;
|
||||
max-width: unset !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
@@ -68,7 +58,7 @@ local sid = "@global[0]"
|
||||
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
async function go() {
|
||||
const _status = document.getElementsByClassName('_status');
|
||||
const _status = document.getElementsByClassName('_socks_status');
|
||||
for (let i = 0; i < _status.length; i++) {
|
||||
const id = _status[i].getAttribute("socks_id");
|
||||
XHR.get('<%=api.url("socks_status")%>', {
|
||||
@@ -76,24 +66,22 @@ local sid = "@global[0]"
|
||||
id: id
|
||||
},
|
||||
function(x, result) {
|
||||
const index = result.index;
|
||||
let div = '';
|
||||
const div1 = '<font style="font-weight:bold;" color="green">✓</font> ';
|
||||
const div2 = '<font style="font-weight:bold;" color="red">X</font> ';
|
||||
|
||||
if (result.socks_status) {
|
||||
div += div1;
|
||||
} else {
|
||||
div += div2;
|
||||
const socks = _status[i].querySelector('._socks');
|
||||
const http = _status[i].querySelector('._http');
|
||||
if (socks) {
|
||||
socks.textContent = result.socks_status ? "✓" : "X";
|
||||
socks.style.fontWeight = "bold";
|
||||
socks.style.color = result.socks_status ? "green" : "red";
|
||||
}
|
||||
if (result.use_http) {
|
||||
if (result.http_status) {
|
||||
div += div1;
|
||||
if (http) {
|
||||
if (result.use_http) {
|
||||
http.textContent = result.http_status ? "✓" : "X";
|
||||
http.style.fontWeight = "bold";
|
||||
http.style.color = result.http_status ? "green" : "red";
|
||||
} else {
|
||||
div += div2;
|
||||
http.textContent = "";
|
||||
}
|
||||
}
|
||||
_status[index].innerHTML = div;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -497,7 +497,8 @@ table td, .table .td {
|
||||
ajax.abortAll();
|
||||
switch (action) {
|
||||
case "add":
|
||||
const dom = document.getElementsByClassName("cbi-tab")[0];
|
||||
const master = document.getElementById("node_list");
|
||||
const dom = master.getElementsByClassName("cbi-tab")[0];
|
||||
const current_group = dom ? (dom.getAttribute("group_name") || "default") : "default";
|
||||
window.location.href='<%=api.url("add_node")%>?redirect=1&group=' + current_group;
|
||||
break;
|
||||
@@ -1215,11 +1216,15 @@ table td, .table .td {
|
||||
|
||||
const set_node_div = {
|
||||
section: '',
|
||||
open(cbi_id) {
|
||||
open(cbi_id, protocol) {
|
||||
this.section = cbi_id;
|
||||
document.getElementById("set_node_div").style.display="block";
|
||||
const node_name = document.getElementById("cbid.<%=appname%>." + cbi_id + ".remarks").value;
|
||||
document.getElementById("set_node_name").textContent = node_name;
|
||||
const shunt_div = document.getElementById("set_node_shunt_div");
|
||||
if (shunt_div) {
|
||||
shunt_div.style.display = protocol === "_shunt" ? "none" : "";
|
||||
}
|
||||
},
|
||||
close() {
|
||||
document.getElementById("set_node_div").style.display="none";
|
||||
@@ -1286,7 +1291,7 @@ table td, .table .td {
|
||||
<td class="td cbi-section-table-cell nowrap cbi-section-actions pw-actions">
|
||||
<div class="node-wrapper">
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:To Top%>" onclick="node_action('row_top', null, {btn:this, group:'{{group}}'})" title="<%:To Top%>"/>
|
||||
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Use%>" id="apply_{{id}}" onclick="set_node_div.open('{{id}}')"/>
|
||||
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Use%>" id="apply_{{id}}" onclick="set_node_div.open('{{id}}','{{protocol}}')"/>
|
||||
<input class="btn cbi-button cbi-button-add" type="button" value="<%:Copy%>" onclick="node_action('copy', '{{id}}')"/>
|
||||
<input class="btn cbi-button cbi-button-edit" type="button" value="<%:Edit%>" onclick="node_action('edit', '{{id}}')" alt="<%:Edit%>" title="<%:Edit%>">
|
||||
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Delete%>" onclick="node_action('del', '{{id}}')" alt="<%:Delete%>" title="<%:Delete%>">
|
||||
@@ -1432,6 +1437,7 @@ table td, .table .td {
|
||||
innerHTML = innerHTML.split("{{remarks_val}}").join(o["remarks"]);
|
||||
innerHTML = innerHTML.split("{{address_val}}").join(o["address"] || "");
|
||||
innerHTML = innerHTML.split("{{port_val}}").join(o["port"] || "");
|
||||
innerHTML = innerHTML.split("{{protocol}}").join(o["protocol"] || "");
|
||||
|
||||
node_tr_html += innerHTML
|
||||
}
|
||||
@@ -1620,20 +1626,27 @@ table td, .table .td {
|
||||
|
||||
<div style="display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; -webkit-justify-content: center; justify-content: center;">
|
||||
<div id="set_node_div">
|
||||
<div class="cbi-value" style="display: flex; justify-content: center; align-items: center; margin: 1em 0; height: 2em;">
|
||||
<div class="cbi-value" style="display: flex; justify-content: center; align-items: center; margin: 0.2em 0; height: 2em;">
|
||||
<font color=#666><%:You choose node is:%></font><a style="color: red" id="set_node_name"></a>
|
||||
<div style="position:absolute; right:0.5em; top: 0.5em;"><input class="btn cbi-button" type="button" onclick="set_node_div.close()" value="X" /></div>
|
||||
</div>
|
||||
<div class="cbi-value" style="justify-content: center; gap: 8px; margin: 1em 0;">
|
||||
<%- if default_node_type == "_shunt" then
|
||||
for i, v in ipairs(shunt_rule_list) do
|
||||
-%>
|
||||
<input class="btn cbi-button" type="button" onclick="set_node_div.set('<%=node%>', '<%=v[".name"]%>')" value="<%=v.remarks%>" />
|
||||
<%-
|
||||
end
|
||||
-%>
|
||||
<% else %>
|
||||
<input class="btn cbi-button" type="button" onclick="set_node_div.set('@global[0]', 'node')" value="<%:Node%>" />
|
||||
<div class="cbi-value" style="justify-content: center; gap: 8px; margin: 0.2em 0;">
|
||||
<div style="margin: 0.5em 0; padding: 0.5em; background: #f7f7f7; border-radius: 4px;">
|
||||
<div class="cbi-section-descr" style="text-align: left;"><a style="color:#FF8C00"><%:Set as the main proxy node:%></a></div>
|
||||
<div>
|
||||
<input class="btn cbi-button" type="button" onclick="set_node_div.set('@global[0]', 'node')" value="<%:OK%>" />
|
||||
</div>
|
||||
</div>
|
||||
<% if default_node_type == "_shunt" then %>
|
||||
<div id="set_node_shunt_div" style="margin: 0.5em 0; padding: 0.5em; background: #f7f7f7; border-radius: 4px;">
|
||||
<div class="cbi-section-descr" style="text-align: left;"><a style="color:#FF8C00"><%:Set as the routing rule node:%></a></div>
|
||||
<div>
|
||||
<% for i, v in ipairs(shunt_rule_list) do %>
|
||||
<input class="btn cbi-button" type="button" onclick="set_node_div.set('<%=node%>', '<%=v[".name"]%>')" value="<%=v.remarks%>" />
|
||||
<% end %>
|
||||
<input class="btn cbi-button" type="button" onclick="set_node_div.set('<%=node%>', 'default_node')" value="<%:Default%>" />
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -148,7 +148,8 @@ table td, .table .td {
|
||||
//<![CDATA[
|
||||
function toPage(action, cbi_id) {
|
||||
if (action == "add") {
|
||||
const dom = document.getElementsByClassName("cbi-tab")[0];
|
||||
const master = document.getElementById("shunt_rule_list");
|
||||
const dom = master.getElementsByClassName("cbi-tab")[0];
|
||||
const current_group = dom ? (dom.getAttribute("group_name") || "default") : "default";
|
||||
const add_name_val = document.getElementById("add_name_" + current_group).value;
|
||||
if (add_name_val.length > 1) {
|
||||
@@ -333,15 +334,19 @@ table td, .table .td {
|
||||
var shunt_rule_list = result
|
||||
|
||||
var group_shunt_rules = {}
|
||||
for (let i = 0; i < shunt_rule_list.length; i++) {
|
||||
let _shunt_rule = shunt_rule_list[i]
|
||||
if (!_shunt_rule.group || _shunt_rule.group === "") {
|
||||
_shunt_rule.group = "default"
|
||||
if (shunt_rule_list.length > 0) {
|
||||
for (let i = 0; i < shunt_rule_list.length; i++) {
|
||||
let _shunt_rule = shunt_rule_list[i]
|
||||
if (!_shunt_rule.group || _shunt_rule.group === "") {
|
||||
_shunt_rule.group = "default"
|
||||
}
|
||||
if (!group_shunt_rules[_shunt_rule.group]) {
|
||||
group_shunt_rules[_shunt_rule.group] = []
|
||||
}
|
||||
group_shunt_rules[_shunt_rule.group].push(_shunt_rule)
|
||||
}
|
||||
if (!group_shunt_rules[_shunt_rule.group]) {
|
||||
group_shunt_rules[_shunt_rule.group] = []
|
||||
}
|
||||
group_shunt_rules[_shunt_rule.group].push(_shunt_rule)
|
||||
} else {
|
||||
group_shunt_rules["default"] = [];
|
||||
}
|
||||
|
||||
var tab_ul_li_html = '';
|
||||
|
||||
@@ -154,12 +154,12 @@ msgstr "当前节点"
|
||||
msgid "Listen Port"
|
||||
msgstr "监听端口"
|
||||
|
||||
msgid "Port Status"
|
||||
msgstr "端口状态"
|
||||
|
||||
msgid "0 is not use"
|
||||
msgstr "0 为不使用"
|
||||
|
||||
msgid "Same as the tcp node"
|
||||
msgstr "与 TCP 节点相同"
|
||||
|
||||
msgid "Current node: %s"
|
||||
msgstr "当前节点:%s"
|
||||
|
||||
@@ -469,6 +469,12 @@ msgstr "你确定要删除选择的节点吗?"
|
||||
msgid "You no select nodes !"
|
||||
msgstr "你没有选择任何节点!"
|
||||
|
||||
msgid "Set as the main proxy node:"
|
||||
msgstr "应用为主代理节点:"
|
||||
|
||||
msgid "Set as the routing rule node:"
|
||||
msgstr "应用为分流规则节点:"
|
||||
|
||||
msgid "Are you sure set this node?"
|
||||
msgstr "你确定要设置这个节点吗?"
|
||||
|
||||
@@ -1607,6 +1613,12 @@ msgstr "本机监听"
|
||||
msgid "When selected, it can only be accessed localhost."
|
||||
msgstr "当勾选时,只能本机访问。"
|
||||
|
||||
msgid "Firewall Allow"
|
||||
msgstr "允许通过防火墙"
|
||||
|
||||
msgid "Source zone"
|
||||
msgstr "源区域"
|
||||
|
||||
msgid "Accept LAN Access"
|
||||
msgstr "接受局域网访问"
|
||||
|
||||
|
||||
@@ -17,21 +17,6 @@ if [ -e "/etc/config/ucitrack" ]; then
|
||||
EOF
|
||||
fi
|
||||
|
||||
uci -q batch <<-EOF
|
||||
delete firewall.passwall_server
|
||||
set firewall.passwall_server=include
|
||||
set firewall.passwall_server.type='script'
|
||||
set firewall.passwall_server.path='/var/etc/passwall_server.include'
|
||||
EOF
|
||||
|
||||
if [ -x "/sbin/fw3" ]; then
|
||||
uci -q set firewall.passwall_server.reload='1'
|
||||
else
|
||||
uci -q delete firewall.passwall_server.reload
|
||||
uci -q delete firewall.passwall_server.fw4_compatible
|
||||
fi
|
||||
uci commit firewall
|
||||
|
||||
# Migrate server sections from the old `user` section type. New user entries
|
||||
# also use `user`, so only sections with a server `type` option are renamed.
|
||||
for sid in $(uci -q show passwall_server | sed -n 's/^passwall_server\.\([^.=]*\)=user$/\1/p'); do
|
||||
|
||||
@@ -15,11 +15,11 @@ UTIL_SS=$LUA_UTIL_PATH/util_shadowsocks.lua
|
||||
UTIL_XRAY=$LUA_UTIL_PATH/util_xray.lua
|
||||
UTIL_NAIVE=$LUA_UTIL_PATH/util_naiveproxy.lua
|
||||
UTIL_HYSTERIA2=$LUA_UTIL_PATH/util_hysteria2.lua
|
||||
SINGBOX_BIN=$(first_type $(config_t_get global_app sing_box_file) sing-box)
|
||||
XRAY_BIN=$(first_type $(config_t_get global_app xray_file) xray)
|
||||
SINGBOX_BIN=$(first_type $(config_n_get @global_app[0] sing_box_file) sing-box)
|
||||
XRAY_BIN=$(first_type $(config_n_get @global_app[0] xray_file) xray)
|
||||
|
||||
check_run_environment() {
|
||||
local prefer_nft=$(config_t_get global_forwarding prefer_nft 1)
|
||||
local prefer_nft=$(config_n_get @global_forwarding[0] prefer_nft 1)
|
||||
local dnsmasq_info=$(dnsmasq -v 2>/dev/null)
|
||||
local dnsmasq_ver=$(echo "$dnsmasq_info" | sed -n '1s/.*version \([0-9.]*\).*/\1/p')
|
||||
# local dnsmasq_opts=$(echo "$dnsmasq_info" | grep -i "Compile time options")
|
||||
@@ -102,7 +102,7 @@ run_singbox() {
|
||||
json_add_string "log" "1"
|
||||
json_add_string "logfile" "${log_file}"
|
||||
fi
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_t_get global loglevel "warn")
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_n_get @global[0] loglevel "warn")
|
||||
json_add_string "loglevel" "$loglevel"
|
||||
|
||||
[ -n "$flag" ] && json_add_string "flag" "$flag"
|
||||
@@ -196,7 +196,7 @@ run_xray() {
|
||||
[ -z "$type" ] && return 1
|
||||
json_init
|
||||
[ -n "$log_file" ] || local log_file="/dev/null"
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_t_get global loglevel "warning")
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_n_get @global[0] loglevel "warning")
|
||||
[ -n "$flag" ] && json_add_string "flag" "$flag"
|
||||
[ -n "$node" ] && json_add_string "node" "$node"
|
||||
[ -n "$use_proxy_list" ] && json_add_string "use_proxy_list" "$use_proxy_list"
|
||||
@@ -481,7 +481,7 @@ run_socks() {
|
||||
json_add_string "local_socks_address" "$bind"
|
||||
json_add_string "local_socks_port" "$socks_port"
|
||||
lua $UTIL_HYSTERIA2 gen_config "$(json_dump)" > $config_file
|
||||
[ -n "$no_run" ] || ln_run "$(first_type $(config_t_get global_app hysteria_file))" "hysteria" $log_file -c "$config_file" client
|
||||
[ -n "$no_run" ] || ln_run "$(first_type $(config_n_get @global_app[0] hysteria_file))" "hysteria" $log_file -c "$config_file" client
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -519,8 +519,8 @@ run_socks() {
|
||||
|
||||
start_global() {
|
||||
[ -z "$NODE" ] && return 1
|
||||
|
||||
local type=$(echo $(config_n_get $NODE type) | tr 'A-Z' 'a-z')
|
||||
[ -z "$type" ] && return 1
|
||||
|
||||
local config_file=${GLOBAL_ACL_PATH}/global.json
|
||||
local log_file=${GLOBAL_ACL_PATH}/global.log
|
||||
@@ -545,7 +545,7 @@ start_global() {
|
||||
port=$node2socks_port
|
||||
remarks="Socks 配置($port 端口)"
|
||||
fi
|
||||
local enable_log=$(config_t_get global log_node 1)
|
||||
local enable_log=$(config_n_get @global[0] log_node 1)
|
||||
[ "$enable_log" != "1" ] && log_file="/dev/null"
|
||||
[ -n "$server_host" ] && [ -n "$port" ] && {
|
||||
check_host $server_host
|
||||
@@ -556,15 +556,15 @@ start_global() {
|
||||
}
|
||||
echolog "全局节点:[$remarks],监听端口:$REDIR_PORT"
|
||||
local on_node_socks=1
|
||||
local node_socks_bind_local=$(config_t_get global node_socks_bind_local 1)
|
||||
local node_socks_bind_local=$(config_n_get @global[0] node_socks_bind_local 1)
|
||||
local node_socks_bind="127.0.0.1"
|
||||
[ "${node_socks_bind_local}" != "1" ] && node_socks_bind="0.0.0.0"
|
||||
local global_socks_port=$(config_t_get global node_socks_port 1070)
|
||||
local global_socks_port=$(config_n_get @global[0] node_socks_port 1070)
|
||||
GLOBAL_SOCKS_port=$(get_new_port $global_socks_port)
|
||||
if [ "$GLOBAL_SOCKS_port" != "$global_socks_port" ]; then
|
||||
echolog "注意:全局节点 Socks 端口冲突,原端口 ${global_socks_port} 已自动更改为 ${GLOBAL_SOCKS_port}!"
|
||||
fi
|
||||
GLOBAL_HTTP_port=$(config_t_get global node_http_port 0)
|
||||
GLOBAL_HTTP_port=$(config_n_get @global[0] node_http_port 0)
|
||||
[ "$GLOBAL_HTTP_port" != "0" ] && local on_node_http=1
|
||||
if [ $PROXY_IPV6 = "1" ]; then
|
||||
echolog "开启实验性IPv6透明代理(TProxy),请确认您的节点及类型支持IPv6!"
|
||||
@@ -616,7 +616,7 @@ start_global() {
|
||||
}
|
||||
|
||||
local protocol=$(config_n_get $NODE protocol)
|
||||
local v2ray_dns_mode=$(config_t_get global v2ray_dns_mode tcp)
|
||||
local v2ray_dns_mode=$(config_n_get @global[0] v2ray_dns_mode tcp)
|
||||
[ "${DNS_MODE}" != "sing-box" ] && [ "$protocol" = "_shunt" ] && {
|
||||
DNS_MODE="sing-box"
|
||||
[ "$v2ray_dns_mode" = "tcp+doh" ] && v2ray_dns_mode="tcp"
|
||||
@@ -638,18 +638,18 @@ start_global() {
|
||||
NO_PLUGIN_DNS=1
|
||||
_args="${_args} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY}"
|
||||
DNSMASQ_FILTER_PROXY_IPV6=0
|
||||
local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip)
|
||||
local _remote_dns_client_ip=$(config_n_get @global[0] remote_dns_client_ip)
|
||||
[ -n "${_remote_dns_client_ip}" ] && _args="${_args} remote_dns_client_ip=${_remote_dns_client_ip}"
|
||||
[ "${DNS_CACHE}" = "0" ] && _args="${_args} dns_cache=0"
|
||||
resolve_dns_port=${NEXT_DNS_LISTEN_PORT}
|
||||
_args="${_args} dns_listen_port=${resolve_dns_port}"
|
||||
|
||||
case "$(config_t_get global direct_dns_mode "auto")" in
|
||||
case "$(config_n_get @global[0] direct_dns_mode "auto")" in
|
||||
udp)
|
||||
_args="${_args} direct_dns_udp_server=$(normalize_dns "$(config_t_get global direct_dns 223.5.5.5:53)")"
|
||||
_args="${_args} direct_dns_udp_server=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")"
|
||||
;;
|
||||
tcp)
|
||||
_args="${_args} direct_dns_tcp_server=$(normalize_dns "$(config_t_get global direct_dns 223.5.5.5:53)")"
|
||||
_args="${_args} direct_dns_tcp_server=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -661,19 +661,19 @@ start_global() {
|
||||
resolve_dns_log="Sing-Box DNS(127.0.0.1#${resolve_dns_port}) -> ${_proto}://${REMOTE_DNS}"
|
||||
;;
|
||||
doh|http3)
|
||||
local remote_dns_doh=$(config_t_get global remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
local remote_dns_doh=$(config_n_get @global[0] remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
_args="${_args} remote_dns_doh=${remote_dns_doh}"
|
||||
resolve_dns_log="Sing-Box DNS(127.0.0.1#${resolve_dns_port}) -> ${remote_dns_doh}"
|
||||
;;
|
||||
esac
|
||||
local remote_fakedns=$(config_t_get global remote_fakedns 0)
|
||||
local remote_fakedns=$(config_n_get @global[0] remote_fakedns 0)
|
||||
[ "${remote_fakedns}" = "1" ] && {
|
||||
REMOTE_FAKEDNS=1
|
||||
_args="${_args} remote_fakedns=1"
|
||||
resolve_dns_log="${resolve_dns_log} + FakeDNS"
|
||||
USE_FAKEDNS=1
|
||||
}
|
||||
_args="${_args} remote_rewrite_ttl=$(config_t_get global remote_rewrite_ttl)"
|
||||
_args="${_args} remote_rewrite_ttl=$(config_n_get @global[0] remote_rewrite_ttl)"
|
||||
NEXT_DNS_LISTEN_PORT=$(expr $NEXT_DNS_LISTEN_PORT + 1)
|
||||
}
|
||||
_args="${_args} use_proxy_list=$USE_PROXY_LIST use_gfw_list=$USE_GFW_LIST chn_list=$CHN_LIST"
|
||||
@@ -692,7 +692,7 @@ start_global() {
|
||||
}
|
||||
|
||||
local protocol=$(config_n_get $NODE protocol)
|
||||
local v2ray_dns_mode=$(config_t_get global v2ray_dns_mode tcp)
|
||||
local v2ray_dns_mode=$(config_n_get @global[0] v2ray_dns_mode tcp)
|
||||
[ "${DNS_MODE}" != "xray" ] && [ "$protocol" = "_shunt" ] && {
|
||||
DNS_MODE="xray"
|
||||
[ "$v2ray_dns_mode" = "http3" ] && v2ray_dns_mode="tcp"
|
||||
@@ -714,18 +714,18 @@ start_global() {
|
||||
NO_PLUGIN_DNS=1
|
||||
_args="${_args} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY}"
|
||||
DNSMASQ_FILTER_PROXY_IPV6=0
|
||||
local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip)
|
||||
local _remote_dns_client_ip=$(config_n_get @global[0] remote_dns_client_ip)
|
||||
[ -n "${_remote_dns_client_ip}" ] && _args="${_args} remote_dns_client_ip=${_remote_dns_client_ip}"
|
||||
[ "${DNS_CACHE}" = "0" ] && _args="${_args} dns_cache=0"
|
||||
resolve_dns_port=${NEXT_DNS_LISTEN_PORT}
|
||||
_args="${_args} dns_listen_port=${resolve_dns_port}"
|
||||
|
||||
case "$(config_t_get global direct_dns_mode "auto")" in
|
||||
case "$(config_n_get @global[0] direct_dns_mode "auto")" in
|
||||
udp)
|
||||
_args="${_args} direct_dns_udp_server=$(normalize_dns "$(config_t_get global direct_dns 223.5.5.5:53)")"
|
||||
_args="${_args} direct_dns_udp_server=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")"
|
||||
;;
|
||||
tcp)
|
||||
_args="${_args} direct_dns_tcp_server=$(normalize_dns "$(config_t_get global direct_dns 223.5.5.5:53)")"
|
||||
_args="${_args} direct_dns_tcp_server=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -737,12 +737,12 @@ start_global() {
|
||||
resolve_dns_log="Xray DNS(127.0.0.1#${resolve_dns_port}) -> ${_proto}://${REMOTE_DNS}"
|
||||
;;
|
||||
doh)
|
||||
local remote_dns_doh=$(config_t_get global remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
local remote_dns_doh=$(config_n_get @global[0] remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
_args="${_args} remote_dns_doh=${remote_dns_doh}"
|
||||
resolve_dns_log="Xray DNS(127.0.0.1#${resolve_dns_port}) -> ${remote_dns_doh}"
|
||||
;;
|
||||
esac
|
||||
local remote_fakedns=$(config_t_get global remote_fakedns 0)
|
||||
local remote_fakedns=$(config_n_get @global[0] remote_fakedns 0)
|
||||
[ "${remote_fakedns}" = "1" ] && {
|
||||
REMOTE_FAKEDNS=1
|
||||
_args="${_args} remote_fakedns=1"
|
||||
@@ -800,7 +800,7 @@ start_global() {
|
||||
}
|
||||
json_add_string "tcp_proxy_way" "${TCP_PROXY_WAY}"
|
||||
lua $UTIL_HYSTERIA2 gen_config "$(json_dump)" > $config_file
|
||||
ln_run "$(first_type $(config_t_get global_app hysteria_file))" "hysteria" $log_file -c "$config_file" client
|
||||
ln_run "$(first_type $(config_n_get @global_app[0] hysteria_file))" "hysteria" $log_file -c "$config_file" client
|
||||
;;
|
||||
esac
|
||||
if [ -n "${_socks_flag}" ]; then
|
||||
@@ -918,7 +918,7 @@ start_crontab() {
|
||||
local update_loop
|
||||
|
||||
if [ "$ENABLED_DEFAULT_ACL" = "1" ] || [ "$ENABLED_ACLS" = "1" ]; then
|
||||
local start_daemon=$(config_t_get global_delay start_daemon 0)
|
||||
local start_daemon=$(config_n_get @global_delay[0] start_daemon 0)
|
||||
[ "$start_daemon" = "1" ] && { $APP_PATH/monitor.sh > /dev/null 2>&1 & }
|
||||
fi
|
||||
|
||||
@@ -969,15 +969,15 @@ start_crontab() {
|
||||
}
|
||||
|
||||
# ===== stop/start/restart =====
|
||||
add_service_cron "$(config_t_get global_delay stop_week_mode)" "$(config_t_get global_delay stop_time_mode)" "stop" "配置定时任务:自动关闭服务。"
|
||||
add_service_cron "$(config_n_get @global_delay[0] stop_week_mode)" "$(config_n_get @global_delay[0] stop_time_mode)" "stop" "配置定时任务:自动关闭服务。"
|
||||
|
||||
add_service_cron "$(config_t_get global_delay start_week_mode)" "$(config_t_get global_delay start_time_mode)" "start" "配置定时任务:自动开启服务。"
|
||||
add_service_cron "$(config_n_get @global_delay[0] start_week_mode)" "$(config_n_get @global_delay[0] start_time_mode)" "start" "配置定时任务:自动开启服务。"
|
||||
|
||||
add_service_cron "$(config_t_get global_delay restart_week_mode)" "$(config_t_get global_delay restart_time_mode)" "restart" "配置定时任务:自动重启服务。"
|
||||
add_service_cron "$(config_n_get @global_delay[0] restart_week_mode)" "$(config_n_get @global_delay[0] restart_time_mode)" "restart" "配置定时任务:自动重启服务。"
|
||||
|
||||
# ===== rule update =====
|
||||
local rules_update_week_mode=$(config_t_get global_rules update_week_mode)
|
||||
local rules_update_time_mode=$(config_t_get global_rules update_time_mode)
|
||||
local rules_update_week_mode=$(config_n_get @global_rules[0] update_week_mode)
|
||||
local rules_update_time_mode=$(config_n_get @global_rules[0] update_time_mode)
|
||||
if [ -n "$rules_update_week_mode" ]; then
|
||||
local rule_t=$(build_time "$rules_update_week_mode" "$rules_update_time_mode")
|
||||
if [ "$rules_update_week_mode" = "8" ]; then
|
||||
@@ -1037,12 +1037,20 @@ stop_crontab() {
|
||||
#echolog "清除定时执行命令。"
|
||||
}
|
||||
|
||||
start_adblock() {
|
||||
[ "$(config_t_get global adblock 0)" != "1" ] && {
|
||||
[ -s $RULES_PATH/my_block_host ] && ln -sf $RULES_PATH/my_block_host $RULES_PATH/block_host || > $RULES_PATH/block_host
|
||||
return
|
||||
}
|
||||
"$APP_PATH/adblock.sh" > /dev/null 2>&1 &
|
||||
}
|
||||
|
||||
start_dns() {
|
||||
echolog "DNS域名解析:"
|
||||
|
||||
local china_ng_local_dns=$(IFS=','; set -- $LOCAL_DNS; [ "${1%%[#:]*}" = "127.0.0.1" ] && echo "$1" || ([ -n "$2" ] && echo "$*" || echo "$1"))
|
||||
local sing_box_local_dns=
|
||||
local direct_dns_mode=$(config_t_get global direct_dns_mode "auto")
|
||||
local direct_dns_mode=$(config_n_get @global[0] direct_dns_mode "auto")
|
||||
|
||||
#获取访问控制节点所使用的DNS分流模式
|
||||
local ACL_RULE_DNSMASQ=0
|
||||
@@ -1056,12 +1064,12 @@ start_dns() {
|
||||
|
||||
case "$direct_dns_mode" in
|
||||
udp)
|
||||
LOCAL_DNS=$(normalize_dns "$(config_t_get global direct_dns 223.5.5.5:53)")
|
||||
LOCAL_DNS=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")
|
||||
china_ng_local_dns=${LOCAL_DNS}
|
||||
sing_box_local_dns="direct_dns_udp_server=${LOCAL_DNS}"
|
||||
;;
|
||||
tcp)
|
||||
local DIRECT_DNS=$(normalize_dns "$(config_t_get global direct_dns 223.5.5.5:53)")
|
||||
local DIRECT_DNS=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")
|
||||
china_ng_local_dns="tcp://${DIRECT_DNS}"
|
||||
sing_box_local_dns="direct_dns_tcp_server=${DIRECT_DNS}"
|
||||
|
||||
@@ -1082,7 +1090,7 @@ start_dns() {
|
||||
esac
|
||||
|
||||
# 追加直连DNS到iptables/nftables
|
||||
[ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && IPT_APPEND_DNS=
|
||||
[ "$(config_n_get @global_haproxy[0] balancing_enable 0)" != "1" ] && IPT_APPEND_DNS=
|
||||
add_default_port() {
|
||||
[ -z "$1" ] && echo "" || echo "$1" | awk -F',' '{for(i=1;i<=NF;i++){if($i !~ /#/) $i=$i"#53";} print $0;}' OFS=','
|
||||
}
|
||||
@@ -1101,7 +1109,7 @@ start_dns() {
|
||||
|
||||
case "$DNS_MODE" in
|
||||
dns2socks)
|
||||
local dns2socks_socks_server=$(echo $(config_t_get global socks_server 127.0.0.1:1080) | sed "s/#/:/g")
|
||||
local dns2socks_socks_server=$(echo $(config_n_get @global[0] socks_server 127.0.0.1:1080) | sed "s/#/:/g")
|
||||
local dns2socks_forward=$(get_first_dns REMOTE_DNS 53 | sed 's/#/:/g')
|
||||
run_dns2socks socks=$dns2socks_socks_server listen_address=127.0.0.1 listen_port=${NEXT_DNS_LISTEN_PORT} dns=$dns2socks_forward cache=$DNS_CACHE
|
||||
echolog " - dns2socks(${TUN_DNS}),${dns2socks_socks_server} -> tcp://${dns2socks_forward}"
|
||||
@@ -1116,17 +1124,17 @@ start_dns() {
|
||||
_args="${_args} direct_dns_query_strategy=${DIRECT_DNS_QUERY_STRATEGY}"
|
||||
_args="${_args} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY}"
|
||||
DNSMASQ_FILTER_PROXY_IPV6=0
|
||||
local remote_fakedns=$(config_t_get global remote_fakedns 0)
|
||||
local remote_fakedns=$(config_n_get @global[0] remote_fakedns 0)
|
||||
[ "${remote_fakedns}" = "1" ] && {
|
||||
REMOTE_FAKEDNS=1
|
||||
_args="${_args} remote_fakedns=1"
|
||||
USE_FAKEDNS=1
|
||||
}
|
||||
_args="${_args} remote_rewrite_ttl=$(config_t_get global remote_rewrite_ttl)"
|
||||
local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip)
|
||||
_args="${_args} remote_rewrite_ttl=$(config_n_get @global[0] remote_rewrite_ttl)"
|
||||
local _remote_dns_client_ip=$(config_n_get @global[0] remote_dns_client_ip)
|
||||
[ -n "${_remote_dns_client_ip}" ] && _args="${_args} remote_dns_client_ip=${_remote_dns_client_ip}"
|
||||
TCP_PROXY_DNS=1
|
||||
local v2ray_dns_mode=$(config_t_get global v2ray_dns_mode tcp)
|
||||
local v2ray_dns_mode=$(config_n_get @global[0] v2ray_dns_mode tcp)
|
||||
_args="${_args} dns_listen_port=${NEXT_DNS_LISTEN_PORT}"
|
||||
_args="${_args} remote_dns_protocol=${v2ray_dns_mode}"
|
||||
case "$v2ray_dns_mode" in
|
||||
@@ -1136,7 +1144,7 @@ start_dns() {
|
||||
echolog " - Sing-Box DNS(${TUN_DNS}) -> ${_proto}://${REMOTE_DNS}"
|
||||
;;
|
||||
doh|http3)
|
||||
local remote_dns_doh=$(config_t_get global remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
local remote_dns_doh=$(config_n_get @global[0] remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
_args="${_args} remote_dns_doh=${remote_dns_doh}"
|
||||
echolog " - Sing-Box DNS(${TUN_DNS}) -> ${remote_dns_doh}"
|
||||
;;
|
||||
@@ -1156,16 +1164,16 @@ start_dns() {
|
||||
_args="${_args} direct_dns_query_strategy=${DIRECT_DNS_QUERY_STRATEGY}"
|
||||
_args="${_args} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY}"
|
||||
DNSMASQ_FILTER_PROXY_IPV6=0
|
||||
local remote_fakedns=$(config_t_get global remote_fakedns 0)
|
||||
local remote_fakedns=$(config_n_get @global[0] remote_fakedns 0)
|
||||
[ "${remote_fakedns}" = "1" ] && {
|
||||
REMOTE_FAKEDNS=1
|
||||
_args="${_args} remote_fakedns=1"
|
||||
USE_FAKEDNS=1
|
||||
}
|
||||
local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip)
|
||||
local _remote_dns_client_ip=$(config_n_get @global[0] remote_dns_client_ip)
|
||||
[ -n "${_remote_dns_client_ip}" ] && _args="${_args} remote_dns_client_ip=${_remote_dns_client_ip}"
|
||||
TCP_PROXY_DNS=1
|
||||
local v2ray_dns_mode=$(config_t_get global v2ray_dns_mode tcp)
|
||||
local v2ray_dns_mode=$(config_n_get @global[0] v2ray_dns_mode tcp)
|
||||
_args="${_args} dns_listen_port=${NEXT_DNS_LISTEN_PORT}"
|
||||
_args="${_args} remote_dns_protocol=${v2ray_dns_mode}"
|
||||
case "$v2ray_dns_mode" in
|
||||
@@ -1175,7 +1183,7 @@ start_dns() {
|
||||
echolog " - Xray DNS(${TUN_DNS}) -> ${_proto}://${REMOTE_DNS}"
|
||||
;;
|
||||
doh)
|
||||
local remote_dns_doh=$(config_t_get global remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
local remote_dns_doh=$(config_n_get @global[0] remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
_args="${_args} remote_dns_doh=${remote_dns_doh}"
|
||||
echolog " - Xray DNS(${TUN_DNS}) -> ${remote_dns_doh}"
|
||||
;;
|
||||
@@ -1219,8 +1227,8 @@ start_dns() {
|
||||
[ "${DNS_SHUNT}" = "smartdns" ] && {
|
||||
if command -v smartdns > /dev/null 2>&1; then
|
||||
rm -rf $TMP_PATH2/dnsmasq_default*
|
||||
local group_domestic=$(config_t_get global group_domestic)
|
||||
local smartdns_remote_dns=$(config_t_get global smartdns_remote_dns)
|
||||
local group_domestic=$(config_n_get @global[0] group_domestic)
|
||||
local smartdns_remote_dns=$(config_n_get @global[0] smartdns_remote_dns)
|
||||
if [ -n "${smartdns_remote_dns}" ] && [ "${smartdns_remote_dns}" != "nil" ]; then
|
||||
smartdns_remote_dns=$(echo ${smartdns_remote_dns} | tr -s ' ' '|')
|
||||
else
|
||||
@@ -1232,7 +1240,7 @@ start_dns() {
|
||||
echolog " - SmartDNS(127.0.0.1#${SMARTDNS_LOCAL_PORT}) -> 国内分组(${group_domestic:-null}),SmartDNS(${china_ng_listen}) -> Dnsmasq"
|
||||
china_ng_listen="${china_ng_listen},::1#${SMARTDNS_LISTEN_PORT}"
|
||||
|
||||
local subnet_ip=$(config_t_get global remote_dns_client_ip)
|
||||
local subnet_ip=$(config_n_get @global[0] remote_dns_client_ip)
|
||||
lua $APP_PATH/helper_smartdns_add.lua -FLAG "default" -SMARTDNS_CONF "/tmp/etc/smartdns/$CONFIG.conf" \
|
||||
-LISTEN_PORT ${SMARTDNS_LISTEN_PORT} -LOCAL_PORT ${SMARTDNS_LOCAL_PORT} \
|
||||
-LOCAL_GROUP ${group_domestic:-null} -REMOTE_GROUP "passwall_proxy" -REMOTE_PROXY_SERVER ${GLOBAL_SOCKS_server} -USE_DEFAULT_DNS "${USE_DEFAULT_DNS:-direct}" \
|
||||
@@ -1277,11 +1285,11 @@ start_dns() {
|
||||
_gfwlist=${USE_GFW_LIST} \
|
||||
_chnlist=${CHN_LIST} \
|
||||
_default_mode=${TCP_PROXY_MODE} \
|
||||
_default_tag=$(config_t_get global chinadns_ng_default_tag smart) \
|
||||
_default_tag=$(config_n_get @global[0] chinadns_ng_default_tag smart) \
|
||||
_no_logic_log=0 \
|
||||
_node=${NODE} \
|
||||
_filter_https=$(config_t_get global force_https_soa 0) \
|
||||
_log=$(config_t_get global log_chinadns_ng 0)
|
||||
_filter_https=$(config_n_get @global[0] force_https_soa 0) \
|
||||
_log=$(config_n_get @global[0] log_chinadns_ng 0)
|
||||
|
||||
USE_DEFAULT_DNS="chinadns_ng"
|
||||
}
|
||||
@@ -1338,16 +1346,8 @@ start_dns() {
|
||||
fi
|
||||
}
|
||||
|
||||
start_adblock() {
|
||||
[ "$(config_t_get global adblock 0)" != "1" ] && {
|
||||
[ -s $RULES_PATH/my_block_host ] && ln -sf $RULES_PATH/my_block_host $RULES_PATH/block_host || > $RULES_PATH/block_host
|
||||
return
|
||||
}
|
||||
"$APP_PATH/adblock.sh" > /dev/null 2>&1 &
|
||||
}
|
||||
|
||||
start_haproxy() {
|
||||
[ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return
|
||||
[ "$(config_n_get @global_haproxy[0] balancing_enable 0)" != "1" ] && return
|
||||
local haproxy_ver=$($(first_type haproxy) -v 2>/dev/null | awk 'NR==1 {print $3}' | cut -d'-' -f1)
|
||||
if [ "$(check_ver "$haproxy_ver" "3.0.0")" = "1" ]; then
|
||||
echolog "* 注意:haproxy($haproxy_ver) 程序版本低,HAPROXY 负载均衡启动失败,请更新到 3.0 以上版本。"
|
||||
@@ -1514,13 +1514,13 @@ acl_app() {
|
||||
_china_ng_listen="127.0.0.1#${chinadns_port},::1#${chinadns_port}"
|
||||
|
||||
_chinadns_local_dns=$(IFS=','; set -- $LOCAL_DNS; [ "${1%%[#:]*}" = "127.0.0.1" ] && echo "$1" || ([ -n "$2" ] && echo "$1,$2" || echo "$1"))
|
||||
_direct_dns_mode=$(config_t_get global direct_dns_mode "auto")
|
||||
_direct_dns_mode=$(config_n_get @global[0] direct_dns_mode "auto")
|
||||
case "${_direct_dns_mode}" in
|
||||
udp)
|
||||
_chinadns_local_dns=$(normalize_dns "$(config_t_get global direct_dns 223.5.5.5:53)")
|
||||
_chinadns_local_dns=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")
|
||||
;;
|
||||
tcp)
|
||||
_chinadns_local_dns="tcp://$(normalize_dns "$(config_t_get global direct_dns 223.5.5.5:53)")"
|
||||
_chinadns_local_dns="tcp://$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1638,7 +1638,7 @@ start() {
|
||||
}
|
||||
mkdir -p /tmp/etc /tmp/log $TMP_PATH $TMP_BIN_PATH $TMP_SCRIPT_FUNC_PATH $TMP_ROUTE_PATH $TMP_ACL_PATH $TMP_PATH2
|
||||
get_config
|
||||
export V2RAY_LOCATION_ASSET=$(config_t_get global_rules v2ray_location_asset "/usr/share/v2ray/")
|
||||
export V2RAY_LOCATION_ASSET=$(config_n_get @global_rules[0] v2ray_location_asset "/usr/share/v2ray/")
|
||||
export XRAY_LOCATION_ASSET=$V2RAY_LOCATION_ASSET
|
||||
export ENABLE_DEPRECATED_GEOSITE=true
|
||||
export ENABLE_DEPRECATED_GEOIP=true
|
||||
@@ -1720,7 +1720,7 @@ stop() {
|
||||
rm -rf $GLOBAL_DNSMASQ_CONF_PATH
|
||||
[ "1" = "1" ] && {
|
||||
#restore logic
|
||||
bak_dnsmasq_dns_redirect=$(config_t_get global dnsmasq_dns_redirect)
|
||||
bak_dnsmasq_dns_redirect=$(config_n_get @global[0] dnsmasq_dns_redirect)
|
||||
[ -n "${bak_dnsmasq_dns_redirect}" ] && {
|
||||
uci -q set dhcp.@dnsmasq[0].dns_redirect="${bak_dnsmasq_dns_redirect}"
|
||||
uci -q commit dhcp
|
||||
@@ -1746,50 +1746,50 @@ stop() {
|
||||
get_config() {
|
||||
ENABLED_DEFAULT_ACL=0
|
||||
REDIR_PORT=$(echo $(get_new_port 1041 tcp,udp))
|
||||
ENABLED=$(config_t_get global enabled 0)
|
||||
SOCKS_ENABLED=$(config_t_get global socks_enabled 0)
|
||||
NODE=$(config_t_get global node)
|
||||
ENABLED=$(config_n_get @global[0] enabled 0)
|
||||
SOCKS_ENABLED=$(config_n_get @global[0] socks_enabled 0)
|
||||
NODE=$(config_n_get @global[0] node)
|
||||
|
||||
[ "$ENABLED" = 1 ] && {
|
||||
if [ -n "$NODE" ] && ([ "$(config_get_type $NODE)" = "nodes" ] || [ "$(config_get_type $NODE)" = "socks" ]); then
|
||||
ENABLED_DEFAULT_ACL=1
|
||||
fi
|
||||
}
|
||||
ENABLED_ACLS=$(config_t_get global acl_enable 0)
|
||||
ENABLED_ACLS=$(config_n_get @global[0] acl_enable 0)
|
||||
set_cache_var ENABLED_DEFAULT_ACL $ENABLED_DEFAULT_ACL
|
||||
set_cache_var ENABLED_ACLS $ENABLED_ACLS
|
||||
|
||||
TCP_PROXY_WAY=$(config_t_get global_forwarding tcp_proxy_way redirect)
|
||||
PROXY_IPV6=$(config_t_get global_forwarding ipv6_tproxy 0)
|
||||
TCP_REDIR_PORTS=$(config_t_get global_forwarding tcp_redir_ports '80,443')
|
||||
UDP_REDIR_PORTS=$(config_t_get global_forwarding udp_redir_ports '1:65535')
|
||||
TCP_NO_REDIR_PORTS=$(config_t_get global_forwarding tcp_no_redir_ports 'disable')
|
||||
UDP_NO_REDIR_PORTS=$(config_t_get global_forwarding udp_no_redir_ports 'disable')
|
||||
TCP_PROXY_DROP_PORTS=$(config_t_get global_forwarding tcp_proxy_drop_ports 'disable')
|
||||
UDP_PROXY_DROP_PORTS=$(config_t_get global_forwarding udp_proxy_drop_ports '80,443')
|
||||
USE_DIRECT_LIST=$(config_t_get global use_direct_list 1)
|
||||
USE_PROXY_LIST=$(config_t_get global use_proxy_list 1)
|
||||
USE_BLOCK_LIST=$(config_t_get global use_block_list 1)
|
||||
USE_GFW_LIST=$(config_t_get global use_gfw_list 1)
|
||||
CHN_LIST=$(config_t_get global chn_list direct)
|
||||
TCP_PROXY_MODE=$(config_t_get global tcp_proxy_mode proxy)
|
||||
UDP_PROXY_MODE=$(config_t_get global udp_proxy_mode proxy)
|
||||
TCP_PROXY_WAY=$(config_n_get @global_forwarding[0] tcp_proxy_way redirect)
|
||||
PROXY_IPV6=$(config_n_get @global_forwarding[0] ipv6_tproxy 0)
|
||||
TCP_REDIR_PORTS=$(config_n_get @global_forwarding[0] tcp_redir_ports '80,443')
|
||||
UDP_REDIR_PORTS=$(config_n_get @global_forwarding[0] udp_redir_ports '1:65535')
|
||||
TCP_NO_REDIR_PORTS=$(config_n_get @global_forwarding[0] tcp_no_redir_ports 'disable')
|
||||
UDP_NO_REDIR_PORTS=$(config_n_get @global_forwarding[0] udp_no_redir_ports 'disable')
|
||||
TCP_PROXY_DROP_PORTS=$(config_n_get @global_forwarding[0] tcp_proxy_drop_ports 'disable')
|
||||
UDP_PROXY_DROP_PORTS=$(config_n_get @global_forwarding[0] udp_proxy_drop_ports '80,443')
|
||||
USE_DIRECT_LIST=$(config_n_get @global[0] use_direct_list 1)
|
||||
USE_PROXY_LIST=$(config_n_get @global[0] use_proxy_list 1)
|
||||
USE_BLOCK_LIST=$(config_n_get @global[0] use_block_list 1)
|
||||
USE_GFW_LIST=$(config_n_get @global[0] use_gfw_list 1)
|
||||
CHN_LIST=$(config_n_get @global[0] chn_list direct)
|
||||
TCP_PROXY_MODE=$(config_n_get @global[0] tcp_proxy_mode proxy)
|
||||
UDP_PROXY_MODE=$(config_n_get @global[0] udp_proxy_mode proxy)
|
||||
[ "${TCP_PROXY_MODE}" != "disable" ] && TCP_PROXY_MODE="proxy"
|
||||
[ "${UDP_PROXY_MODE}" != "disable" ] && UDP_PROXY_MODE="proxy"
|
||||
LOCALHOST_PROXY=$(config_t_get global localhost_proxy 1)
|
||||
LOCALHOST_PROXY=$(config_n_get @global[0] localhost_proxy 1)
|
||||
[ "${LOCALHOST_PROXY}" = 1 ] && {
|
||||
LOCALHOST_TCP_PROXY_MODE=$TCP_PROXY_MODE
|
||||
LOCALHOST_UDP_PROXY_MODE=$UDP_PROXY_MODE
|
||||
}
|
||||
CLIENT_PROXY=$(config_t_get global client_proxy 1)
|
||||
DNS_SHUNT=$(config_t_get global dns_shunt dnsmasq)
|
||||
CLIENT_PROXY=$(config_n_get @global[0] client_proxy 1)
|
||||
DNS_SHUNT=$(config_n_get @global[0] dns_shunt dnsmasq)
|
||||
[ -z "$(first_type $DNS_SHUNT)" ] && DNS_SHUNT="dnsmasq"
|
||||
DNS_MODE=$(config_t_get global dns_mode tcp)
|
||||
[ "$DNS_SHUNT" = "smartdns" ] && DNS_MODE=$(config_t_get global smartdns_dns_mode socks)
|
||||
REMOTE_DNS=$(normalize_dns "$(config_t_get global remote_dns 1.1.1.1:53)")
|
||||
USE_DEFAULT_DNS=$(config_t_get global use_default_dns direct)
|
||||
FILTER_PROXY_IPV6=$(config_t_get global filter_proxy_ipv6 0)
|
||||
DNS_REDIRECT=$(config_t_get global dns_redirect 1)
|
||||
DNS_MODE=$(config_n_get @global[0] dns_mode tcp)
|
||||
[ "$DNS_SHUNT" = "smartdns" ] && DNS_MODE=$(config_n_get @global[0] smartdns_dns_mode socks)
|
||||
REMOTE_DNS=$(normalize_dns "$(config_n_get @global[0] remote_dns 1.1.1.1:53)")
|
||||
USE_DEFAULT_DNS=$(config_n_get @global[0] use_default_dns direct)
|
||||
FILTER_PROXY_IPV6=$(config_n_get @global[0] filter_proxy_ipv6 0)
|
||||
DNS_REDIRECT=$(config_n_get @global[0] dns_redirect 1)
|
||||
|
||||
REDIRECT_LIST="socks ss-rust ssr sing-box xray naiveproxy hysteria2"
|
||||
TPROXY_LIST="socks ss-rust ssr sing-box xray hysteria2"
|
||||
|
||||
@@ -353,7 +353,7 @@ load_acl() {
|
||||
}
|
||||
|
||||
local dns_redirect
|
||||
[ $(config_t_get global dns_redirect "1") = "1" ] && dns_redirect=53
|
||||
[ $(config_n_get @global[0] dns_redirect "1") = "1" ] && dns_redirect=53
|
||||
if ([ -n "$tcp_port" ] && [ -n "${tcp_proxy_mode}" ]) || ([ -n "$udp_port" ] && [ -n "${udp_proxy_mode}" ]); then
|
||||
[ "${use_proxy_list}" = "1" ] && {
|
||||
[ "${use_global_config}" = "0" ] && {
|
||||
@@ -583,7 +583,7 @@ load_acl() {
|
||||
}
|
||||
|
||||
local DNS_REDIRECT
|
||||
[ $(config_t_get global dns_redirect "1") = "1" ] && DNS_REDIRECT=53
|
||||
[ $(config_n_get @global[0] dns_redirect "1") = "1" ] && DNS_REDIRECT=53
|
||||
if [ -n "$NODE" ] && ([ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ]); then
|
||||
[ -n "${DNS_REDIRECT_PORT}" ] && DNS_REDIRECT=${DNS_REDIRECT_PORT}
|
||||
else
|
||||
@@ -769,7 +769,7 @@ filter_server_port() {
|
||||
local port=$(echo "$2" | tr '-' ':' | tr -d ' ')
|
||||
local stream=$(echo "$3" | tr 'A-Z' 'a-z')
|
||||
local ipt_tmp="$ipt_n" _is_tproxy _ipt_cmd _ver multi_ports p ports
|
||||
[ "$(config_t_get global_forwarding tcp_proxy_way redirect)" = "tproxy" ] && _is_tproxy="TPROXY"
|
||||
[ "$(config_n_get @global_forwarding[0] tcp_proxy_way redirect)" = "tproxy" ] && _is_tproxy="TPROXY"
|
||||
[ "$stream" = "udp" ] && _is_tproxy="TPROXY"
|
||||
[ -n "$_is_tproxy" ] && ipt_tmp="$ipt_m"
|
||||
for _ver in 4 6; do
|
||||
@@ -892,8 +892,8 @@ add_firewall_rule() {
|
||||
local USE_DIRECT_LIST_ALL=${USE_DIRECT_LIST}
|
||||
local USE_BLOCK_LIST_ALL=${USE_BLOCK_LIST}
|
||||
USE_SHUNT_NODE=0
|
||||
USE_GEOVIEW=$(config_t_get global_rules enable_geoview)
|
||||
[ -z "$(first_type $(config_t_get global_app geoview_file) geoview)" ] && USE_GEOVIEW=0
|
||||
USE_GEOVIEW=$(config_n_get @global_rules[0] enable_geoview)
|
||||
[ -z "$(first_type $(config_n_get @global_app[0] geoview_file) geoview)" ] && USE_GEOVIEW=0
|
||||
|
||||
[ -n "$NODE" ] && [ "$(config_n_get $NODE protocol)" = "_shunt" ] && USE_SHUNT_NODE=1
|
||||
|
||||
@@ -1022,8 +1022,8 @@ add_firewall_rule() {
|
||||
filter_vpsip > /dev/null 2>&1 &
|
||||
# filter_haproxy > /dev/null 2>&1 &
|
||||
|
||||
accept_icmp=$(config_t_get global_forwarding accept_icmp 0)
|
||||
accept_icmpv6=$(config_t_get global_forwarding accept_icmpv6 0)
|
||||
accept_icmp=$(config_n_get @global_forwarding[0] accept_icmp 0)
|
||||
accept_icmpv6=$(config_n_get @global_forwarding[0] accept_icmpv6 0)
|
||||
|
||||
if [ "${TCP_PROXY_WAY}" = "redirect" ]; then
|
||||
unset is_tproxy
|
||||
@@ -1050,7 +1050,7 @@ add_firewall_rule() {
|
||||
$ipt_n -A PSW_OUTPUT -m mark --mark 255 -j RETURN
|
||||
|
||||
$ipt_n -N PSW_DNS
|
||||
if [ $(config_t_get global dns_redirect "1") = "0" ]; then
|
||||
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
|
||||
#Only hijack when dest address is local IP
|
||||
$ipt_n -I PREROUTING -m set --match-set $IPSET_LAN src $(dst $IPSET_LOCAL) -j PSW_DNS
|
||||
else
|
||||
@@ -1121,7 +1121,7 @@ add_firewall_rule() {
|
||||
}
|
||||
|
||||
$ip6t_n -N PSW_DNS
|
||||
if [ $(config_t_get global dns_redirect "1") = "0" ]; then
|
||||
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
|
||||
#Only hijack when dest address is local IP
|
||||
$ip6t_n -I PREROUTING -m set --match-set $IPSET_LAN6 src $(dst $IPSET_LOCAL6) -j PSW_DNS
|
||||
else
|
||||
@@ -1532,7 +1532,7 @@ start() {
|
||||
stop() {
|
||||
[ -z "$(command -v echolog)" ] && . "$UTILS_PATH"
|
||||
del_firewall_rule
|
||||
[ $(config_t_get global flush_set_on_reboot "0") = "1" ] || [ $(config_t_get global flush_set "0") = "1" ] && {
|
||||
[ $(config_n_get @global[0] flush_set_on_reboot "0") = "1" ] || [ $(config_n_get @global[0] flush_set "0") = "1" ] && {
|
||||
uci -q delete ${CONFIG}.@global[0].flush_set
|
||||
uci -q commit ${CONFIG}
|
||||
flush_ipset
|
||||
|
||||
@@ -8,9 +8,13 @@ MAX_RESTART_COUNT=10
|
||||
RESTART_STATS_DIR="${TMP_PATH}/script_rstats"
|
||||
mkdir -p "$RESTART_STATS_DIR"
|
||||
|
||||
ENABLED=$(config_n_get @global[0] enabled 0)
|
||||
[ "$ENABLED" != 1 ] && return 1
|
||||
ENABLED=$(config_n_get @global_delay[0] start_daemon 0)
|
||||
[ "$ENABLED" != 1 ] && return 1
|
||||
sleep 58s
|
||||
last_cleanup_date=$(date +%Y%m%d)
|
||||
while [ 1 -eq 1 ]; do
|
||||
while [ "$ENABLED" -eq 1 ]; do
|
||||
[ -f "$LOCK_FILE" ] && {
|
||||
sleep 6s
|
||||
continue
|
||||
|
||||
@@ -406,7 +406,7 @@ load_acl() {
|
||||
}
|
||||
|
||||
local dns_redirect
|
||||
[ $(config_t_get global dns_redirect "1") = "1" ] && dns_redirect=53
|
||||
[ $(config_n_get @global[0] dns_redirect "1") = "1" ] && dns_redirect=53
|
||||
if ([ -n "$tcp_port" ] && [ -n "${tcp_proxy_mode}" ]) || ([ -n "$udp_port" ] && [ -n "${udp_proxy_mode}" ]); then
|
||||
[ "${use_proxy_list}" = "1" ] && {
|
||||
[ "${use_global_config}" = "0" ] && {
|
||||
@@ -643,7 +643,7 @@ load_acl() {
|
||||
}
|
||||
|
||||
local DNS_REDIRECT
|
||||
[ $(config_t_get global dns_redirect "1") = "1" ] && DNS_REDIRECT=53
|
||||
[ $(config_n_get @global[0] dns_redirect "1") = "1" ] && DNS_REDIRECT=53
|
||||
if [ -n "$NODE" ] && ([ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ]); then
|
||||
[ -n "${DNS_REDIRECT_PORT}" ] && DNS_REDIRECT=${DNS_REDIRECT_PORT}
|
||||
else
|
||||
@@ -842,7 +842,7 @@ filter_server_port() {
|
||||
local stream=$(echo "$3" | tr 'A-Z' 'a-z')
|
||||
local _ip_type _port_expr _ver _is_tproxy
|
||||
local _nft_output_chain="PSW_OUTPUT_NAT"
|
||||
[ "$(config_t_get global_forwarding tcp_proxy_way redirect)" = "tproxy" ] && _is_tproxy="TPROXY"
|
||||
[ "$(config_n_get @global_forwarding[0] tcp_proxy_way redirect)" = "tproxy" ] && _is_tproxy="TPROXY"
|
||||
[ "$stream" = "udp" ] && _is_tproxy="TPROXY"
|
||||
[ -n "$_is_tproxy" ] && _nft_output_chain="PSW_OUTPUT_MANGLE"
|
||||
case "$port" in
|
||||
@@ -996,8 +996,8 @@ add_firewall_rule() {
|
||||
local USE_DIRECT_LIST_ALL=${USE_DIRECT_LIST}
|
||||
local USE_BLOCK_LIST_ALL=${USE_BLOCK_LIST}
|
||||
USE_SHUNT_NODE=0
|
||||
USE_GEOVIEW=$(config_t_get global_rules enable_geoview)
|
||||
[ -z "$(first_type $(config_t_get global_app geoview_file) geoview)" ] && USE_GEOVIEW=0
|
||||
USE_GEOVIEW=$(config_n_get @global_rules[0] enable_geoview)
|
||||
[ -z "$(first_type $(config_n_get @global_app[0] geoview_file) geoview)" ] && USE_GEOVIEW=0
|
||||
|
||||
[ -n "$NODE" ] && [ "$(config_n_get $NODE protocol)" = "_shunt" ] && USE_SHUNT_NODE=1
|
||||
|
||||
@@ -1114,8 +1114,8 @@ add_firewall_rule() {
|
||||
# Prevent some conditions
|
||||
filter_vps_addr $(config_n_get $NODE address) $(config_n_get $NODE download_address) > /dev/null 2>&1 &
|
||||
|
||||
accept_icmp=$(config_t_get global_forwarding accept_icmp 0)
|
||||
accept_icmpv6=$(config_t_get global_forwarding accept_icmpv6 0)
|
||||
accept_icmp=$(config_n_get @global_forwarding[0] accept_icmp 0)
|
||||
accept_icmpv6=$(config_n_get @global_forwarding[0] accept_icmpv6 0)
|
||||
|
||||
if [ "${TCP_PROXY_WAY}" = "redirect" ]; then
|
||||
unset is_tproxy
|
||||
@@ -1134,7 +1134,7 @@ add_firewall_rule() {
|
||||
|
||||
nft "add chain $NFTABLE_NAME PSW_DNS"
|
||||
nft "flush chain $NFTABLE_NAME PSW_DNS"
|
||||
if [ $(config_t_get global dns_redirect "1") = "0" ]; then
|
||||
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
|
||||
#Only hijack when dest address is local IP
|
||||
nft "insert rule $NFTABLE_NAME dstnat ip saddr @${NFTSET_LAN} ip daddr @${NFTSET_LOCAL} jump PSW_DNS"
|
||||
nft "insert rule $NFTABLE_NAME dstnat ip6 saddr @${NFTSET_LAN6} ip6 daddr @${NFTSET_LOCAL6} jump PSW_DNS"
|
||||
@@ -1570,7 +1570,7 @@ start() {
|
||||
stop() {
|
||||
[ -z "$(command -v echolog)" ] && . "$UTILS_PATH"
|
||||
del_firewall_rule
|
||||
[ $(config_t_get global flush_set_on_reboot "0") = "1" ] || [ $(config_t_get global flush_set "0") = "1" ] && {
|
||||
[ $(config_n_get @global[0] flush_set_on_reboot "0") = "1" ] || [ $(config_n_get @global[0] flush_set "0") = "1" ] && {
|
||||
uci -q delete ${CONFIG}.@global[0].flush_set
|
||||
uci -q commit ${CONFIG}
|
||||
#flush_table
|
||||
|
||||
@@ -18,8 +18,8 @@ do
|
||||
|
||||
if [ "$CFG_UPDATE_INT" -ne 0 ]; then
|
||||
|
||||
restart_week_mode=$(config_t_get global_delay restart_week_mode)
|
||||
restart_interval_mode=$(config_t_get global_delay restart_interval_mode)
|
||||
restart_week_mode=$(config_n_get @global_delay[0] restart_week_mode)
|
||||
restart_interval_mode=$(config_n_get @global_delay[0] restart_interval_mode)
|
||||
restart_interval_mode=$(expr "$restart_interval_mode" \* 60)
|
||||
if [ -n "$restart_week_mode" ]; then
|
||||
[ "$restart_week_mode" = "8" ] && {
|
||||
@@ -27,8 +27,8 @@ do
|
||||
}
|
||||
fi
|
||||
|
||||
rules_update_week_mode=$(config_t_get global_rules update_week_mode)
|
||||
rules_update_interval_mode=$(config_t_get global_rules update_interval_mode)
|
||||
rules_update_week_mode=$(config_n_get @global_rules[0] update_week_mode)
|
||||
rules_update_interval_mode=$(config_n_get @global_rules[0] update_interval_mode)
|
||||
rules_update_interval_mode=$(expr "$rules_update_interval_mode" \* 60)
|
||||
if [ -n "$rules_update_week_mode" ]; then
|
||||
[ "$rules_update_week_mode" = "8" ] && {
|
||||
|
||||
@@ -61,7 +61,7 @@ url_test_node() {
|
||||
local curlx="socks5h://127.0.0.1:${_tmp_port}"
|
||||
fi
|
||||
sleep 2s
|
||||
local probeUrl=$(config_t_get global_other url_test_url https://www.google.com/generate_204)
|
||||
local probeUrl=$(config_n_get @global_other[0] url_test_url https://www.google.com/generate_204)
|
||||
result=$(curl --connect-timeout 3 --max-time 5 -o /dev/null -I -skL -w "%{http_code}:%{time_pretransfer}" -x ${curlx} "${probeUrl}")
|
||||
# 结束 SS 插件进程
|
||||
local pid_file="${TMP_PATH}/url_test_${node_id}_plugin.pid"
|
||||
|
||||
@@ -40,12 +40,6 @@ config_n_get() {
|
||||
echo "${ret:=$3}"
|
||||
}
|
||||
|
||||
config_t_get() {
|
||||
local index=${4:-0}
|
||||
local ret=$(uci -q get "${CONFIG}.@${1}[${index}].${2}" 2>/dev/null)
|
||||
echo "${ret:=${3}}"
|
||||
}
|
||||
|
||||
config_t_set() {
|
||||
local index=${4:-0}
|
||||
local ret=$(uci -q set "${CONFIG}.@${1}[${index}].${2}=${3}" 2>/dev/null)
|
||||
@@ -70,9 +64,9 @@ get_geoip() {
|
||||
local geoip_type_flag=""
|
||||
local output_path="${geo_output_path}/geoip-${geoip_code}-$2"
|
||||
[ ! -s "${output_path}" ] && {
|
||||
local geoip_path="$(config_t_get global_rules v2ray_location_asset)"
|
||||
local geoip_path="$(config_n_get @global_rules[0] v2ray_location_asset)"
|
||||
geoip_path="${geoip_path%*/}/geoip.dat"
|
||||
local bin="$(first_type $(config_t_get global_app geoview_file) geoview)"
|
||||
local bin="$(first_type $(config_n_get @global_app[0] geoview_file) geoview)"
|
||||
[ -n "$bin" ] && [ -s "$geoip_path" ] || { echo ""; return; }
|
||||
case "$2" in
|
||||
"ipv4") geoip_type_flag="-ipv6=false" ;;
|
||||
@@ -480,8 +474,8 @@ ln_run() {
|
||||
return 1
|
||||
}
|
||||
[ "${output}" != "/dev/null" ] && [ -n "$(echo "${output}" | grep -E "default|socks_")" ] && [ "${ln_name}" != "chinadns-ng" ] && {
|
||||
local persist_log_path=$(config_t_get global persist_log_path)
|
||||
local sys_log=$(config_t_get global sys_log "0")
|
||||
local persist_log_path=$(config_n_get @global[0] persist_log_path)
|
||||
local sys_log=$(config_n_get @global[0] sys_log "0")
|
||||
}
|
||||
if [ -z "$persist_log_path" ] && [ "$sys_log" != "1" ]; then
|
||||
${file_func:-echolog " - ${ln_name}"} "$@" >${output} 2>&1 &
|
||||
|
||||
@@ -7,14 +7,13 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=26.8.20
|
||||
PKG_RELEASE:=98
|
||||
PKG_RELEASE:=99
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Server \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \
|
||||
@@ -104,11 +103,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy
|
||||
select PACKAGE_haproxy
|
||||
default y if aarch64||arm||i386||x86_64
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria
|
||||
bool "Include Hysteria"
|
||||
select PACKAGE_hysteria
|
||||
default n
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client
|
||||
bool "Include Shadowsocks Rust Client"
|
||||
depends on !i386
|
||||
|
||||
@@ -72,7 +72,6 @@ function index()
|
||||
entry({"admin", "services", appname, "get_now_use_node"}, call("get_now_use_node")).leaf = true
|
||||
entry({"admin", "services", appname, "get_redir_log"}, call("get_redir_log")).leaf = true
|
||||
entry({"admin", "services", appname, "get_socks_log"}, call("get_socks_log")).leaf = true
|
||||
entry({"admin", "services", appname, "get_acl_log"}, call("get_acl_log")).leaf = true
|
||||
entry({"admin", "services", appname, "get_log"}, call("get_log")).leaf = true
|
||||
entry({"admin", "services", appname, "clear_log"}, call("clear_log")).leaf = true
|
||||
entry({"admin", "services", appname, "index_status"}, call("index_status")).leaf = true
|
||||
@@ -304,10 +303,9 @@ end
|
||||
|
||||
function get_redir_log()
|
||||
local id = http.formvalue("id")
|
||||
local name = http.formvalue("name")
|
||||
local file_path = api.TMP_PATH .. "/acl/" .. id .. "/" .. name .. ".log"
|
||||
local file_path = api.TMP_PATH .. "/acl/" .. id .. ".log"
|
||||
if nixio.fs.access(file_path) then
|
||||
local content = luci.sys.exec("tail -n 19999 '" .. file_path .. "'")
|
||||
local content = luci.sys.exec("tail -n 5000 '" .. file_path .. "'")
|
||||
content = content:gsub("\n", "<br />")
|
||||
http.write(content)
|
||||
else
|
||||
@@ -327,18 +325,6 @@ function get_socks_log()
|
||||
end
|
||||
end
|
||||
|
||||
function get_acl_log()
|
||||
local id = http.formvalue("id")
|
||||
local path = api.TMP_PATH .. "/acl/" .. id .. "/node.log"
|
||||
if nixio.fs.access(path) then
|
||||
local content = luci.sys.exec("tail -n 5000 '" .. path .. "'")
|
||||
content = content:gsub("\n", "<br />")
|
||||
http.write(content)
|
||||
else
|
||||
http.write(string.format("<script>alert('%s');window.close();</script>", i18n.translate("Not enabled log")))
|
||||
end
|
||||
end
|
||||
|
||||
function get_log()
|
||||
-- luci.sys.exec("[ -f /tmp/log/passwall2.log ] && sed '1!G;h;$!d' /tmp/log/passwall2.log > /tmp/log/passwall2_show.log")
|
||||
http.write(luci.sys.exec("[ -f '/tmp/log/passwall2.log' ] && cat /tmp/log/passwall2.log"))
|
||||
@@ -350,7 +336,7 @@ end
|
||||
|
||||
function index_status()
|
||||
local e = {}
|
||||
e["global_status"] = luci.sys.call("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/bin/' | grep 'default' | grep 'global' >/dev/null" % api.TMP_PATH) == 0
|
||||
e["global_status"] = luci.sys.call("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/bin/' | grep '/acl/default' >/dev/null" % api.TMP_PATH) == 0
|
||||
http_write_json(e)
|
||||
end
|
||||
|
||||
|
||||
@@ -50,20 +50,11 @@ end
|
||||
|
||||
o = s:option(DummyValue, "sources", translate("Source"))
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
local e = ''
|
||||
local v = Value.cfgvalue(t, n) or '-'
|
||||
string.gsub(v, '[^' .. " " .. ']+', function(w)
|
||||
local a = w
|
||||
if mac_t[w] then
|
||||
a = a .. ' (' .. mac_t[w].ip .. ')'
|
||||
end
|
||||
if #e > 0 then
|
||||
e = e .. "<br />"
|
||||
end
|
||||
e = e .. a
|
||||
end)
|
||||
return e
|
||||
o.cfgvalue = function(self, section)
|
||||
local v = self.map:get(section, self.option) or {}
|
||||
if type(v) == "table" then
|
||||
return table.concat(v, "<br/>")
|
||||
end
|
||||
end
|
||||
|
||||
i = s:option(DummyValue, "mode", translate("Mode"))
|
||||
@@ -71,6 +62,8 @@ i.cfgvalue = function(t, n)
|
||||
local v = Value.cfgvalue(t, n) or '0'
|
||||
if v == "1" then
|
||||
return translate("Proxy")
|
||||
elseif v == "2" then
|
||||
return translate("Proxy") .. " " .. translate("Use global config")
|
||||
end
|
||||
return translate("No Proxy")
|
||||
end
|
||||
|
||||
@@ -98,25 +98,9 @@ sources.description = "<ul><li>" .. translate("Example:")
|
||||
.. "</li><li>" .. translate("IP range") .. ": 192.168.1.100-192.168.1.200"
|
||||
.. "</li><li>" .. translate("IPSet") .. ": ipset:lanlist"
|
||||
.. "</li></ul>"
|
||||
sources.cast = "string"
|
||||
for _, key in pairs(mac_t) do
|
||||
sources:value(key.mac, "%s (%s)" % {key.mac, key.ip})
|
||||
end
|
||||
|
||||
sources.cfgvalue = function(self, section)
|
||||
local value
|
||||
if self.tag_error[section] then
|
||||
value = self:formvalue(section)
|
||||
else
|
||||
value = self.map:get(section, self.option)
|
||||
if type(value) == "string" then
|
||||
local value2 = {}
|
||||
string.gsub(value, '[^' .. " " .. ']+', function(w) table.insert(value2, w) end)
|
||||
value = value2
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
sources.validate = function(self, value, t)
|
||||
local err = {}
|
||||
for _, v in ipairs(value) do
|
||||
@@ -155,47 +139,75 @@ sources.validate = function(self, value, t)
|
||||
return value
|
||||
end
|
||||
|
||||
local NODE = m:get("@global[0]", "node")
|
||||
o = s:option(ListValue, "mode", translate("Mode"))
|
||||
o:value("0", translate("No Proxy"))
|
||||
o:value("1", translate("Proxy"))
|
||||
o:value("2", translate("Proxy") .. " " .. translate("Use global config") .. "(" .. api.get_node_name(NODE) .. ")")
|
||||
|
||||
---- TCP No Redir Ports
|
||||
local TCP_NO_REDIR_PORTS = m:get("@global_forwarding[0]", "tcp_no_redir_ports")
|
||||
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
|
||||
o:value("", translate("Use global config") .. "(" .. TCP_NO_REDIR_PORTS .. ")")
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("", translate("No patterns are used"))
|
||||
o:value("1:65535", translate("All"))
|
||||
o:depends("mode", "1")
|
||||
o:depends("mode", "2")
|
||||
o.validate = port_validate
|
||||
|
||||
---- UDP No Redir Ports
|
||||
local UDP_NO_REDIR_PORTS = m:get("@global_forwarding[0]", "udp_no_redir_ports")
|
||||
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"))
|
||||
o:value("", translate("Use global config") .. "(" .. UDP_NO_REDIR_PORTS .. ")")
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("", translate("No patterns are used"))
|
||||
o:value("1:65535", translate("All"))
|
||||
o:depends("mode", "1")
|
||||
o:depends("mode", "2")
|
||||
o.validate = port_validate
|
||||
|
||||
o = s:option(DummyValue, "_hide_node_option", "")
|
||||
o = s:option(DummyValue, "_show_tcp_redir", "")
|
||||
o.template = m:template_path("/cbi/hidevalue")
|
||||
o.value = "1"
|
||||
o:depends({ tcp_no_redir_ports = "1:65535", ['!reverse'] = true })
|
||||
|
||||
o = s:option(DummyValue, "_show_udp_redir", "")
|
||||
o.template = m:template_path("/cbi/hidevalue")
|
||||
o.value = "1"
|
||||
o:depends({ udp_no_redir_ports = "1:65535", ['!reverse'] = true })
|
||||
|
||||
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
|
||||
o:value("1:65535", translate("All"))
|
||||
o:value("22,25,53,80,143,443,465,587,853,873,993,995,5222,8080,8443,9418", translate("Common Use"))
|
||||
o:value("80,443", "80,443")
|
||||
o.default = o.keylist[1]
|
||||
o.validate = port_validate
|
||||
o:depends({ _node = "1", _show_tcp_redir = "1" })
|
||||
o:depends({ mode = "2", _show_tcp_redir = "1" })
|
||||
|
||||
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
|
||||
o:value("1:65535", translate("All"))
|
||||
o.default = o.keylist[1]
|
||||
o.validate = port_validate
|
||||
o:depends({ _node = "1", _show_udp_redir = "1" })
|
||||
o:depends({ mode = "2", _show_udp_redir = "1" })
|
||||
|
||||
o = s:option(DummyValue, "tips", " ")
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
return string.format('<font color="red">%s</font>',
|
||||
translate("The port settings support single ports and ranges.<br>Separate multiple ports with commas (,).<br>Example: 21,80,443,1000:2000."))
|
||||
end
|
||||
o:depends("mode", "1")
|
||||
o:depends("mode", "2")
|
||||
|
||||
o = s:option(DummyValue, "_no_proxy", "")
|
||||
o.template = m:template_path("/cbi/hidevalue")
|
||||
o.value = "1"
|
||||
o:depends("mode", "0")
|
||||
o:depends({ tcp_no_redir_ports = "1:65535", udp_no_redir_ports = "1:65535" })
|
||||
if TCP_NO_REDIR_PORTS == "1:65535" and UDP_NO_REDIR_PORTS == "1:65535" then
|
||||
o:depends({ tcp_no_redir_ports = "", udp_no_redir_ports = "" })
|
||||
end
|
||||
|
||||
local GLOBAL_ENABLED = m:get("@global[0]", "enabled")
|
||||
local NODE = m:get("@global[0]", "node")
|
||||
o = s:option(DummyValue, "_show_node_option", "")
|
||||
o.template = m:template_path("/cbi/hidevalue")
|
||||
o.value = "1"
|
||||
o:depends({ mode = "1", _no_proxy = "" })
|
||||
|
||||
o = s:option(ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
|
||||
if GLOBAL_ENABLED == "1" and NODE then
|
||||
o:value("", translate("Use global config") .. "(" .. api.get_node_name(NODE) .. ")")
|
||||
o.group = {""}
|
||||
else
|
||||
o.group = {}
|
||||
end
|
||||
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
|
||||
o.group = {}
|
||||
o:depends("_show_node_option", "1")
|
||||
o.template = m:template_path("/cbi/nodes_listvalue")
|
||||
|
||||
current_node_id = o:formvalue(arg[1])
|
||||
@@ -204,9 +216,14 @@ if not current_node_id then
|
||||
end
|
||||
current_node = current_node_id and m:get(current_node_id) or {}
|
||||
|
||||
o = s:option(Flag, "log", translate("Enable Node Log"))
|
||||
o = s:option(DummyValue, "_node", "")
|
||||
o.template = m:template_path("/cbi/hidevalue")
|
||||
o.value = "1"
|
||||
o:depends({ node = "", ['!reverse'] = true })
|
||||
|
||||
o = s:option(Flag, "log", translate("Enable Node Log"))
|
||||
o:depends("_node", "1")
|
||||
|
||||
o = s:option(ListValue, "loglevel", translate("Log Level"))
|
||||
o.default = "warn"
|
||||
o:value("debug", "Debug")
|
||||
@@ -218,8 +235,8 @@ o:depends("log", "1")
|
||||
o = s:option(DummyValue, "_acl_log", translate("Log File"))
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
local log_path = api.TMP_PATH .. "/acl/" .. arg[1] .. "/node.log"
|
||||
local log_url = api.url("get_acl_log") .. "?id=" .. arg[1]
|
||||
local log_path = api.TMP_PATH .. "/acl/" .. arg[1] .. ".log"
|
||||
local log_url = api.url("get_redir_log") .. "?id=" .. arg[1]
|
||||
return string.format(
|
||||
'<code>%s</code> <input class="btn cbi-button cbi-button-apply" type="button" value="%s" onclick="window.open(\'%s\', \'_blank\')" />',
|
||||
log_path,
|
||||
@@ -229,46 +246,17 @@ o.cfgvalue = function(t, n)
|
||||
end
|
||||
o:depends("log", "1")
|
||||
|
||||
---- TCP Redir Ports
|
||||
local TCP_REDIR_PORTS = m:get("@global_forwarding[0]", "tcp_redir_ports")
|
||||
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
|
||||
o:value("", translate("Use global config") .. "(" .. TCP_REDIR_PORTS .. ")")
|
||||
o:value("1:65535", translate("All"))
|
||||
o:value("22,25,53,80,143,443,465,587,853,873,993,995,5222,8080,8443,9418", translate("Common Use"))
|
||||
o:value("80,443", "80,443")
|
||||
o.validate = port_validate
|
||||
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
|
||||
|
||||
---- UDP Redir Ports
|
||||
local UDP_REDIR_PORTS = m:get("@global_forwarding[0]", "udp_redir_ports")
|
||||
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
|
||||
o:value("", translate("Use global config") .. "(" .. UDP_REDIR_PORTS .. ")")
|
||||
o:value("1:65535", translate("All"))
|
||||
o.validate = port_validate
|
||||
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
|
||||
|
||||
o = s:option(DummyValue, "tips", " ")
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
return string.format('<font color="red">%s</font>',
|
||||
translate("The port settings support single ports and ranges.<br>Separate multiple ports with commas (,).<br>Example: 21,80,443,1000:2000."))
|
||||
end
|
||||
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
|
||||
|
||||
o = s:option(DummyValue, "_hide_dns_option", "")
|
||||
o = s:option(DummyValue, "_show_dns_option", "")
|
||||
o.template = m:template_path("/cbi/hidevalue")
|
||||
o.value = "1"
|
||||
o:depends({ node = "" })
|
||||
if GLOBAL_ENABLED == "1" and NODE then
|
||||
o:depends({ node = NODE })
|
||||
end
|
||||
o:depends("_hide", "1")
|
||||
|
||||
o = s:option(ListValue, "direct_dns_query_strategy", translate("Direct Query Strategy"))
|
||||
o.default = "UseIP"
|
||||
o:value("UseIP")
|
||||
o:value("UseIPv4")
|
||||
o:value("UseIPv6")
|
||||
o:depends({ _hide_dns_option = "1", ['!reverse'] = true })
|
||||
o:depends("_show_dns_option", "1")
|
||||
|
||||
o = s:option(ListValue, "remote_dns_protocol", translate("Remote DNS Protocol"))
|
||||
o:value("tcp", "TCP")
|
||||
@@ -279,7 +267,7 @@ if current_node.type == "sing-box" then
|
||||
o:value("quic", "QUIC(DoQ)")
|
||||
o:value("http3", "HTTP3(DoH3)")
|
||||
end
|
||||
o:depends({ _hide_dns_option = "1", ['!reverse'] = true })
|
||||
o:depends("_show_dns_option", "1")
|
||||
|
||||
---- DNS over TCP or UDP or TLS (DoT) or QUIC (DoQ)
|
||||
o = s:option(Value, "remote_dns", translate("Remote DNS"))
|
||||
@@ -356,12 +344,13 @@ o:depends("remote_dns_protocol", "tls")
|
||||
o = s:option(Value, "remote_rewrite_ttl", translate("Remote DNS") .. " TTL")
|
||||
o.datatype = "min(1)"
|
||||
o.default = "30"
|
||||
o:depends("_hide", "1")
|
||||
|
||||
o = s:option(ListValue, "dns_hosts_mode", translate("Domain Override"))
|
||||
o:value("default", translate("Use global config"))
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("custom", translate("-- custom --"))
|
||||
o:depends({ _hide_dns_option = "1", ['!reverse'] = true })
|
||||
o:depends("_show_dns_option", "1")
|
||||
|
||||
o = s:option(TextValue, "dns_hosts", translate("Domain Override"))
|
||||
o.rows = 5
|
||||
@@ -385,6 +374,7 @@ for k, v in pairs(nodes_table) do
|
||||
if v.type == "sing-box" then
|
||||
s.fields["remote_rewrite_ttl"]:depends({ node = v.id })
|
||||
end
|
||||
s.fields["_show_dns_option"]:depends({ mode = "1", node = v.id })
|
||||
if v.node_type == "normal" or v.protocol == "_balancing" or v.protocol == "_urltest" then
|
||||
--Shunt node has its own separate options.
|
||||
s.fields["remote_fakedns"]:depends({ node = v.id, remote_dns_protocol = "tcp" })
|
||||
|
||||
@@ -282,8 +282,8 @@ loglevel:value("error")
|
||||
o = s:taboption("log", DummyValue, "_log", translate("Log File"))
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
local log_path = api.TMP_PATH .. "/acl/default/global.log"
|
||||
local log_url = api.url("get_redir_log") .. "?id=default&name=global"
|
||||
local log_path = api.TMP_PATH .. "/acl/default.log"
|
||||
local log_url = api.url("get_redir_log") .. "?id=default"
|
||||
return string.format(
|
||||
'<code>%s</code> <input class="btn cbi-button cbi-button-apply" type="button" value="%s" onclick="window.open(\'%s\', \'_blank\')" />',
|
||||
log_path,
|
||||
|
||||
@@ -4,7 +4,6 @@ api.set_default_cbi()
|
||||
local has_ss_rust = api.is_finded("sslocal")
|
||||
local has_singbox = api.finded_com("sing-box")
|
||||
local has_xray = api.finded_com("xray")
|
||||
local has_hysteria2 = api.finded_com("hysteria")
|
||||
local ss_type = {}
|
||||
local trojan_type = {}
|
||||
local vmess_type = {}
|
||||
@@ -33,10 +32,6 @@ if has_xray then
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
end
|
||||
if has_hysteria2 then
|
||||
local s = "hysteria2"
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
|
||||
m = Map()
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ m:appendTemplate("/cbi/nodes_listvalue_com")
|
||||
local has_ss_rust = api.is_finded("sslocal")
|
||||
local has_singbox = api.finded_com("sing-box")
|
||||
local has_xray = api.finded_com("xray")
|
||||
local has_hysteria2 = api.finded_com("hysteria")
|
||||
local ss_type = {}
|
||||
local trojan_type = {}
|
||||
local vmess_type = {}
|
||||
@@ -46,10 +45,6 @@ if has_xray then
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
end
|
||||
if has_hysteria2 then
|
||||
local s = "hysteria2"
|
||||
table.insert(hysteria2_type, s)
|
||||
end
|
||||
local nodes_table = {}
|
||||
for k, e in ipairs(api.get_valid_nodes()) do
|
||||
if e.node_type == "normal" then
|
||||
|
||||
@@ -72,8 +72,7 @@ s = m:section(NamedSection, "@global_forwarding[0]", "global_forwarding", transl
|
||||
|
||||
---- TCP No Redir Ports
|
||||
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
|
||||
o.default = "disable"
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("", translate("No patterns are used"))
|
||||
o:value("1:65535", translate("All"))
|
||||
o.validate = port_validate
|
||||
|
||||
@@ -82,23 +81,22 @@ o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
|
||||
"<font color='red'>" ..
|
||||
translate("Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") ..
|
||||
"</font>")
|
||||
o.default = "disable"
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("", translate("No patterns are used"))
|
||||
o:value("1:65535", translate("All"))
|
||||
o.validate = port_validate
|
||||
|
||||
---- TCP Redir Ports
|
||||
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
|
||||
o.default = "22,25,53,80,143,443,465,587,853,873,993,995,5222,8080,8443,9418"
|
||||
o:value("1:65535", translate("All"))
|
||||
o:value("22,25,53,80,143,443,465,587,853,873,993,995,5222,8080,8443,9418", translate("Common Use"))
|
||||
o:value("80,443", translate("Only Web"))
|
||||
o.default = o.keylist[1]
|
||||
o.validate = port_validate
|
||||
|
||||
---- UDP Redir Ports
|
||||
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
|
||||
o.default = "1:65535"
|
||||
o:value("1:65535", translate("All"))
|
||||
o.default = o.keylist[1]
|
||||
o.validate = port_validate
|
||||
|
||||
o = s:option(DummyValue, "tips", " ")
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
if not api.finded_com("hysteria") then
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ Hysteria2 ]]
|
||||
local m, s1 = ...
|
||||
local type_name = "Hysteria2"
|
||||
|
||||
s1.fields["type"]:value(type_name, "Hysteria2")
|
||||
|
||||
if s1.val["type"] ~= type_name then
|
||||
return
|
||||
end
|
||||
|
||||
local s = NamedSection(m, arg[1], "server")
|
||||
s.type_name = type_name
|
||||
s.option_prefix = "hysteria2_"
|
||||
|
||||
o = s:option(Value, "address", translate("Address (Support Domain Name)"))
|
||||
o:depends({ realms = false })
|
||||
|
||||
o = s:option(Value, "port", translate("Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ realms = false })
|
||||
|
||||
o = s:option(Value, "hop", translate("Port hopping range"))
|
||||
o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).")
|
||||
o:depends({ realms = false })
|
||||
|
||||
o = s:option(Value, "hop_interval", translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5."))
|
||||
o.datatype = "or(uinteger,portrange)"
|
||||
o.placeholder = "30"
|
||||
o.default = "30"
|
||||
o:depends({ realms = false })
|
||||
|
||||
o = s:option(Flag, "realms", translate("Realms"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Value, "realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
|
||||
o:depends({ realms = "1" })
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value)
|
||||
local realm = api.parse_realm_uri(value)
|
||||
if realm then return value end
|
||||
return nil, translate("Invalid Realm URL.")
|
||||
end
|
||||
|
||||
o = s:option(DynamicList, "realm_stun", translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o:depends({ realms = "1" })
|
||||
|
||||
o = s:option(Value, "auth_password", translate("Auth Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(ListValue, "obfs_type", translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:value("gecko")
|
||||
|
||||
o = s:option(Value, "obfs_password", translate("Obfs Password"))
|
||||
o:depends({ obfs_type = "salamander" })
|
||||
o:depends({ obfs_type = "gecko" })
|
||||
|
||||
o = s:option(Value, "obfs_MinPacketSize", translate("Gecko Packet Size (min)"))
|
||||
o.datatype = "uinteger"
|
||||
o.placeholder = "512"
|
||||
o.default = "512"
|
||||
o:depends({ obfs_type = "gecko" })
|
||||
|
||||
o = s:option(Value, "obfs_MaxPacketSize", translate("Gecko Packet Size (max)"))
|
||||
o.datatype = "uinteger"
|
||||
o.placeholder = "1200"
|
||||
o.default = "1200"
|
||||
o:depends({ obfs_type = "gecko" })
|
||||
|
||||
o = s:option(Flag, "fast_open", translate("Fast Open"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Value, "tls_serverName", translate("Domain"))
|
||||
|
||||
o = s:option(Flag, "tls_allowInsecure", translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Value, "tls_pinSHA256", translate("PinSHA256"),translate("Certificate fingerprint"))
|
||||
|
||||
o = s:option(Value, "up_mbps", translate("Max upload Mbps"))
|
||||
|
||||
o = s:option(Value, "down_mbps", translate("Max download Mbps"))
|
||||
|
||||
o = s:option(Value, "recv_window", translate("QUIC stream receive window"))
|
||||
|
||||
o = s:option(Value, "recv_window_conn", translate("QUIC connection receive window"))
|
||||
|
||||
o = s:option(Value, "idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)")
|
||||
o.datatype = "range(4,120)"
|
||||
|
||||
o = s:option(Value, "keep_alive_period", translate("QUIC KeepAlive interval"), translate("Units:seconds") .. " (2~60)")
|
||||
o.datatype = "range(2,60)"
|
||||
|
||||
o = s:option(Flag, "disable_mtu_discovery", translate("Disable MTU detection"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Flag, "lazy_start", translate("Lazy Start"))
|
||||
o.default = "0"
|
||||
|
||||
api.luci_types(s1, s)
|
||||
@@ -455,9 +455,16 @@ if singbox_tags:find("with_wireguard") then
|
||||
o:depends({ protocol = "wireguard" })
|
||||
end
|
||||
|
||||
o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false, is_endpoint = "" })
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "accept_lan", translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
|
||||
o.default = "0"
|
||||
|
||||
@@ -473,10 +473,17 @@ o = s:option(DummyValue, "gen_wireguard_key")
|
||||
o.template = m:template_path("/server/gen_wireguard_key")
|
||||
o:depends({ protocol = "wireguard" })
|
||||
|
||||
o = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "accept_lan", translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
@@ -72,6 +72,17 @@ o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "log", translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
@@ -103,6 +103,17 @@ o = s:option(Flag, "udp_forward", translate("UDP Forward"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "firewall_allow", translate("Firewall Allow"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "firewall_allow_src", translate("Source zone"))
|
||||
o.nocreate = true
|
||||
o.allowany = true
|
||||
o.default = "wan"
|
||||
o.template = "cbi/firewall_zonelist"
|
||||
o:depends({ custom = false, firewall_allow = true })
|
||||
|
||||
o = s:option(Flag, "log", translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
if not api.finded_com("hysteria") then
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ Hysteria2 ]]
|
||||
local m, s1 = ...
|
||||
local type_name = "Hysteria2"
|
||||
|
||||
s1.fields["type"]:value(type_name, "Hysteria2")
|
||||
|
||||
if not s1.val["type"] then
|
||||
s1.val["type"] = type_name
|
||||
end
|
||||
|
||||
if s1.val["type"] and s1.val["type"] ~= type_name then
|
||||
return
|
||||
end
|
||||
|
||||
local s = NamedSection(m, arg[1], "server")
|
||||
s.type_name = type_name
|
||||
s.option_prefix = "hysteria2_"
|
||||
|
||||
o = s:option(Flag, "custom", translate("Use Custom Config"))
|
||||
|
||||
o = s:option(TextValue, "custom_config", translate("Custom Config"))
|
||||
o.rows = 10
|
||||
o.wrap = "off"
|
||||
o:depends({ custom = true })
|
||||
o.datatype = "json"
|
||||
local o_validate = o.validate
|
||||
o.validate = function(self, value)
|
||||
local v = o_validate(self, value)
|
||||
if v then return v end
|
||||
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
|
||||
end
|
||||
o.custom_cfgvalue = function(self, section, value)
|
||||
local config_str = m:get(section, "config_str")
|
||||
if config_str then
|
||||
return api.base64Decode(config_str)
|
||||
end
|
||||
end
|
||||
o.custom_write = function(self, section, value)
|
||||
m:set(section, "config_str", api.base64Encode(value) or "")
|
||||
end
|
||||
|
||||
o = s:option(Value, "port", translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(DynamicList, "users", translate("User"))
|
||||
for i, v in ipairs(user_list) do
|
||||
o:value(v[".name"], v.username)
|
||||
end
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Flag, "realms", translate("Realms"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "realm_url", translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name")
|
||||
o:depends({ realms = true })
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value)
|
||||
local realm = api.parse_realm_uri(value)
|
||||
if realm then return value end
|
||||
return nil, translate("Invalid Realm URL.")
|
||||
end
|
||||
|
||||
o = s:option(DynamicList, "realm_stun", translate("Realm STUN"))
|
||||
o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" }
|
||||
o:depends({ realms = true })
|
||||
|
||||
o = s:option(ListValue, "obfs_type", translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:value("gecko")
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "obfs_password", translate("Obfs Password"))
|
||||
o:depends({ obfs_type = "salamander" })
|
||||
o:depends({ obfs_type = "gecko" })
|
||||
|
||||
o = s:option(Value, "obfs_MinPacketSize", translate("Gecko Packet Size (min)"))
|
||||
o.datatype = "uinteger"
|
||||
o.placeholder = "512"
|
||||
o.default = "512"
|
||||
o:depends({ obfs_type = "gecko" })
|
||||
|
||||
o = s:option(Value, "obfs_MaxPacketSize", translate("Gecko Packet Size (max)"))
|
||||
o.datatype = "uinteger"
|
||||
o.placeholder = "1200"
|
||||
o.default = "1200"
|
||||
o:depends({ obfs_type = "gecko" })
|
||||
|
||||
o = s:option(Flag, "udp", translate("UDP"))
|
||||
o.default = "1"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "up_mbps", translate("Max upload Mbps"))
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Value, "down_mbps", translate("Max download Mbps"))
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Flag, "ignoreClientBandwidth", translate("ignoreClientBandwidth"))
|
||||
o.default = "0"
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
|
||||
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not api.fs.access(value) then
|
||||
return nil, translate("Can't find this file!")
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
|
||||
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not api.fs.access(value) then
|
||||
return nil, translate("Can't find this file!")
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
o:depends({ custom = false })
|
||||
|
||||
o = s:option(Flag, "log", translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
api.luci_types(s1, s)
|
||||
@@ -26,6 +26,7 @@ TMP_PATH = "/tmp/etc/" .. c_config
|
||||
CACHE_PATH = TMP_PATH .. "_tmp"
|
||||
S_TMP_PATH = "/tmp/etc/" .. s_config
|
||||
TMP_IFACE_PATH = TMP_PATH .. "/iface"
|
||||
TMP_ACL_PATH = TMP_PATH .. "/acl"
|
||||
|
||||
local lang = uci:get("luci", "main", "lang") or "auto"
|
||||
if lang == "auto" then
|
||||
@@ -201,9 +202,10 @@ function get_cache_var(key)
|
||||
return val
|
||||
end
|
||||
|
||||
function get_new_port()
|
||||
function get_new_port(p)
|
||||
if not p then p = "auto" end
|
||||
local cmd_format = ". /usr/share/passwall2/utils.sh ; echo -n $(get_new_port %s tcp,udp)"
|
||||
return tonumber(sys.exec(string.format(cmd_format, "auto")))
|
||||
return tonumber(sys.exec(string.format(cmd_format, p)))
|
||||
end
|
||||
|
||||
function exec_call(cmd)
|
||||
@@ -613,7 +615,7 @@ function get_valid_nodes()
|
||||
end
|
||||
end
|
||||
local port = e.port or e.hysteria_hop or e.hysteria2_hop
|
||||
local is_realm = (e.type == "Hysteria2" or e.protocol == 'hysteria2') and e.hysteria2_realms or nil
|
||||
local is_realm = e.protocol == 'hysteria2' and e.hysteria2_realms or nil
|
||||
if (port and e.address) or is_realm then
|
||||
local address = e.address
|
||||
if is_ip(address) or datatypes.hostname(address) or is_realm then
|
||||
@@ -739,7 +741,7 @@ function get_node_remarks(n)
|
||||
end
|
||||
type_name = type_name .. " " .. protocol
|
||||
end
|
||||
if (n.type == "Hysteria2" or n.protocol == 'hysteria2') and n.hysteria2_realms then
|
||||
if n.protocol == "hysteria2" and n.hysteria2_realms then
|
||||
type_name = type_name .. " Realm"
|
||||
end
|
||||
remarks = trim("%s:[%s]" % {type_name, n.remarks})
|
||||
|
||||
@@ -10,21 +10,6 @@ local function gh_pre_release_url(self)
|
||||
return "https://github.com/Openwrt-Passwall/openwrt-passwall-packages/releases/download/api-cache/" .. string.lower(self.name) .. "-pre-release-api.json"
|
||||
end
|
||||
|
||||
_M.hysteria = {
|
||||
name = "Hysteria",
|
||||
repo = "HyNetwork/hysteria",
|
||||
get_url = gh_release_url,
|
||||
cmd_version = "version | awk '/^Version:/ {print $2}'",
|
||||
remote_version_str_replace = "app/",
|
||||
zipped = false,
|
||||
default_path = "/usr/bin/hysteria",
|
||||
match_fmt_str = "linux%%-%s$",
|
||||
file_tree = {
|
||||
armv6 = "arm",
|
||||
armv7 = "arm"
|
||||
}
|
||||
}
|
||||
|
||||
_M["sing-box"] = {
|
||||
name = "Sing-Box",
|
||||
repo = "SagerNet/sing-box",
|
||||
|
||||
@@ -8,16 +8,10 @@ local jsonc = api.jsonc
|
||||
|
||||
local CONFIG = api.s_config
|
||||
local CONFIG_PATH = api.S_TMP_PATH
|
||||
local NFT_INCLUDE_FILE = CONFIG_PATH .. "/" .. CONFIG .. ".nft"
|
||||
local LOG_APP_FILE = "/tmp/log/" .. CONFIG .. ".log"
|
||||
local TMP_BIN_PATH = CONFIG_PATH .. "/bin"
|
||||
local require_dir = "luci.passwall2."
|
||||
|
||||
local ipt_bin = sys.exec("echo -n $(/usr/share/passwall2/iptables.sh get_ipt_bin)")
|
||||
local ip6t_bin = sys.exec("echo -n $(/usr/share/passwall2/iptables.sh get_ip6t_bin)")
|
||||
|
||||
local nft_flag = api.is_finded("fw4") and "1" or "0"
|
||||
|
||||
local function log(...)
|
||||
local f, err = io.open(LOG_APP_FILE, "a")
|
||||
if f and err == nil then
|
||||
@@ -31,18 +25,6 @@ local function cmd(cmd)
|
||||
sys.call(cmd)
|
||||
end
|
||||
|
||||
local function ipt(arg)
|
||||
if ipt_bin and #ipt_bin > 0 then
|
||||
cmd(ipt_bin .. " -w " .. arg)
|
||||
end
|
||||
end
|
||||
|
||||
local function ip6t(arg)
|
||||
if ip6t_bin and #ip6t_bin > 0 then
|
||||
cmd(ip6t_bin .. " -w " .. arg)
|
||||
end
|
||||
end
|
||||
|
||||
local function ln_run(s, d, command, output)
|
||||
if not output then
|
||||
output = "/dev/null"
|
||||
@@ -52,37 +34,6 @@ local function ln_run(s, d, command, output)
|
||||
return string.format("%s >%s 2>&1 &", d .. " " ..command, output)
|
||||
end
|
||||
|
||||
local function gen_include()
|
||||
cmd(string.format("echo '#!/bin/sh' > %s.include", CONFIG_PATH))
|
||||
local function extract_rules(n, a)
|
||||
local _ipt = ipt_bin
|
||||
if n == "6" then
|
||||
_ipt = ip6t_bin
|
||||
end
|
||||
local result = "*" .. a
|
||||
result = result .. "\n" .. sys.exec(_ipt .. '-save -t ' .. a .. ' | grep "PSW2-SERVER" | sed -e "s/^-A \\(INPUT\\)/-I \\1 1/"')
|
||||
result = result .. "COMMIT"
|
||||
return result
|
||||
end
|
||||
local f, err = io.open(CONFIG_PATH .. ".include", "a")
|
||||
if f and err == nil then
|
||||
if nft_flag == "0" then
|
||||
f:write(ipt_bin .. '-save -c | grep -v "PSW2-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n")
|
||||
f:write(ipt_bin .. '-restore -n <<-EOT' .. "\n")
|
||||
f:write(extract_rules("4", "filter") .. "\n")
|
||||
f:write("EOT" .. "\n")
|
||||
f:write(ip6t_bin .. '-save -c | grep -v "PSW2-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n")
|
||||
f:write(ip6t_bin .. '-restore -n <<-EOT' .. "\n")
|
||||
f:write(extract_rules("6", "filter") .. "\n")
|
||||
f:write("EOT" .. "\n")
|
||||
f:close()
|
||||
else
|
||||
f:write("nft -f " .. NFT_INCLUDE_FILE .. "\n")
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function start()
|
||||
local enabled = tonumber(api.uci_get_s("@global[0]", "enable") or 0)
|
||||
if enabled == nil or enabled == 0 then
|
||||
@@ -90,18 +41,7 @@ local function start()
|
||||
end
|
||||
cmd(string.format("mkdir -p %s %s", CONFIG_PATH, TMP_BIN_PATH))
|
||||
cmd(string.format("touch %s", LOG_APP_FILE))
|
||||
if nft_flag == "0" then
|
||||
ipt("-N PSW2-SERVER")
|
||||
ipt("-I INPUT -j PSW2-SERVER")
|
||||
ip6t("-N PSW2-SERVER")
|
||||
ip6t("-I INPUT -j PSW2-SERVER")
|
||||
else
|
||||
nft_file, err = io.open(NFT_INCLUDE_FILE, "w")
|
||||
nft_file:write('#!/usr/sbin/nft -f\n')
|
||||
nft_file:write('add chain inet fw4 PSW2-SERVER\n')
|
||||
nft_file:write('flush chain inet fw4 PSW2-SERVER\n')
|
||||
nft_file:write('insert rule inet fw4 input position 0 jump PSW2-SERVER comment "PSW2-SERVER"\n')
|
||||
end
|
||||
local firewall_num = 0
|
||||
api.uci_foreach_s("server", function(server)
|
||||
local id = server[".name"]
|
||||
local enable = server.enable
|
||||
@@ -169,13 +109,6 @@ local function start()
|
||||
config = require(require_dir .. "util_sing-box").gen_config_server(server)
|
||||
end
|
||||
bin = ln_run(api.get_app_path("sing-box"), "sing-box", "run -c " .. config_file, log_path)
|
||||
elseif type == "Hysteria2" then
|
||||
if server.custom == "1" and server.config_str then
|
||||
config = jsonc.parse(api.base64Decode(server.config_str))
|
||||
else
|
||||
config = require(require_dir .. "util_hysteria2").gen_config_server(server)
|
||||
end
|
||||
bin = ln_run(api.get_app_path("hysteria"), "hysteria", "-c " .. config_file .. " server", log_path)
|
||||
end
|
||||
|
||||
if next(config) then
|
||||
@@ -191,48 +124,38 @@ local function start()
|
||||
cmd(bin)
|
||||
end
|
||||
|
||||
local bind_local = server.bind_local or 0
|
||||
if bind_local and tonumber(bind_local) ~= 1 and port then
|
||||
if nft_flag == "0" then
|
||||
ipt(string.format('-A PSW2-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
|
||||
ip6t(string.format('-A PSW2-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
|
||||
if udp_forward == 1 then
|
||||
ipt(string.format('-A PSW2-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
|
||||
ip6t(string.format('-A PSW2-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
|
||||
end
|
||||
else
|
||||
nft_file:write(string.format('add rule inet fw4 PSW2-SERVER meta l4proto tcp tcp dport {%s} counter accept comment "%s"\n', port, remarks))
|
||||
if udp_forward == 1 then
|
||||
nft_file:write(string.format('add rule inet fw4 PSW2-SERVER meta l4proto udp udp dport {%s} counter accept comment "%s"\n', port, remarks))
|
||||
end
|
||||
end
|
||||
local firewall_allow = server.firewall_allow
|
||||
if firewall_allow == "1" then
|
||||
firewall_num = firewall_num + 1
|
||||
local uid = CONFIG .. "_" .. id
|
||||
uci:section("firewall", "rule", uid)
|
||||
uci:set("firewall", uid, "name", uid)
|
||||
uci:set("firewall", uid, "src", server.firewall_allow_src or "wan")
|
||||
uci:set("firewall", uid, "dest_port", port)
|
||||
uci:set("firewall", uid, "target", "ACCEPT")
|
||||
end
|
||||
end
|
||||
end)
|
||||
if nft_flag == "1" then
|
||||
nft_file:write("add rule inet fw4 PSW2-SERVER return\n")
|
||||
nft_file:close()
|
||||
cmd("nft -f " .. NFT_INCLUDE_FILE)
|
||||
if firewall_num > 0 then
|
||||
api.uci_save(uci, "firewall", true, true)
|
||||
end
|
||||
gen_include()
|
||||
end
|
||||
|
||||
local function stop()
|
||||
cmd(string.format("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/' | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1", CONFIG_PATH))
|
||||
if nft_flag == "0" then
|
||||
ipt("-D INPUT -j PSW2-SERVER 2>/dev/null")
|
||||
ipt("-F PSW2-SERVER 2>/dev/null")
|
||||
ipt("-X PSW2-SERVER 2>/dev/null")
|
||||
ip6t("-D INPUT -j PSW2-SERVER 2>/dev/null")
|
||||
ip6t("-F PSW2-SERVER 2>/dev/null")
|
||||
ip6t("-X PSW2-SERVER 2>/dev/null")
|
||||
else
|
||||
local nft_cmd = "handles=$(nft -a list chain inet fw4 input | grep -E \"PSW2-SERVER\" | awk -F '# handle ' '{print$2}')\n for handle in $handles; do\n nft delete rule inet fw4 input handle ${handle} 2>/dev/null\n done"
|
||||
cmd(nft_cmd)
|
||||
cmd("nft flush chain inet fw4 PSW2-SERVER 2>/dev/null")
|
||||
cmd("nft delete chain inet fw4 PSW2-SERVER 2>/dev/null")
|
||||
if true then
|
||||
local num = 0
|
||||
uci:foreach("firewall", "rule", function(rule)
|
||||
if rule[".name"]:find(CONFIG) == 1 then
|
||||
num = num + 1
|
||||
uci:delete("firewall", rule[".name"])
|
||||
end
|
||||
end)
|
||||
if num > 0 then
|
||||
api.uci_save(uci, "firewall", true, true)
|
||||
end
|
||||
end
|
||||
cmd(string.format("rm -rf %s %s %s", CONFIG_PATH, LOG_APP_FILE, CONFIG_PATH .. ".include"))
|
||||
cmd(string.format("rm -rf %s %s", CONFIG_PATH, LOG_APP_FILE))
|
||||
end
|
||||
|
||||
if action then
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
module("luci.passwall2.util_hysteria2", package.seeall)
|
||||
local api = require "luci.passwall2.api"
|
||||
local jsonc = api.jsonc
|
||||
|
||||
function gen_config_server(node)
|
||||
local users = nil
|
||||
if node.users and #node.users > 0 then
|
||||
users = {}
|
||||
for i, v in ipairs(node.users) do
|
||||
local user = api.uci_get_s(v) or {}
|
||||
if user[".type"] == "user" then
|
||||
users[user.username] = user.password
|
||||
end
|
||||
end
|
||||
if not next(users) then
|
||||
users = nil
|
||||
end
|
||||
end
|
||||
local config = {
|
||||
listen = (function()
|
||||
if node.realms and node.realm_url then
|
||||
local url = node.realm_url:gsub("/+$", "")
|
||||
if node.port then
|
||||
url = url .. (url:find("?") and "&lport=" or "?lport=") .. node.port
|
||||
end
|
||||
return url
|
||||
end
|
||||
return ":" .. (node.port or "0")
|
||||
end)(),
|
||||
tls = {
|
||||
cert = node.tls_certificateFile,
|
||||
key = node.tls_keyFile,
|
||||
},
|
||||
obfs = (node.obfs_type and node.obfs_password) and {
|
||||
type = node.obfs_type,
|
||||
[node.obfs_type] = {
|
||||
password = node.obfs_password
|
||||
}
|
||||
} or nil,
|
||||
auth = users and {
|
||||
type = "userpass",
|
||||
userpass = users
|
||||
} or nil,
|
||||
bandwidth = (node.up_mbps or node.down_mbps) and {
|
||||
up = node.up_mbps and node.up_mbps .. " mbps" or nil,
|
||||
down = node.down_mbps and node.down_mbps .. " mbps" or nil
|
||||
} or nil,
|
||||
ignoreClientBandwidth = (node.ignoreClientBandwidth == "1") and true or false,
|
||||
disableUDP = (node.udp == "0") and true or false,
|
||||
realm = (node.realms and node.realm_stun) and {
|
||||
stunServers = node.realm_stun
|
||||
} or nil
|
||||
}
|
||||
|
||||
if config.obfs and config.obfs.gecko then
|
||||
local min = tonumber(node.obfs_MinPacketSize) or 512
|
||||
local max = tonumber(node.obfs_MaxPacketSize) or 1200
|
||||
if min <= 0 or min > max or max > 2048 then
|
||||
min = 512
|
||||
max = 1200
|
||||
end
|
||||
config.obfs.gecko.minPacketSize = min
|
||||
config.obfs.gecko.maxPacketSize = max
|
||||
end
|
||||
|
||||
return config
|
||||
end
|
||||
|
||||
function gen_config(var)
|
||||
local node_id = var["node"]
|
||||
if not node_id then
|
||||
print("node Cannot be empty!")
|
||||
return
|
||||
end
|
||||
local node = api.uci_get_c(node_id)
|
||||
local local_socks_address = var["local_socks_address"] or "0.0.0.0"
|
||||
local local_socks_port = var["local_socks_port"]
|
||||
local local_socks_username = var["local_socks_username"]
|
||||
local local_socks_password = var["local_socks_password"]
|
||||
local local_http_address = var["local_http_address"] or "0.0.0.0"
|
||||
local local_http_port = var["local_http_port"]
|
||||
local local_http_username = var["local_http_username"]
|
||||
local local_http_password = var["local_http_password"]
|
||||
local server_host = var["server_host"] or (node.address or ""):lower()
|
||||
local server_port = var["server_port"] or node.port
|
||||
|
||||
if api.is_ipv6(server_host) then
|
||||
server_host = api.get_ipv6_full(server_host)
|
||||
end
|
||||
|
||||
local port_hop = ((server_port or "") .. "," .. (node.hysteria2_hop or "")):gsub("^[%s,]+", ""):gsub("[%s,]+$", ""):gsub(":", "-")
|
||||
local server = server_host .. ":" .. (port_hop ~= "" and port_hop or "443")
|
||||
|
||||
local config = {
|
||||
server = (function()
|
||||
if node.hysteria2_realms and node.hysteria2_realm_url then
|
||||
return node.hysteria2_realm_url:gsub("/+$", "")
|
||||
end
|
||||
return server
|
||||
end)(),
|
||||
realm = (node.hysteria2_realms and node.hysteria2_realm_stun) and {
|
||||
stunServers = node.hysteria2_realm_stun
|
||||
} or nil,
|
||||
transport = {
|
||||
type = "udp",
|
||||
udp = node.hysteria2_hop and (function()
|
||||
local udp = {}
|
||||
local t = node.hysteria2_hop_interval
|
||||
if not t then return nil end
|
||||
if t:find("-", 1, true) then
|
||||
local min, max = t:match("^(%d+)%-(%d+)$")
|
||||
min = tonumber(min)
|
||||
max = tonumber(max)
|
||||
if min and max then
|
||||
min = (min >= 5) and min or 5
|
||||
max = (max >= min) and max or min
|
||||
udp.minHopInterval = min .. "s"
|
||||
udp.maxHopInterval = max .. "s"
|
||||
return udp
|
||||
end
|
||||
end
|
||||
t = tonumber((t or "30"):match("^%d+"))
|
||||
t = (t and t >= 5) and t or 30
|
||||
udp.hopInterval = t .. "s"
|
||||
return udp
|
||||
end)() or nil
|
||||
},
|
||||
obfs = (node.hysteria2_obfs_type and node.hysteria2_obfs_password) and {
|
||||
type = node.hysteria2_obfs_type,
|
||||
[node.hysteria2_obfs_type] = {
|
||||
password = node.hysteria2_obfs_password
|
||||
}
|
||||
} or nil,
|
||||
auth = node.hysteria2_auth_password,
|
||||
tls = {
|
||||
sni = node.tls_serverName,
|
||||
insecure = (node.tls_allowInsecure == "1") and true or false,
|
||||
pinSHA256 = (node.tls_pinSHA256) and node.tls_pinSHA256 or nil,
|
||||
},
|
||||
quic = {
|
||||
initStreamReceiveWindow = (node.hysteria2_recv_window) and tonumber(node.hysteria2_recv_window) or nil,
|
||||
initConnReceiveWindow = (node.hysteria2_recv_window_conn) and tonumber(node.hysteria2_recv_window_conn) or nil,
|
||||
maxIdleTimeout = (function(t)
|
||||
t = tonumber(tostring(t or "30"):match("^%d+"))
|
||||
return (t and t >= 4 and t <= 120) and t .. "s" or "30s"
|
||||
end)(node.hysteria2_idle_timeout),
|
||||
keepAlivePeriod = (function(t)
|
||||
t = tonumber(tostring(t or "0"):match("^%d+"))
|
||||
return (t and t >= 2 and t <= 60) and t .. "s" or nil
|
||||
end)(node.hysteria2_keep_alive_period),
|
||||
disablePathMTUDiscovery = (node.hysteria2_disable_mtu_discovery) and true or false,
|
||||
},
|
||||
bandwidth = (node.hysteria2_up_mbps or node.hysteria2_down_mbps) and {
|
||||
up = node.hysteria2_up_mbps and node.hysteria2_up_mbps .. " mbps" or nil,
|
||||
down = node.hysteria2_down_mbps and node.hysteria2_down_mbps .. " mbps" or nil
|
||||
} or nil,
|
||||
fast_open = (node.fast_open == "1") and true or false,
|
||||
lazy = (node.hysteria2_lazy_start == "1") and true or false,
|
||||
socks5 = (local_socks_address and local_socks_port) and {
|
||||
listen = local_socks_address .. ":" .. local_socks_port,
|
||||
username = (local_socks_username and local_socks_password) and local_socks_username or nil,
|
||||
password = (local_socks_username and local_socks_password) and local_socks_password or nil,
|
||||
disableUDP = false,
|
||||
} or nil,
|
||||
http = (local_http_address and local_http_port) and {
|
||||
listen = local_http_address .. ":" .. local_http_port,
|
||||
username = (local_http_username and local_http_password) and local_http_username or nil,
|
||||
password = (local_http_username and local_http_password) and local_http_password or nil,
|
||||
} or nil
|
||||
}
|
||||
|
||||
if config.obfs and config.obfs.gecko then
|
||||
local min = tonumber(node.hysteria2_obfs_MinPacketSize) or 512
|
||||
local max = tonumber(node.hysteria2_obfs_MaxPacketSize) or 1200
|
||||
if min <= 0 or min > max or max > 2048 then
|
||||
min = 512
|
||||
max = 1200
|
||||
end
|
||||
config.obfs.gecko.minPacketSize = min
|
||||
config.obfs.gecko.maxPacketSize = max
|
||||
end
|
||||
|
||||
return jsonc.stringify(config, 1)
|
||||
end
|
||||
|
||||
_G.gen_config = gen_config
|
||||
|
||||
if arg[1] then
|
||||
local func =_G[arg[1]]
|
||||
if func then
|
||||
local var = nil
|
||||
if arg[2] then
|
||||
var = jsonc.parse(arg[2])
|
||||
end
|
||||
print(func(var))
|
||||
end
|
||||
end
|
||||
@@ -784,7 +784,7 @@ function gen_config_server(node)
|
||||
local inbound = {
|
||||
type = node.protocol,
|
||||
tag = "inbound",
|
||||
listen = (node.bind_local == "1") and "127.0.0.1" or "::",
|
||||
listen = "::",
|
||||
listen_port = tonumber(node.port),
|
||||
}
|
||||
|
||||
|
||||
@@ -675,7 +675,7 @@ function gen_config_server(node)
|
||||
},
|
||||
inbounds = {
|
||||
{
|
||||
listen = (node.bind_local == "1") and "127.0.0.1" or nil,
|
||||
listen = "::",
|
||||
port = tonumber(node.port),
|
||||
protocol = node.protocol,
|
||||
settings = settings,
|
||||
|
||||
@@ -133,7 +133,7 @@ local sid = "@global[0]"
|
||||
|
||||
const m = cbid.match(/\.node$/);
|
||||
if (m) {
|
||||
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_redir_log")%>?id=default&name=' + 'global' + '\', \'_blank\')"><%:Log%></a>';
|
||||
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_redir_log")%>?id=default' + '\', \'_blank\')"><%:Log%></a>';
|
||||
}
|
||||
|
||||
html = '<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">' + html + '</div>'
|
||||
|
||||
@@ -7,13 +7,12 @@ local map = self.map
|
||||
local has_ss_rust = api.is_finded("sslocal")
|
||||
local has_singbox = api.finded_com("sing-box")
|
||||
local has_xray = api.finded_com("xray")
|
||||
local has_hysteria2 = api.finded_com("hysteria")
|
||||
|
||||
local ss_type = api.get_core("ss_type", {{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local trojan_type = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local vmess_type = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local vless_type = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local hysteria2_type = api.get_core("hysteria2_type", {{has_hysteria2,"hysteria2"},{has_singbox,"sing-box"}, {has_xray,"xray"}})
|
||||
local hysteria2_type = api.get_core("hysteria2_type", {{has_singbox,"sing-box"}, {has_xray,"xray"}})
|
||||
|
||||
local current_node = map:get(section)
|
||||
-%>
|
||||
@@ -21,7 +20,6 @@ local current_node = map:get(section)
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
let has_singbox = "<%=has_singbox%>"
|
||||
let has_xray = "<%=has_xray%>"
|
||||
let has_hysteria2 = "<%=has_hysteria2%>"
|
||||
let ss_type = "<%=ss_type%>"
|
||||
let trojan_type = "<%=trojan_type%>"
|
||||
let vmess_type = "<%=vmess_type%>"
|
||||
@@ -585,7 +583,7 @@ local current_node = map:get(section)
|
||||
params = params.substring(1);
|
||||
}
|
||||
url += params;
|
||||
} else if ((v_type === "Hysteria2") || ((v_type === "sing-box" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "hysteria2")) {
|
||||
} else if (((v_type === "sing-box" || v_type === "Xray") && opt.get(dom_prefix + "protocol").value === "hysteria2")) {
|
||||
protocol = "hysteria2"
|
||||
var v_port = opt.get(dom_prefix + "port");
|
||||
var params = "";
|
||||
@@ -595,36 +593,20 @@ local current_node = map:get(section)
|
||||
params += opt.query("pcs", dom_prefix + "tls_pinSHA256");
|
||||
params += opt.query("vcn", dom_prefix + "tls_CertByName");
|
||||
|
||||
var v_password = null;
|
||||
|
||||
if (v_type === "Hysteria2") {
|
||||
v_password = opt.get("hysteria2_auth_password");
|
||||
var dom_obfs_type = opt.get("hysteria2_obfs_type");
|
||||
if (dom_obfs_type && dom_obfs_type.value != "") {
|
||||
params += opt.query("obfs", "hysteria2_obfs_type");
|
||||
params += opt.query("obfs-password", "hysteria2_obfs_password");
|
||||
if (dom_obfs_type.value === "gecko") {
|
||||
params += opt.query("minPacketSize", "hysteria2_obfs_MinPacketSize");
|
||||
params += opt.query("maxPacketSize", "hysteria2_obfs_MaxPacketSize");
|
||||
}
|
||||
}
|
||||
params += opt.query("mport", "hysteria2_hop");
|
||||
} else {
|
||||
v_password = opt.get(dom_prefix + "hysteria2_auth_password");
|
||||
var dom_obfs_type = opt.get(dom_prefix + "hysteria2_obfs_type");
|
||||
if (dom_obfs_type && dom_obfs_type.value != "") {
|
||||
params += opt.query("obfs", dom_prefix + "hysteria2_obfs_type");
|
||||
params += opt.query("obfs-password", dom_prefix + "hysteria2_obfs_password");
|
||||
if (dom_obfs_type.value === "gecko") {
|
||||
params += opt.query("minPacketSize", dom_prefix + "hysteria2_obfs_MinPacketSize");
|
||||
params += opt.query("maxPacketSize", dom_prefix + "hysteria2_obfs_MaxPacketSize");
|
||||
}
|
||||
}
|
||||
params += opt.query("mport", dom_prefix + "hysteria2_hop");
|
||||
if (opt.get(dom_prefix + "use_finalmask")?.checked) {
|
||||
params += opt.query("fm", dom_prefix + "finalmask");
|
||||
var v_password = opt.get(dom_prefix + "hysteria2_auth_password");
|
||||
var dom_obfs_type = opt.get(dom_prefix + "hysteria2_obfs_type");
|
||||
if (dom_obfs_type && dom_obfs_type.value != "") {
|
||||
params += opt.query("obfs", dom_prefix + "hysteria2_obfs_type");
|
||||
params += opt.query("obfs-password", dom_prefix + "hysteria2_obfs_password");
|
||||
if (dom_obfs_type.value === "gecko") {
|
||||
params += opt.query("minPacketSize", dom_prefix + "hysteria2_obfs_MinPacketSize");
|
||||
params += opt.query("maxPacketSize", dom_prefix + "hysteria2_obfs_MaxPacketSize");
|
||||
}
|
||||
}
|
||||
params += opt.query("mport", dom_prefix + "hysteria2_hop");
|
||||
if (opt.get(dom_prefix + "use_finalmask")?.checked) {
|
||||
params += opt.query("fm", dom_prefix + "finalmask");
|
||||
}
|
||||
params = params.replace(/^&/, "");
|
||||
url =
|
||||
_address + ":" +
|
||||
@@ -1640,19 +1622,6 @@ local current_node = map:get(section)
|
||||
opt.set(dom_prefix + 'hysteria2_hop', queryParam.mport || "");
|
||||
opt.set(dom_prefix + 'use_finalmask', !!queryParam.fm);
|
||||
opt.set(dom_prefix + 'finalmask', queryParam.fm || "");
|
||||
} else if (has_hysteria2) {
|
||||
opt.set('type', "Hysteria2");
|
||||
dom_prefix = "hysteria2_"
|
||||
opt.set(dom_prefix + 'auth_password', decodeURIComponent(password));
|
||||
if (queryParam["obfs-password"] || queryParam["obfs_password"]) {
|
||||
opt.set(dom_prefix + 'obfs_type', queryParam.obfs || "salamander");
|
||||
opt.set(dom_prefix + 'obfs_password', queryParam["obfs-password"] || queryParam["obfs_password"]);
|
||||
}
|
||||
if (queryParam.obfs === "gecko") {
|
||||
opt.set(dom_prefix + 'obfs_MinPacketSize', queryParam.minPacketSize || "512");
|
||||
opt.set(dom_prefix + 'obfs_MaxPacketSize', queryParam.maxPacketSize || "1200");
|
||||
}
|
||||
opt.set(dom_prefix + 'hop', queryParam.mport || "");
|
||||
}
|
||||
|
||||
opt.set(dom_prefix + 'address', unbracketIP(m.hostname));
|
||||
|
||||
@@ -495,7 +495,8 @@ table td, .table .td {
|
||||
ajax.abortAll();
|
||||
switch (action) {
|
||||
case "add":
|
||||
const dom = document.getElementsByClassName("cbi-tab")[0];
|
||||
const master = document.getElementById("node_list");
|
||||
const dom = master.getElementsByClassName("cbi-tab")[0];
|
||||
const current_group = dom ? (dom.getAttribute("group_name") || "default") : "default";
|
||||
window.location.href='<%=api.url("add_node")%>?redirect=1&group=' + current_group;
|
||||
break;
|
||||
|
||||
@@ -144,7 +144,8 @@ table td, .table .td {
|
||||
//<![CDATA[
|
||||
function toPage(action, cbi_id) {
|
||||
if (action == "add") {
|
||||
const dom = document.getElementsByClassName("cbi-tab")[0];
|
||||
const master = document.getElementById("shunt_rule_list");
|
||||
const dom = master.getElementsByClassName("cbi-tab")[0];
|
||||
const current_group = dom ? (dom.getAttribute("group_name") || "default") : "default";
|
||||
const add_name_val = document.getElementById("add_name_" + current_group).value;
|
||||
if (add_name_val.length > 1) {
|
||||
@@ -329,15 +330,19 @@ table td, .table .td {
|
||||
var shunt_rule_list = result
|
||||
|
||||
var group_shunt_rules = {}
|
||||
for (let i = 0; i < shunt_rule_list.length; i++) {
|
||||
let _shunt_rule = shunt_rule_list[i]
|
||||
if (!_shunt_rule.group || _shunt_rule.group === "") {
|
||||
_shunt_rule.group = "default"
|
||||
if (shunt_rule_list.length > 0) {
|
||||
for (let i = 0; i < shunt_rule_list.length; i++) {
|
||||
let _shunt_rule = shunt_rule_list[i]
|
||||
if (!_shunt_rule.group || _shunt_rule.group === "") {
|
||||
_shunt_rule.group = "default"
|
||||
}
|
||||
if (!group_shunt_rules[_shunt_rule.group]) {
|
||||
group_shunt_rules[_shunt_rule.group] = []
|
||||
}
|
||||
group_shunt_rules[_shunt_rule.group].push(_shunt_rule)
|
||||
}
|
||||
if (!group_shunt_rules[_shunt_rule.group]) {
|
||||
group_shunt_rules[_shunt_rule.group] = []
|
||||
}
|
||||
group_shunt_rules[_shunt_rule.group].push(_shunt_rule)
|
||||
} else {
|
||||
group_shunt_rules["default"] = [];
|
||||
}
|
||||
|
||||
var tab_ul_li_html = '';
|
||||
|
||||
@@ -1426,6 +1426,12 @@ msgstr "اتصال محلی (Bind Local)"
|
||||
msgid "When selected, it can only be accessed localhost."
|
||||
msgstr "در صورت انتخاب، فقط از طریق localhost قابل دسترسی است."
|
||||
|
||||
msgid "Firewall Allow"
|
||||
msgstr "فایروال مجاز است"
|
||||
|
||||
msgid "Source zone"
|
||||
msgstr "منطقه منبع"
|
||||
|
||||
msgid "Accept LAN Access"
|
||||
msgstr "پذیرش دسترسی شبکه داخلی (LAN)"
|
||||
|
||||
@@ -2147,8 +2153,8 @@ msgstr "پروکسی نکردن همه %s"
|
||||
msgid "Use the %s node [%s]"
|
||||
msgstr "استفاده از گره %s [%s]"
|
||||
|
||||
msgid "Using a node that is different from the global configuration, DNS has been forcibly redirected to a dedicated DNS server."
|
||||
msgstr "استفاده از گرهای متفاوت از پیکربندی سراسری، DNS به اجبار به سرور DNS اختصاصی هدایت شده است."
|
||||
msgid "DNS will redirected to the dedicated DNS server [%s]."
|
||||
msgstr "DNS به سرور DNS اختصاصی [%s] هدایت خواهد شد."
|
||||
|
||||
msgid "Add direct DNS to %s: %s"
|
||||
msgstr "افزودن DNS مستقیم به %s: %s"
|
||||
|
||||
@@ -1427,6 +1427,12 @@ msgstr "Только для localhost"
|
||||
msgid "When selected, it can only be accessed localhost."
|
||||
msgstr "Если включено, доступ возможен только с самого роутера."
|
||||
|
||||
msgid "Firewall Allow"
|
||||
msgstr "Брандмауэр разрешить"
|
||||
|
||||
msgid "Source zone"
|
||||
msgstr "Зона источника"
|
||||
|
||||
msgid "Accept LAN Access"
|
||||
msgstr "Разрешить доступ из LAN"
|
||||
|
||||
@@ -2148,8 +2154,8 @@ msgstr "не прокси все %s"
|
||||
msgid "Use the %s node [%s]"
|
||||
msgstr "Использовать %s сервер [%s]"
|
||||
|
||||
msgid "Using a node that is different from the global configuration, DNS has been forcibly redirected to a dedicated DNS server."
|
||||
msgstr "Используется сервер, отличный от глобальной настройки: DNS принудительно перенаправлен на выделенный DNS-сервер."
|
||||
msgid "DNS will redirected to the dedicated DNS server [%s]."
|
||||
msgstr "DNS будет перенаправлен на выделенный DNS-сервер [%s]."
|
||||
|
||||
msgid "Add direct DNS to %s: %s"
|
||||
msgstr "Добавление прямого DNS в %s: %s"
|
||||
|
||||
@@ -1418,6 +1418,12 @@ msgstr "本机监听"
|
||||
msgid "When selected, it can only be accessed localhost."
|
||||
msgstr "当勾选时,只能本机访问。"
|
||||
|
||||
msgid "Firewall Allow"
|
||||
msgstr "允许通过防火墙"
|
||||
|
||||
msgid "Source zone"
|
||||
msgstr "源区域"
|
||||
|
||||
msgid "Accept LAN Access"
|
||||
msgstr "接受局域网访问"
|
||||
|
||||
@@ -2133,8 +2139,8 @@ msgstr "不代理所有 %s"
|
||||
msgid "Use the %s node [%s]"
|
||||
msgstr "使用 %s 节点[%s]"
|
||||
|
||||
msgid "Using a node that is different from the global configuration, DNS has been forcibly redirected to a dedicated DNS server."
|
||||
msgstr "使用与全局配置不相同节点,已将DNS强制重定向到专用 DNS 服务器。"
|
||||
msgid "DNS will redirected to the dedicated DNS server [%s]."
|
||||
msgstr "DNS 将重定向到专用 DNS 服务器 [%s]。"
|
||||
|
||||
msgid "Add direct DNS to %s: %s"
|
||||
msgstr "追加直连 DNS 到 %s: %s"
|
||||
|
||||
@@ -1418,6 +1418,12 @@ msgstr "本機監聽"
|
||||
msgid "When selected, it can only be accessed localhost."
|
||||
msgstr "當勾選時,只能本機訪問。"
|
||||
|
||||
msgid "Firewall Allow"
|
||||
msgstr "允許通過防火墻"
|
||||
|
||||
msgid "Source zone"
|
||||
msgstr "源區域"
|
||||
|
||||
msgid "Accept LAN Access"
|
||||
msgstr "接受局域網訪問"
|
||||
|
||||
@@ -2139,8 +2145,8 @@ msgstr "不代理所有 %s"
|
||||
msgid "Use the %s node [%s]"
|
||||
msgstr "使用 %s 節點[%s]"
|
||||
|
||||
msgid "Using a node that is different from the global configuration, DNS has been forcibly redirected to a dedicated DNS server."
|
||||
msgstr "使用与全局配置不相同節點,已將DNS強制重定向到專用 DNS 服務器。"
|
||||
msgid "DNS will redirected to the dedicated DNS server [%s]."
|
||||
msgstr "DNS 將重定向到專用 DNS 服務器 [%s]。"
|
||||
|
||||
msgid "Add direct DNS to %s: %s"
|
||||
msgstr "追加直連 DNS 到 %s: %s"
|
||||
|
||||
@@ -38,45 +38,10 @@ else
|
||||
fi
|
||||
uci commit firewall
|
||||
|
||||
|
||||
[ ! -s "/etc/config/passwall2" ] && cp -f /usr/share/passwall2/0_default_config /etc/config/passwall2
|
||||
|
||||
chmod +x /usr/share/passwall2/*.sh
|
||||
|
||||
[ "$(uci -q get passwall2.@global_xray[0].sniffing)" == "1" ] && [ "$(uci -q get passwall2.@global_xray[0].route_only)" != "1" ] && uci -q set passwall2.@global_xray[0].sniffing_override_dest=1
|
||||
uci -q delete passwall2.@global_xray[0].sniffing
|
||||
uci -q delete passwall2.@global_xray[0].route_only
|
||||
frag_len=$(uci -q get passwall2.@global_xray[0].fragment_length)
|
||||
[ -n "$frag_len" ] && uci -q set passwall2.@global_xray[0].fragment_lengths="$frag_len" && uci -q delete passwall2.@global_xray[0].fragment_length
|
||||
frag_dly=$(uci -q get passwall2.@global_xray[0].fragment_delay)
|
||||
[ -n "$frag_dly" ] && uci -q set passwall2.@global_xray[0].fragment_delays="$frag_dly" && uci -q delete passwall2.@global_xray[0].fragment_delay
|
||||
|
||||
for sid in $(uci show passwall2 | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}'); do
|
||||
if [ -z "$(echo ${sid} | grep '^socks_')" ]; then
|
||||
new_id="socks_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5)"
|
||||
old_ref="Socks_${sid}"
|
||||
uci -q rename passwall2.${sid}="${new_id}"
|
||||
for item in $(uci show passwall2 | grep "='${old_ref}'\$" | cut -d '=' -sf 1); do
|
||||
uci -q set ${item}="${new_id}"
|
||||
done
|
||||
unset sid new_id old_ref item
|
||||
fi
|
||||
done
|
||||
for sid in $(uci show passwall2 | grep "@acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
|
||||
new_id="acl_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5)"
|
||||
uci -q rename passwall2.${sid}="${new_id}"
|
||||
unset sid new_id
|
||||
done
|
||||
for sid in $(uci show passwall2 | grep "@subscribe_list" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
|
||||
new_id="sub_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5)"
|
||||
uci -q rename passwall2.${sid}="${new_id}"
|
||||
unset sid new_id
|
||||
done
|
||||
|
||||
uci -q commit passwall2
|
||||
|
||||
sed -i "s#add_from#group#g" /etc/config/passwall2 2>/dev/null
|
||||
|
||||
rm -f /tmp/luci-indexcache /tmp/luci-indexcache.*
|
||||
rm -rf /tmp/luci-modulecache/
|
||||
killall -HUP rpcd 2>/dev/null
|
||||
|
||||
@@ -17,21 +17,6 @@ if [ -e "/etc/config/ucitrack" ]; then
|
||||
EOF
|
||||
fi
|
||||
|
||||
uci -q batch <<-EOF
|
||||
delete firewall.passwall2_server
|
||||
set firewall.passwall2_server=include
|
||||
set firewall.passwall2_server.type='script'
|
||||
set firewall.passwall2_server.path='/var/etc/passwall2_server.include'
|
||||
EOF
|
||||
|
||||
if [ -x "/sbin/fw3" ]; then
|
||||
uci -q set firewall.passwall2_server.reload='1'
|
||||
else
|
||||
uci -q delete firewall.passwall2_server.reload
|
||||
uci -q delete firewall.passwall2_server.fw4_compatible
|
||||
fi
|
||||
uci commit firewall
|
||||
|
||||
rm -f /tmp/luci-indexcache /tmp/luci-indexcache.*
|
||||
rm -rf /tmp/luci-modulecache/
|
||||
killall -HUP rpcd 2>/dev/null
|
||||
|
||||
@@ -25,8 +25,6 @@ config global_delay
|
||||
option start_delay '60'
|
||||
|
||||
config global_forwarding
|
||||
option tcp_no_redir_ports 'disable'
|
||||
option udp_no_redir_ports 'disable'
|
||||
option tcp_redir_ports '1:65535'
|
||||
option udp_redir_ports '1:65535'
|
||||
option accept_icmp '0'
|
||||
@@ -45,13 +43,12 @@ config global_rules
|
||||
option geosite_update '1'
|
||||
option geoip_update '1'
|
||||
option v2ray_location_asset '/usr/share/v2ray/'
|
||||
option geoip_url 'https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip.dat'
|
||||
option geoip_url 'https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat'
|
||||
option geosite_url 'https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat'
|
||||
|
||||
config global_app
|
||||
option geoview_file '/usr/bin/geoview'
|
||||
option xray_file '/usr/bin/xray'
|
||||
option hysteria_file '/usr/bin/hysteria'
|
||||
option sing_box_file '/usr/bin/sing-box'
|
||||
|
||||
config global_subscribe
|
||||
|
||||
@@ -7,17 +7,15 @@
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
. /usr/share/passwall2/utils.sh
|
||||
GLOBAL_ACL_PATH=${TMP_ACL_PATH}/default
|
||||
LUA_UTIL_PATH=/usr/lib/lua/luci/passwall2
|
||||
UTIL_SINGBOX=$LUA_UTIL_PATH/util_sing-box.lua
|
||||
UTIL_SS=$LUA_UTIL_PATH/util_shadowsocks.lua
|
||||
UTIL_XRAY=$LUA_UTIL_PATH/util_xray.lua
|
||||
UTIL_HYSTERIA2=$LUA_UTIL_PATH/util_hysteria2.lua
|
||||
SINGBOX_BIN=$(first_type $(config_t_get global_app sing_box_file) sing-box)
|
||||
XRAY_BIN=$(first_type $(config_t_get global_app xray_file) xray)
|
||||
SINGBOX_BIN=$(first_type $(config_n_get @global_app[0] sing_box_file) sing-box)
|
||||
XRAY_BIN=$(first_type $(config_n_get @global_app[0] xray_file) xray)
|
||||
|
||||
check_run_environment() {
|
||||
local prefer_nft=$(config_t_get global_forwarding prefer_nft 1)
|
||||
local prefer_nft=$(config_n_get @global_forwarding[0] prefer_nft 1)
|
||||
local dnsmasq_info=$(dnsmasq -v 2>/dev/null)
|
||||
local dnsmasq_ver=$(echo "$dnsmasq_info" | sed -n '1s/.*version \([0-9.]*\).*/\1/p')
|
||||
# local dnsmasq_opts=$(echo "$dnsmasq_info" | grep -i "Compile time options")
|
||||
@@ -70,13 +68,13 @@ check_run_environment() {
|
||||
}
|
||||
|
||||
run_xray() {
|
||||
local flag node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password
|
||||
local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password
|
||||
local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache
|
||||
local loglevel log_file config_file
|
||||
eval_set_val $@
|
||||
node_protocol=$(config_n_get $node protocol)
|
||||
[ -n "$log_file" ] || local log_file="/dev/null"
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_t_get global loglevel "warning")
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_n_get @global[0] loglevel "warning")
|
||||
|
||||
json_init
|
||||
json_add_string "loglevel" "${loglevel}"
|
||||
@@ -106,9 +104,8 @@ run_xray() {
|
||||
[ -n "$dns_cache" ] && json_add_string "dns_cache" "${dns_cache}"
|
||||
[ "${node_protocol}" = "_shunt" ] && local write_ipset_direct=$(config_n_get $node write_ipset_direct 0)
|
||||
[ "${write_ipset_direct}" = "1" ] && {
|
||||
direct_dnsmasq_listen_port=$(get_new_port $(expr $dns_listen_port + 1) udp)
|
||||
local direct_ipset_conf=${GLOBAL_ACL_PATH}/dns_${flag}_direct.conf
|
||||
[ -n "$(echo ${flag} | grep '^acl')" ] && direct_ipset_conf=${TMP_ACL_PATH}/${sid}/dns_${flag}_direct.conf
|
||||
direct_dnsmasq_listen_port=$(get_new_port auto)
|
||||
local direct_ipset_conf=${TMP_ACL_PATH}/dns_${flag}_direct.conf
|
||||
if [ "${nftflag}" = "1" ]; then
|
||||
local direct_nftset4="psw2_${node}_white"
|
||||
local direct_nftset6="psw2_${node}_white6"
|
||||
@@ -178,7 +175,7 @@ run_xray() {
|
||||
[ -n "${redir_port}" ] && {
|
||||
json_add_string "redir_port" "${redir_port}"
|
||||
set_cache_var "node_${node}_redir_port" "${redir_port}"
|
||||
[ -n "${tcp_proxy_way}" ] && json_add_string "tcp_proxy_way" "${tcp_proxy_way}"
|
||||
json_add_string "tcp_proxy_way" "${TCP_PROXY_WAY}"
|
||||
}
|
||||
|
||||
json_add_string "node" "${node}"
|
||||
@@ -199,7 +196,7 @@ run_xray() {
|
||||
}
|
||||
|
||||
run_singbox() {
|
||||
local flag node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password
|
||||
local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password
|
||||
local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy remote_rewrite_ttl dns_cache
|
||||
local loglevel log_file config_file
|
||||
eval_set_val $@
|
||||
@@ -207,7 +204,7 @@ run_singbox() {
|
||||
[ -z "$type" ] && return 1
|
||||
node_protocol=$(config_n_get $node protocol)
|
||||
[ -n "$log_file" ] || local log_file="/dev/null"
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_t_get global loglevel "warn")
|
||||
[ -z "$loglevel" ] && local loglevel=$(config_n_get @global[0] loglevel "warn")
|
||||
local singbox_tag=$($SINGBOX_BIN version | grep 'Tags:' | awk '{print $2}')
|
||||
|
||||
json_init
|
||||
@@ -244,9 +241,8 @@ run_singbox() {
|
||||
[ -n "$dns_listen_port" ] && {
|
||||
[ "${node_protocol}" = "_shunt" ] && local write_ipset_direct=$(config_n_get $node write_ipset_direct 0)
|
||||
[ "${write_ipset_direct}" = "1" ] && {
|
||||
direct_dnsmasq_listen_port=$(get_new_port $(expr $dns_listen_port + 1) udp)
|
||||
local direct_ipset_conf=${GLOBAL_ACL_PATH}/dns_${flag}_direct.conf
|
||||
[ -n "$(echo ${flag} | grep '^acl')" ] && direct_ipset_conf=${TMP_ACL_PATH}/${sid}/dns_${flag}_direct.conf
|
||||
direct_dnsmasq_listen_port=$(get_new_port auto)
|
||||
local direct_ipset_conf=${TMP_ACL_PATH}/dns_${flag}_direct.conf
|
||||
if [ "${nftflag}" = "1" ]; then
|
||||
local direct_nftset4="psw2_${node}_white"
|
||||
local direct_nftset6="psw2_${node}_white6"
|
||||
@@ -325,7 +321,7 @@ run_singbox() {
|
||||
[ -n "${redir_port}" ] && {
|
||||
json_add_string "redir_port" "${redir_port}"
|
||||
set_cache_var "node_${node}_redir_port" "${redir_port}"
|
||||
[ -n "${tcp_proxy_way}" ] && json_add_string "tcp_proxy_way" "${tcp_proxy_way}"
|
||||
json_add_string "tcp_proxy_way" "${TCP_PROXY_WAY}"
|
||||
}
|
||||
|
||||
json_add_string "node" "${node}"
|
||||
@@ -411,7 +407,7 @@ run_socks() {
|
||||
json_add_null "server_port"
|
||||
}
|
||||
[ "${log_file}" != "/dev/null" ] && {
|
||||
local loglevel=$(config_t_get global loglevel "warn")
|
||||
local loglevel=$(config_n_get @global[0] loglevel "warn")
|
||||
json_add_string "log" "1"
|
||||
json_add_string "loglevel" "${loglevel}"
|
||||
json_add_string "logfile" "${log_file}"
|
||||
@@ -439,7 +435,7 @@ run_socks() {
|
||||
json_add_null "server_port"
|
||||
}
|
||||
[ "${log_file}" != "/dev/null" ] && {
|
||||
local loglevel=$(config_t_get global loglevel "warn")
|
||||
local loglevel=$(config_n_get @global[0] loglevel "warn")
|
||||
json_add_string "log" "1"
|
||||
json_add_string "loglevel" "${loglevel}"
|
||||
}
|
||||
@@ -478,19 +474,6 @@ run_socks() {
|
||||
lua $UTIL_SS gen_config "${_json_arg}" > $config_file
|
||||
[ -z "$no_run" ] && ln_run ${QUEUE_RUN} "$(first_type sslocal)" "sslocal" $log_file -c "$config_file" -v
|
||||
;;
|
||||
hysteria2)
|
||||
json_add_string "local_socks_address" "${bind}"
|
||||
json_add_string "local_socks_port" "${socks_port}"
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
json_add_string "local_http_address" "${bind}"
|
||||
json_add_string "local_http_port" "${http_port}"
|
||||
}
|
||||
local _json_arg="$(json_dump)"
|
||||
lua $UTIL_HYSTERIA2 gen_config "${_json_arg}" > $config_file
|
||||
[ -z "$no_run" ] && ln_run ${QUEUE_RUN} "$(first_type $(config_t_get global_app hysteria_file))" "hysteria" $log_file -c "$config_file" client
|
||||
;;
|
||||
esac
|
||||
|
||||
# http to socks
|
||||
@@ -561,146 +544,6 @@ socks_node_switch() {
|
||||
}
|
||||
}
|
||||
|
||||
run_global() {
|
||||
[ -z "$NODE" ] && return 1
|
||||
TYPE=$(echo $(config_n_get $NODE type) | tr 'A-Z' 'a-z')
|
||||
[ -z "$TYPE" ] && return 1
|
||||
|
||||
if [ $PROXY_IPV6 == "1" ]; then
|
||||
log_i18n 0 "To enable experimental IPv6 transparent proxy (TProxy), please ensure your node and type support IPv6!"
|
||||
fi
|
||||
|
||||
TUN_DNS_PORT=15353
|
||||
TUN_DNS="127.0.0.1#${TUN_DNS_PORT}"
|
||||
|
||||
V2RAY_ARGS="flag=global node=$NODE redir_port=$REDIR_PORT tcp_proxy_way=${TCP_PROXY_WAY}"
|
||||
V2RAY_ARGS="${V2RAY_ARGS} dns_listen_port=${TUN_DNS_PORT} direct_dns_query_strategy=${DIRECT_DNS_QUERY_STRATEGY} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY} dns_cache=${DNS_CACHE}"
|
||||
local dns_msg="DNS: ${TUN_DNS} ($(i18n "Direct DNS: %s" "${AUTO_DNS}")"
|
||||
|
||||
[ -n "$REMOTE_DNS_PROTOCOL" ] && {
|
||||
V2RAY_ARGS="${V2RAY_ARGS} remote_dns_protocol=${REMOTE_DNS_PROTOCOL} remote_dns_detour=${REMOTE_DNS_DETOUR}"
|
||||
case "$REMOTE_DNS_PROTOCOL" in
|
||||
udp|\
|
||||
quic)
|
||||
V2RAY_ARGS="${V2RAY_ARGS} remote_dns_udp_server=${REMOTE_DNS}"
|
||||
dns_msg="${dns_msg} $(i18n "Remote DNS: %s" "${REMOTE_DNS}")"
|
||||
;;
|
||||
tcp|\
|
||||
tls)
|
||||
V2RAY_ARGS="${V2RAY_ARGS} remote_dns_tcp_server=${REMOTE_DNS}"
|
||||
dns_msg="${dns_msg} $(i18n "Remote DNS: %s" "${REMOTE_DNS}")"
|
||||
;;
|
||||
doh|\
|
||||
http3)
|
||||
REMOTE_DNS_DOH=$(config_t_get global remote_dns_doh "https://1.1.1.1/dns-query")
|
||||
V2RAY_ARGS="${V2RAY_ARGS} remote_dns_doh=${REMOTE_DNS_DOH}"
|
||||
dns_msg="${dns_msg} $(i18n "Remote DNS: %s" "${REMOTE_DNS_DOH}")"
|
||||
;;
|
||||
esac
|
||||
[ "$REMOTE_FAKEDNS" = "1" ] && {
|
||||
V2RAY_ARGS="${V2RAY_ARGS} remote_fakedns=1"
|
||||
dns_msg="${dns_msg} + FakeDNS "
|
||||
}
|
||||
|
||||
local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip)
|
||||
[ -n "${_remote_dns_client_ip}" ] && V2RAY_ARGS="${V2RAY_ARGS} remote_dns_client_ip=${_remote_dns_client_ip}"
|
||||
V2RAY_ARGS="${V2RAY_ARGS} remote_rewrite_ttl=$(config_t_get global remote_rewrite_ttl)"
|
||||
}
|
||||
dns_msg="${dns_msg})"
|
||||
|
||||
V2RAY_CONFIG=${GLOBAL_ACL_PATH}/global.json
|
||||
V2RAY_LOG=${GLOBAL_ACL_PATH}/global.log
|
||||
[ "$(config_t_get global log_node 1)" != "1" ] && V2RAY_LOG="/dev/null"
|
||||
V2RAY_ARGS="${V2RAY_ARGS} log_file=${V2RAY_LOG} config_file=${V2RAY_CONFIG}"
|
||||
|
||||
node_socks_port=$(config_t_get global node_socks_port 1070)
|
||||
node_socks_bind_local=$(config_t_get global node_socks_bind_local 1)
|
||||
node_socks_bind="127.0.0.1"
|
||||
[ "${node_socks_bind_local}" != "1" ] && node_socks_bind="0.0.0.0"
|
||||
V2RAY_ARGS="${V2RAY_ARGS} socks_address=${node_socks_bind} socks_port=${node_socks_port}"
|
||||
set_cache_var "GLOBAL_SOCKS_server" "127.0.0.1:$node_socks_port"
|
||||
|
||||
node_http_port=$(config_t_get global node_http_port 0)
|
||||
[ "$node_http_port" != "0" ] && V2RAY_ARGS="${V2RAY_ARGS} http_port=${node_http_port}"
|
||||
|
||||
local run_func
|
||||
[ -n "${XRAY_BIN}" ] && run_func="run_xray"
|
||||
[ -n "${SINGBOX_BIN}" ] && run_func="run_singbox"
|
||||
if [ "${TYPE}" = "xray" ] && [ -n "${XRAY_BIN}" ]; then
|
||||
run_func="run_xray"
|
||||
elif [ "${TYPE}" = "sing-box" ] && [ -n "${SINGBOX_BIN}" ]; then
|
||||
run_func="run_singbox"
|
||||
fi
|
||||
|
||||
${run_func} ${V2RAY_ARGS}; local status=$?
|
||||
|
||||
if [ "$status" == 0 ]; then
|
||||
log 0 ${dns_msg}
|
||||
else
|
||||
log_i18n 0 "[%s] process %s error, skip this transparent proxy!" $(i18n "Global") "${V2RAY_CONFIG}"
|
||||
cat ${_error_log_file} >> ${LOG_FILE}
|
||||
unset _error_log_file
|
||||
ENABLED_DEFAULT_ACL=0
|
||||
return 1
|
||||
fi
|
||||
|
||||
set_cache_var "ACL_GLOBAL_node" "$NODE"
|
||||
set_cache_var "ACL_GLOBAL_redir_port" "$REDIR_PORT"
|
||||
}
|
||||
|
||||
run_global_dnsmasq() {
|
||||
[ -z "${ACL_GLOBAL_node}" ] && return
|
||||
local RUN_NEW_DNSMASQ=1
|
||||
RUN_NEW_DNSMASQ=${DNS_REDIRECT}
|
||||
DNSMASQ_DEFAULT_DNS="${AUTO_DNS}"
|
||||
DNSMASQ_LOCAL_DNS="${LOCAL_DNS:-${AUTO_DNS}}"
|
||||
DNSMASQ_TUN_DNS="${TUN_DNS}"
|
||||
if [ "${RUN_NEW_DNSMASQ}" == "0" ]; then
|
||||
#The old logic will be removed in the future.
|
||||
#Run a copy dnsmasq instance, DNS hijack that don't need a proxy devices.
|
||||
[ "1" = "0" ] && {
|
||||
DIRECT_DNSMASQ_PORT=$(get_new_port 11400)
|
||||
DIRECT_DNSMASQ_CONF=${GLOBAL_ACL_PATH}/direct_dnsmasq.conf
|
||||
DIRECT_DNSMASQ_CONF_PATH=${GLOBAL_ACL_PATH}/direct_dnsmasq.d
|
||||
mkdir -p ${DIRECT_DNSMASQ_CONF_PATH}
|
||||
json_init
|
||||
json_add_string "LISTEN_PORT" "${DIRECT_DNSMASQ_PORT}"
|
||||
json_add_string "DNSMASQ_CONF" "${DIRECT_DNSMASQ_CONF}"
|
||||
json_add_string "TMP_DNSMASQ_PATH" "${DIRECT_DNSMASQ_CONF_PATH}"
|
||||
lua $APP_PATH/helper_dnsmasq.lua copy_instance "$(json_dump)"
|
||||
ln_run 0 "$(first_type dnsmasq)" "dnsmasq_direct" "/dev/null" -C ${DIRECT_DNSMASQ_CONF} -x ${GLOBAL_ACL_PATH}/direct_dnsmasq.pid
|
||||
set_cache_var "DIRECT_DNSMASQ_PORT" "${DIRECT_DNSMASQ_PORT}"
|
||||
}
|
||||
|
||||
#Rewrite the default DNS service configuration
|
||||
#Modify the default dnsmasq service
|
||||
lua $APP_PATH/helper_dnsmasq.lua stretch
|
||||
json_init
|
||||
json_add_string "FLAG" "default"
|
||||
json_add_string "TMP_DNSMASQ_PATH" "${GLOBAL_DNSMASQ_CONF_PATH}"
|
||||
json_add_string "DNSMASQ_CONF_FILE" "${GLOBAL_DNSMASQ_CONF}"
|
||||
json_add_string "DEFAULT_DNS" "${DNSMASQ_DEFAULT_DNS}"
|
||||
json_add_string "LOCAL_DNS" "${DNSMASQ_LOCAL_DNS}"
|
||||
json_add_string "TUN_DNS" "${DNSMASQ_TUN_DNS}"
|
||||
json_add_string "NFTFLAG" "${nftflag:-0}"
|
||||
json_add_string "NO_LOGIC_LOG" "${NO_LOGIC_LOG:-0}"
|
||||
lua $APP_PATH/helper_dnsmasq.lua add_rule "$(json_dump)"
|
||||
uci -q add_list dhcp.@dnsmasq[0].addnmount=${GLOBAL_DNSMASQ_CONF_PATH}
|
||||
uci -q commit dhcp
|
||||
|
||||
json_init
|
||||
json_add_string "LOG" "1"
|
||||
lua $APP_PATH/helper_dnsmasq.lua logic_restart "$(json_dump)"
|
||||
else
|
||||
#Run a copy dnsmasq instance, DNS hijack for that need proxy devices.
|
||||
GLOBAL_DNSMASQ_PORT=$(get_new_port 11400)
|
||||
run_copy_dnsmasq flag="default" listen_port=$GLOBAL_DNSMASQ_PORT local_dns="${DNSMASQ_LOCAL_DNS}" tun_dns="${DNSMASQ_TUN_DNS}" default_dns="${DNSMASQ_DEFAULT_DNS}"
|
||||
DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT}
|
||||
#dhcp.leases to hosts
|
||||
$APP_PATH/lease2hosts.sh > /dev/null 2>&1 &
|
||||
fi
|
||||
}
|
||||
|
||||
start_socks() {
|
||||
[ "$SOCKS_ENABLED" = "1" ] && {
|
||||
local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
|
||||
@@ -746,7 +589,7 @@ clean_crontab() {
|
||||
|
||||
start_crontab() {
|
||||
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
|
||||
start_daemon=$(config_t_get global_delay start_daemon 0)
|
||||
start_daemon=$(config_n_get @global_delay[0] start_daemon 0)
|
||||
[ "$start_daemon" = "1" ] && { $APP_PATH/monitor.sh > /dev/null 2>&1 & }
|
||||
fi
|
||||
|
||||
@@ -763,8 +606,8 @@ start_crontab() {
|
||||
return
|
||||
}
|
||||
|
||||
stop_week_mode=$(config_t_get global_delay stop_week_mode)
|
||||
stop_time_mode=$(config_t_get global_delay stop_time_mode)
|
||||
stop_week_mode=$(config_n_get @global_delay[0] stop_week_mode)
|
||||
stop_time_mode=$(config_n_get @global_delay[0] stop_time_mode)
|
||||
if [ -n "$stop_week_mode" ]; then
|
||||
stop_time_hh=$(echo $stop_time_mode | awk -F ':' '{print $1}')
|
||||
stop_time_mm=$(echo $stop_time_mode | awk -F ':' '{print $2}')
|
||||
@@ -774,8 +617,8 @@ start_crontab() {
|
||||
log_i18n 0 "Scheduled tasks: Auto stop service."
|
||||
fi
|
||||
|
||||
start_week_mode=$(config_t_get global_delay start_week_mode)
|
||||
start_time_mode=$(config_t_get global_delay start_time_mode)
|
||||
start_week_mode=$(config_n_get @global_delay[0] start_week_mode)
|
||||
start_time_mode=$(config_n_get @global_delay[0] start_time_mode)
|
||||
if [ -n "$start_week_mode" ]; then
|
||||
start_time_hh=$(echo $start_time_mode | awk -F ':' '{print $1}')
|
||||
start_time_mm=$(echo $start_time_mode | awk -F ':' '{print $2}')
|
||||
@@ -785,8 +628,8 @@ start_crontab() {
|
||||
log_i18n 0 "Scheduled tasks: Auto start service."
|
||||
fi
|
||||
|
||||
restart_week_mode=$(config_t_get global_delay restart_week_mode)
|
||||
restart_time_mode=$(config_t_get global_delay restart_time_mode)
|
||||
restart_week_mode=$(config_n_get @global_delay[0] restart_week_mode)
|
||||
restart_time_mode=$(config_n_get @global_delay[0] restart_time_mode)
|
||||
if [ -n "$restart_week_mode" ]; then
|
||||
restart_time_hh=$(echo $restart_time_mode | awk -F ':' '{print $1}')
|
||||
restart_time_mm=$(echo $restart_time_mode | awk -F ':' '{print $2}')
|
||||
@@ -800,8 +643,8 @@ start_crontab() {
|
||||
log_i18n 0 "Scheduled tasks: Auto restart service."
|
||||
fi
|
||||
|
||||
rules_update_week_mode=$(config_t_get global_rules update_week_mode)
|
||||
rules_update_time_mode=$(config_t_get global_rules update_time_mode)
|
||||
rules_update_week_mode=$(config_n_get @global_rules[0] update_week_mode)
|
||||
rules_update_time_mode=$(config_n_get @global_rules[0] update_time_mode)
|
||||
if [ -n "$rules_update_week_mode" ]; then
|
||||
rules_update_time_hh=$(echo $rules_update_time_mode | awk -F ':' '{print $1}')
|
||||
rules_update_time_mm=$(echo $rules_update_time_mode | awk -F ':' '{print $2}')
|
||||
@@ -865,7 +708,7 @@ stop_crontab() {
|
||||
}
|
||||
|
||||
start_haproxy() {
|
||||
[ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return
|
||||
[ "$(config_n_get @global_haproxy[0] balancing_enable 0)" != "1" ] && return
|
||||
haproxy_path=$TMP_PATH/haproxy
|
||||
haproxy_conf="config.cfg"
|
||||
lua $APP_PATH/haproxy.lua -path ${haproxy_path} -conf ${haproxy_conf}
|
||||
@@ -875,8 +718,9 @@ start_haproxy() {
|
||||
run_copy_dnsmasq() {
|
||||
local flag listen_port local_dns tun_dns default_dns
|
||||
eval_set_val $@
|
||||
local dnsmasq_conf=$TMP_ACL_PATH/$flag/dnsmasq.conf
|
||||
local dnsmasq_conf_path=$TMP_ACL_PATH/$flag/dnsmasq.d
|
||||
local dnsmasq_conf="${TMP_ACL_PATH}/${flag}_dnsmasq.conf"
|
||||
local dnsmasq_conf_path="${TMP_ACL_PATH}/${flag}_dnsmasq.d"
|
||||
local dnsmasq_pid="${TMP_ACL_PATH}/${flag}_dnsmasq.pid"
|
||||
mkdir -p $dnsmasq_conf_path
|
||||
|
||||
json_init
|
||||
@@ -895,7 +739,7 @@ run_copy_dnsmasq() {
|
||||
json_add_string "NO_LOGIC_LOG" "${NO_LOGIC_LOG:-0}"
|
||||
lua $APP_PATH/helper_dnsmasq.lua add_rule "$(json_dump)"
|
||||
|
||||
ln_run 0 "$(first_type dnsmasq)" "dnsmasq_${flag}" "/dev/null" -C $dnsmasq_conf -x $TMP_ACL_PATH/$flag/dnsmasq.pid
|
||||
ln_run 0 "$(first_type dnsmasq)" "dnsmasq_${flag}" "/dev/null" -C ${dnsmasq_conf} -x ${dnsmasq_pid}
|
||||
set_cache_var "ACL_${flag}_dns_port" "${listen_port}"
|
||||
}
|
||||
|
||||
@@ -958,156 +802,75 @@ run_ipset_dnsmasq() {
|
||||
ln_run 0 "$(first_type dnsmasq)" "dnsmasq" "/dev/null" -C $config_file
|
||||
}
|
||||
|
||||
acl_app() {
|
||||
local items=$(uci show ${CONFIG} | grep "=acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1)
|
||||
if [ -z "$items" ]; then
|
||||
ENABLED_ACLS=0
|
||||
return
|
||||
else
|
||||
local has_enabled
|
||||
local index=0
|
||||
local sid
|
||||
local redir_port dns_port dnsmasq_port socks_port
|
||||
local ipt_tmp msg msg2
|
||||
redir_port=11200
|
||||
socks_port=11600
|
||||
dns_port=11300
|
||||
dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400}
|
||||
for sid in $items; do
|
||||
index=$(expr $index + 1)
|
||||
local enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy remote_rewrite_ttl log loglevel log_file
|
||||
local _ip _mac _iprange _ipset _ip_or_mac source_list config_file
|
||||
[ "$(config_n_get $sid enabled)" = "1" ] || continue
|
||||
has_enabled=1
|
||||
eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-)
|
||||
acl_node() {
|
||||
local run_func
|
||||
[ -n "${XRAY_BIN}" ] && run_func="run_xray"
|
||||
[ -n "${SINGBOX_BIN}" ] && run_func="run_singbox"
|
||||
local acl_node_num=0
|
||||
for nid in $(jsonfilter -s "${acl_json}" -e '$.node_order[*]'); do
|
||||
[ ! -f ${TMP_ACL_PATH}/acl_node_${nid} ] && continue
|
||||
acl_node_num=$(expr $acl_node_num + 1)
|
||||
local _var=$(cat ${TMP_ACL_PATH}/acl_node_${nid} 2>/dev/null)
|
||||
eval local ${_var}
|
||||
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
|
||||
[ -n "${type}" ] || continue
|
||||
if [ "${type}" = "xray" ] && [ -n "${XRAY_BIN}" ]; then
|
||||
run_func="run_xray"
|
||||
elif [ "${type}" = "sing-box" ] && [ -n "${SINGBOX_BIN}" ]; then
|
||||
run_func="run_singbox"
|
||||
fi
|
||||
${run_func} ${_var}
|
||||
local status=$?
|
||||
if [ "$status" != 0 ]; then
|
||||
log_i18n 2 "[%s] process %s error, skip this transparent proxy!" "${node}" "${config_file}"
|
||||
cat ${_error_log_file} >> ${LOG_FILE}
|
||||
unset _error_log_file
|
||||
continue
|
||||
fi
|
||||
if [ "${flag}" = "default" ]; then
|
||||
set_cache_var "GLOBAL_SOCKS_server" "127.0.0.1:$socks_port"
|
||||
set_cache_var "ACL_GLOBAL_node" "$node"
|
||||
local RUN_NEW_DNSMASQ=$(config_n_get @global[0] dns_redirect 1)
|
||||
local DNSMASQ_DEFAULT_DNS="${AUTO_DNS}"
|
||||
local DNSMASQ_LOCAL_DNS="${LOCAL_DNS:-${AUTO_DNS}}"
|
||||
local DNSMASQ_TUN_DNS="127.0.0.1#${dns_listen_port}"
|
||||
if [ "${RUN_NEW_DNSMASQ}" == "0" ]; then
|
||||
#Rewrite the default DNS service configuration
|
||||
#Modify the default dnsmasq service
|
||||
lua $APP_PATH/helper_dnsmasq.lua stretch
|
||||
json_init
|
||||
json_add_string "FLAG" "default"
|
||||
json_add_string "TMP_DNSMASQ_PATH" "${GLOBAL_DNSMASQ_CONF_PATH}"
|
||||
json_add_string "DNSMASQ_CONF_FILE" "${GLOBAL_DNSMASQ_CONF}"
|
||||
json_add_string "DEFAULT_DNS" "${DNSMASQ_DEFAULT_DNS}"
|
||||
json_add_string "LOCAL_DNS" "${DNSMASQ_LOCAL_DNS}"
|
||||
json_add_string "TUN_DNS" "${DNSMASQ_TUN_DNS}"
|
||||
json_add_string "NFTFLAG" "${nftflag:-0}"
|
||||
json_add_string "NO_LOGIC_LOG" "${NO_LOGIC_LOG:-0}"
|
||||
lua $APP_PATH/helper_dnsmasq.lua add_rule "$(json_dump)"
|
||||
uci -q add_list dhcp.@dnsmasq[0].addnmount=${GLOBAL_DNSMASQ_CONF_PATH}
|
||||
uci -q commit dhcp
|
||||
|
||||
if [ -n "${sources}" ]; then
|
||||
for s in $sources; do
|
||||
local s2
|
||||
is_iprange=$(lua_api "iprange(\"${s}\")")
|
||||
if [ "${is_iprange}" = "true" ]; then
|
||||
s2="iprange:${s}"
|
||||
elif [ -n "$(echo ${s} | grep '^ipset:')" ]; then
|
||||
s2="ipset:${s}"
|
||||
else
|
||||
_ip_or_mac=$(lua_api "ip_or_mac(\"${s}\")")
|
||||
if [ "${_ip_or_mac}" = "ip" ]; then
|
||||
s2="ip:${s}"
|
||||
elif [ "${_ip_or_mac}" = "mac" ]; then
|
||||
s2="mac:${s}"
|
||||
fi
|
||||
fi
|
||||
[ -n "${s2}" ] && source_list="${source_list}\n${s2}"
|
||||
unset s2
|
||||
done
|
||||
json_init
|
||||
json_add_string "LOG" "1"
|
||||
lua $APP_PATH/helper_dnsmasq.lua logic_restart "$(json_dump)"
|
||||
else
|
||||
source_list="any"
|
||||
#Run a copy dnsmasq instance, DNS hijack for that need proxy devices.
|
||||
dnsmasq_port=$(get_new_port auto)
|
||||
run_copy_dnsmasq flag="default" listen_port=${dnsmasq_port} local_dns="${DNSMASQ_LOCAL_DNS}" tun_dns="${DNSMASQ_TUN_DNS}" default_dns="${DNSMASQ_DEFAULT_DNS}"
|
||||
#dhcp.leases to hosts
|
||||
$APP_PATH/lease2hosts.sh > /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
local acl_path=${TMP_ACL_PATH}/$sid
|
||||
mkdir -p ${acl_path}
|
||||
[ -n "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > ${acl_path}/source_list
|
||||
|
||||
log=${log:-0}
|
||||
loglevel=${loglevel:-warn}
|
||||
log_file="/dev/null"
|
||||
[ "${log}" = "1" ] && log_file="${acl_path}/node.log"
|
||||
|
||||
node=${node:-default}
|
||||
tcp_no_redir_ports=${tcp_no_redir_ports:-default}
|
||||
udp_no_redir_ports=${udp_no_redir_ports:-default}
|
||||
[ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS
|
||||
[ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS
|
||||
if has_1_65535 "$tcp_no_redir_ports" && has_1_65535 "$udp_no_redir_ports"; then
|
||||
unset node
|
||||
fi
|
||||
|
||||
[ -n "$node" ] && {
|
||||
tcp_proxy_mode="global"
|
||||
udp_proxy_mode="global"
|
||||
direct_dns_query_strategy=${direct_dns_query_strategy:-UseIP}
|
||||
remote_dns_protocol=${remote_dns_protocol:-tcp}
|
||||
remote_dns=${remote_dns:-1.1.1.1}
|
||||
case "$remote_dns_protocol" in
|
||||
doh|\
|
||||
http3)
|
||||
remote_dns=${remote_dns_doh:-https://1.1.1.1/dns-query}
|
||||
;;
|
||||
esac
|
||||
remote_dns_detour=${remote_dns_detour:-remote}
|
||||
remote_fakedns=${remote_fakedns:-0}
|
||||
remote_dns_query_strategy=${remote_dns_query_strategy:-UseIPv4}
|
||||
|
||||
local GLOBAL_node=$(get_cache_var "ACL_GLOBAL_node")
|
||||
[ -n "${GLOBAL_node}" ] && GLOBAL_redir_port=$(get_cache_var "ACL_GLOBAL_redir_port")
|
||||
|
||||
if [ "$node" = "default" ]; then
|
||||
if [ -n "${GLOBAL_node}" ]; then
|
||||
set_cache_var "ACL_${sid}_node" "${GLOBAL_node}"
|
||||
set_cache_var "ACL_${sid}_redir_port" "${GLOBAL_redir_port}"
|
||||
set_cache_var "ACL_${sid}_dns_port" "${GLOBAL_DNSMASQ_PORT}"
|
||||
set_cache_var "ACL_${sid}_default" "1"
|
||||
else
|
||||
log 1 "$(i18n "Global nodes are not enabled, skip [%s]." "${remarks}")"
|
||||
fi
|
||||
else
|
||||
[ "$(config_get_type $node)" = "nodes" ] && {
|
||||
if [ -n "${GLOBAL_node}" ] && [ "$node" = "${GLOBAL_node}" ]; then
|
||||
set_cache_var "ACL_${sid}_node" "${GLOBAL_node}"
|
||||
set_cache_var "ACL_${sid}_redir_port" "${GLOBAL_redir_port}"
|
||||
set_cache_var "ACL_${sid}_dns_port" "${GLOBAL_DNSMASQ_PORT}"
|
||||
set_cache_var "ACL_${sid}_default" "1"
|
||||
else
|
||||
redir_port=$(get_new_port $(expr $redir_port + 1))
|
||||
socks_port=$(get_new_port $(expr $socks_port + 1))
|
||||
|
||||
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
|
||||
if [ -n "${type}" ]; then
|
||||
config_file=$TMP_ACL_PATH/${node}_TCP_UDP_DNS_${redir_port}.json
|
||||
dns_port=$(get_new_port $(expr $dns_port + 1))
|
||||
local acl_socks_port=$socks_port
|
||||
local run_func
|
||||
[ -n "${XRAY_BIN}" ] && run_func="run_xray"
|
||||
[ -n "${SINGBOX_BIN}" ] && run_func="run_singbox"
|
||||
if [ "${type}" = "xray" ] && [ -n "${XRAY_BIN}" ]; then
|
||||
run_func="run_xray"
|
||||
elif [ "${type}" = "sing-box" ] && [ -n "${SINGBOX_BIN}" ]; then
|
||||
run_func="run_singbox"
|
||||
fi
|
||||
${run_func} flag=acl_$sid node=$node redir_port=$redir_port tcp_proxy_way=${TCP_PROXY_WAY} \
|
||||
socks_address=127.0.0.1 socks_port=$acl_socks_port \
|
||||
dns_listen_port=${dns_port} \
|
||||
direct_dns_query_strategy=${direct_dns_query_strategy} \
|
||||
remote_dns_protocol=${remote_dns_protocol} remote_dns_tcp_server=${remote_dns} remote_dns_udp_server=${remote_dns} remote_dns_doh="${remote_dns}" \
|
||||
remote_dns_client_ip=${remote_dns_client_ip} remote_dns_detour=${remote_dns_detour} remote_dns_query_strategy=${remote_dns_query_strategy} \
|
||||
remote_fakedns=${remote_fakedns} remote_rewrite_ttl=${remote_rewrite_ttl} \
|
||||
config_file=${config_file} \
|
||||
log_file="${log_file}" loglevel="${loglevel}"
|
||||
local status=$?
|
||||
if [ "$status" != 0 ]; then
|
||||
log_i18n 2 "[%s] process %s error, skip this transparent proxy!" "${remarks}" "${config_file}"
|
||||
cat ${_error_log_file} >> ${LOG_FILE}
|
||||
unset _error_log_file
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1))
|
||||
run_copy_dnsmasq flag="$sid" listen_port=$dnsmasq_port local_dns="${LOCAL_DNS:-${AUTO_DNS}}" tun_dns="127.0.0.1#${dns_port}" default_dns="${AUTO_DNS}"
|
||||
#dhcp.leases to hostsMore actions
|
||||
$APP_PATH/lease2hosts.sh > /dev/null 2>&1 &
|
||||
|
||||
set_cache_var "ACL_${sid}_node" "$node"
|
||||
set_cache_var "ACL_${sid}_redir_port" "$redir_port"
|
||||
fi
|
||||
}
|
||||
fi
|
||||
}
|
||||
unset enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy remote_rewrite_ttl
|
||||
unset _ip _mac _iprange _ipset _ip_or_mac source_list config_file
|
||||
done
|
||||
unset redir_port dns_port dnsmasq_port
|
||||
[ -n "${has_enabled}" ] || ENABLED_ACLS=0
|
||||
fi
|
||||
else
|
||||
dnsmasq_port=$(get_new_port auto)
|
||||
run_copy_dnsmasq flag="${flag}" listen_port=${dnsmasq_port} local_dns="${LOCAL_DNS:-${AUTO_DNS}}" tun_dns="127.0.0.1#${dns_listen_port}" default_dns="${AUTO_DNS}"
|
||||
#dhcp.leases to hostsMore actions
|
||||
$APP_PATH/lease2hosts.sh > /dev/null 2>&1 &
|
||||
fi
|
||||
rm -f ${TMP_ACL_PATH}/acl_node_${nid}
|
||||
done
|
||||
[ ! -f ${TMP_ACL_PATH}/acl_node_default ] && ENABLED_DEFAULT_ACL=0
|
||||
[ "${acl_node_num}" == 0 ] && ENABLED_ACLS=0 && ENABLED_DEFAULT_ACL=0
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -1118,7 +881,7 @@ start() {
|
||||
}
|
||||
mkdir -p /tmp/etc /tmp/log $TMP_PATH $TMP_BIN_PATH $TMP_SCRIPT_FUNC_PATH $TMP_ROUTE_PATH $TMP_ACL_PATH $TMP_PATH2
|
||||
get_config
|
||||
export V2RAY_LOCATION_ASSET=$(config_t_get global_rules v2ray_location_asset "/usr/share/v2ray/")
|
||||
export V2RAY_LOCATION_ASSET=$(config_n_get @global_rules[0] v2ray_location_asset "/usr/share/v2ray/")
|
||||
export XRAY_LOCATION_ASSET=$V2RAY_LOCATION_ASSET
|
||||
export ENABLE_DEPRECATED_GEOSITE=true
|
||||
export ENABLE_DEPRECATED_GEOIP=true
|
||||
@@ -1129,21 +892,16 @@ start() {
|
||||
nftflag=0
|
||||
USE_TABLES=""
|
||||
check_run_environment
|
||||
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
|
||||
[ "$(uci -q get dhcp.@dnsmasq[0].dns_redirect)" == "1" ] && {
|
||||
uci -q set ${CONFIG}.@global[0].dnsmasq_dns_redirect='1'
|
||||
uci -q commit ${CONFIG}
|
||||
uci -q set dhcp.@dnsmasq[0].dns_redirect='0'
|
||||
uci -q commit dhcp
|
||||
[ "$(uci -q get dhcp.@dnsmasq[0].dns_redirect)" == "1" ] && {
|
||||
uci -q set ${CONFIG}.@global[0].dnsmasq_dns_redirect='1'
|
||||
uci -q commit ${CONFIG}
|
||||
uci -q set dhcp.@dnsmasq[0].dns_redirect='0'
|
||||
uci -q commit dhcp
|
||||
|
||||
json_init
|
||||
json_add_string "LOG" "0"
|
||||
lua $APP_PATH/helper_dnsmasq.lua restart "$(json_dump)"
|
||||
}
|
||||
fi
|
||||
mkdir -p ${GLOBAL_ACL_PATH}
|
||||
[ "$ENABLED_DEFAULT_ACL" == 1 ] && run_global
|
||||
run_global_dnsmasq
|
||||
json_init
|
||||
json_add_string "LOG" "0"
|
||||
lua $APP_PATH/helper_dnsmasq.lua restart "$(json_dump)"
|
||||
}
|
||||
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start
|
||||
set_cache_var "USE_TABLES" "$USE_TABLES"
|
||||
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
|
||||
@@ -1200,7 +958,7 @@ stop() {
|
||||
rm -rf $GLOBAL_DNSMASQ_CONF_PATH
|
||||
[ "1" = "1" ] && {
|
||||
#restore logic
|
||||
bak_dnsmasq_dns_redirect=$(config_t_get global dnsmasq_dns_redirect)
|
||||
bak_dnsmasq_dns_redirect=$(config_n_get @global[0] dnsmasq_dns_redirect)
|
||||
[ -n "${bak_dnsmasq_dns_redirect}" ] && {
|
||||
uci -q set dhcp.@dnsmasq[0].dns_redirect="${bak_dnsmasq_dns_redirect}"
|
||||
uci -q commit dhcp
|
||||
@@ -1247,32 +1005,14 @@ get_direct_dns() {
|
||||
|
||||
get_config() {
|
||||
ENABLED_DEFAULT_ACL=0
|
||||
ENABLED=$(config_t_get global enabled 0)
|
||||
NODE=$(config_t_get global node)
|
||||
[ "$ENABLED" == 1 ] && {
|
||||
[ -n "$NODE" ] && [ "$(config_get_type $NODE)" == "nodes" ] && ENABLED_DEFAULT_ACL=1
|
||||
}
|
||||
ENABLED_ACLS=$(config_t_get global acl_enable 0)
|
||||
SOCKS_ENABLED=$(config_t_get global socks_enabled 0)
|
||||
REDIR_PORT=$(echo $(get_new_port 1041 tcp,udp))
|
||||
TCP_PROXY_WAY=$(config_t_get global_forwarding tcp_proxy_way redirect)
|
||||
TCP_NO_REDIR_PORTS=$(config_t_get global_forwarding tcp_no_redir_ports 'disable')
|
||||
UDP_NO_REDIR_PORTS=$(config_t_get global_forwarding udp_no_redir_ports 'disable')
|
||||
TCP_REDIR_PORTS=$(config_t_get global_forwarding tcp_redir_ports '22,25,53,143,465,587,853,993,995,80,443')
|
||||
UDP_REDIR_PORTS=$(config_t_get global_forwarding udp_redir_ports '1:65535')
|
||||
PROXY_IPV6=$(config_t_get global_forwarding ipv6_tproxy 0)
|
||||
TCP_PROXY_MODE="global"
|
||||
UDP_PROXY_MODE="global"
|
||||
LOCALHOST_PROXY=$(config_t_get global localhost_proxy '1')
|
||||
CLIENT_PROXY=$(config_t_get global client_proxy '1')
|
||||
DIRECT_DNS_QUERY_STRATEGY=$(config_t_get global direct_dns_query_strategy UseIP)
|
||||
REMOTE_DNS_PROTOCOL=$(config_t_get global remote_dns_protocol tcp)
|
||||
REMOTE_DNS_DETOUR=$(config_t_get global remote_dns_detour remote)
|
||||
REMOTE_DNS=$(config_t_get global remote_dns 1.1.1.1:53 | sed 's/#/:/g' | sed -E 's/\:([^:]+)$/#\1/g')
|
||||
REMOTE_FAKEDNS=$(config_t_get global remote_fakedns '0')
|
||||
REMOTE_DNS_QUERY_STRATEGY=$(config_t_get global remote_dns_query_strategy UseIPv4)
|
||||
DNS_CACHE=$(config_t_get global dns_cache 1)
|
||||
DNS_REDIRECT=$(config_t_get global dns_redirect 1)
|
||||
ENABLED=$(config_n_get @global[0] enabled 0)
|
||||
NODE=$(config_n_get @global[0] node)
|
||||
[ "$ENABLED" == 1 ] && [ -n "$NODE" ] && [ "$(config_get_type $NODE)" == "nodes" ] && ENABLED_DEFAULT_ACL=1
|
||||
ENABLED_ACLS=$(config_n_get @global[0] acl_enable 0)
|
||||
SOCKS_ENABLED=$(config_n_get @global[0] socks_enabled 0)
|
||||
TCP_PROXY_WAY=$(config_n_get @global_forwarding[0] tcp_proxy_way redirect)
|
||||
PROXY_IPV6=$(config_n_get @global_forwarding[0] ipv6_tproxy 0)
|
||||
DIRECT_DNS_QUERY_STRATEGY=$(config_n_get @global[0] direct_dns_query_strategy UseIP)
|
||||
|
||||
get_direct_dns
|
||||
|
||||
@@ -1288,7 +1028,7 @@ get_config() {
|
||||
fi
|
||||
fi
|
||||
set_cache_var GLOBAL_DNSMASQ_CONF ${DNSMASQ_CONF_DIR}/dnsmasq-${CONFIG}.conf
|
||||
set_cache_var GLOBAL_DNSMASQ_CONF_PATH ${GLOBAL_ACL_PATH}/dnsmasq.d
|
||||
set_cache_var GLOBAL_DNSMASQ_CONF_PATH ${TMP_ACL_PATH}/default_dnsmasq.d
|
||||
|
||||
QUEUE_RUN=1
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
-- Copyright (C) 2026 xiaorouji
|
||||
|
||||
local api = require "luci.passwall2.api"
|
||||
local jsonc = api.jsonc
|
||||
local sys = api.sys
|
||||
local fs = api.fs
|
||||
local i18n = api.i18n
|
||||
local log = api.log
|
||||
local uci, uci_get, uci_set, uci_del, uci_foreach, uci_save = api.uci, api.uci_get_c, api.uci_set_c, api.uci_del_c, api.uci_foreach_c, api.uci_save_c
|
||||
|
||||
local VAR = {} -- Set VAR
|
||||
local D = {} -- Default Global Access Control
|
||||
local L = {
|
||||
acl = {},
|
||||
node = {},
|
||||
node_order = {}
|
||||
}
|
||||
|
||||
function add_args(t, k, v)
|
||||
if not t or not k or not v then return end
|
||||
table.insert(t, k .. "=" .. '"' .. v .. '"')
|
||||
end
|
||||
|
||||
function init_acl()
|
||||
if true then
|
||||
-- Get Default AC
|
||||
D.flag = "default"
|
||||
D.remarks = api.i18n.translatef("Default")
|
||||
D.tcp_no_redir_ports = uci_get("@global_forwarding[0]", "tcp_no_redir_ports")
|
||||
D.udp_no_redir_ports = uci_get("@global_forwarding[0]", "udp_no_redir_ports")
|
||||
D.tcp_redir_ports = uci_get("@global_forwarding[0]", "tcp_redir_ports")
|
||||
D.udp_redir_ports = uci_get("@global_forwarding[0]", "udp_redir_ports")
|
||||
D.node = uci_get("@global[0]", "node")
|
||||
D.local_proxy = uci_get("@global[0]", "localhost_proxy")
|
||||
D.client_proxy = uci_get("@global[0]", "client_proxy")
|
||||
if D.node then
|
||||
local node = uci_get(D.node)
|
||||
if node and node[".type"] == "nodes" then
|
||||
local n = {
|
||||
config = node,
|
||||
enabled = uci_get("@global[0]", "enabled") or "0",
|
||||
log = uci_get("@global[0]", "log_node") or "0",
|
||||
loglevel = uci_get("@global[0]", "loglevel") or "warn",
|
||||
socks_listen = uci_get("@global[0]", "node_socks_bind_local") == "0" and "0.0.0.0" or "127.0.0.1",
|
||||
socks_port = uci_get("@global[0]", "node_socks_port"),
|
||||
redir_port = api.get_new_port(),
|
||||
dns_port = api.get_new_port(),
|
||||
direct_dns_query_strategy = uci_get("@global[0]", "direct_dns_query_strategy") or "UseIP",
|
||||
remote_dns_protocol = uci_get("@global[0]", "remote_dns_protocol") or "tcp",
|
||||
remote_dns_detour = uci_get("@global[0]", "remote_dns_detour") or "remote",
|
||||
remote_dns = uci_get("@global[0]", "remote_dns") or "1.1.1.1:53",
|
||||
remote_dns_doh = uci_get("@global[0]", "remote_dns_doh") or "https://1.1.1.1/dns-query",
|
||||
remote_dns_client_ip = uci_get("@global[0]", "remote_dns_client_ip"),
|
||||
remote_dns_query_strategy = uci_get("@global[0]", "remote_dns_query_strategy") or "UseIPv4",
|
||||
remote_rewrite_ttl = uci_get("@global[0]", "remote_rewrite_ttl"),
|
||||
remote_fakedns = uci_get("@global[0]", "remote_fakedns") or "0",
|
||||
}
|
||||
L.node[D.flag] = n
|
||||
D.use = D.flag
|
||||
if n.enabled == "1" then
|
||||
L.node_order[#L.node_order + 1] = D.flag
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local acl_num = 0
|
||||
if uci_get("@global[0]", "acl_enable") == "1" then
|
||||
uci_foreach("acl_rule", function(o)
|
||||
if o.enabled == "1" then
|
||||
acl_num = acl_num + 1
|
||||
local a = {}
|
||||
a.flag = o[".name"]
|
||||
a.remarks = o.remarks
|
||||
a.interface = o.interface
|
||||
a.sources = o.sources
|
||||
a.tcp_no_redir_ports = o.tcp_no_redir_ports
|
||||
a.udp_no_redir_ports = o.udp_no_redir_ports
|
||||
a.tcp_redir_ports = o.tcp_redir_ports
|
||||
a.udp_redir_ports = o.udp_redir_ports
|
||||
a.client_proxy = "1"
|
||||
a.local_proxy = "0"
|
||||
a.node = o.node
|
||||
if o.mode == "0" then
|
||||
a.tcp_no_redir_ports = "1:65535"
|
||||
a.udp_no_redir_ports = "1:65535"
|
||||
elseif o.mode == "2" then
|
||||
local U = L.node[D.use]
|
||||
if U.enabled == "0" then
|
||||
U.enabled = "1"
|
||||
D.local_proxy = "0"
|
||||
D.client_proxy = "0"
|
||||
end
|
||||
a.use = D.use
|
||||
end
|
||||
if a.tcp_no_redir_ports == "1:65535" and a.udp_no_redir_ports == "1:65535" then
|
||||
a.node = nil
|
||||
end
|
||||
if a.node then
|
||||
local node = uci_get(a.node)
|
||||
if node and node[".type"] == "nodes" then
|
||||
local n = {
|
||||
config = node,
|
||||
enabled = "1",
|
||||
log = o.log or "0",
|
||||
loglevel = o.loglevel or "warn",
|
||||
redir_port = api.get_new_port(),
|
||||
dns_port = api.get_new_port(),
|
||||
direct_dns_query_strategy = o.direct_dns_query_strategy,
|
||||
remote_dns_protocol = o.remote_dns_protocol,
|
||||
remote_dns_detour = o.remote_dns_detour,
|
||||
remote_dns = o.remote_dns,
|
||||
remote_dns_doh = o.remote_dns_doh,
|
||||
remote_dns_client_ip = o.remote_dns_client_ip,
|
||||
remote_dns_query_strategy = o.remote_dns_query_strategy,
|
||||
remote_rewrite_ttl = o.remote_rewrite_ttl,
|
||||
remote_fakedns = o.remote_fakedns,
|
||||
}
|
||||
L.node[a.flag] = n
|
||||
a.use = a.flag
|
||||
if n.enabled == "1" then
|
||||
L.node_order[#L.node_order + 1] = a.flag
|
||||
end
|
||||
end
|
||||
end
|
||||
L.acl[#L.acl + 1] = a
|
||||
end
|
||||
end)
|
||||
end
|
||||
if next(D) then
|
||||
L.acl[#L.acl + 1] = D
|
||||
end
|
||||
VAR["ENABLED_ACLS"] = acl_num > 0 and 1 or 0
|
||||
return L
|
||||
end
|
||||
|
||||
function acl_app(l)
|
||||
if not l then l = L end
|
||||
for i, v in ipairs(l.acl) do
|
||||
local sid = v.flag
|
||||
local acl_path = api.TMP_ACL_PATH .. "/" .. sid
|
||||
sys.call("mkdir -p " .. acl_path)
|
||||
local out = io.open(acl_path .. "/var", "a")
|
||||
for k2, v2 in pairs(v) do
|
||||
if type(v2) == "string" then
|
||||
out:write(k2 .. "=" .. '"' .. v2 .. '"' .. "\n")
|
||||
end
|
||||
end
|
||||
if v.use then
|
||||
local node = l.node[v.use]
|
||||
if node.config then
|
||||
out:write("node" .. "=" .. '"' .. node.config[".name"] .. '"' .. "\n")
|
||||
out:write("node_remarks" .. "=" .. '"' .. node.config.remarks .. '"' .. "\n")
|
||||
end
|
||||
out:write("redir_port" .. "=" .. '"' .. node.redir_port .. '"' .. "\n")
|
||||
end
|
||||
out:close()
|
||||
local source_list = "any"
|
||||
if v.sources and #v.sources > 0 then
|
||||
local s1 = {}
|
||||
for i, w in ipairs(v.sources) do
|
||||
if api.iprange(w) then
|
||||
s1[#s1 + 1] = "iprange:" .. w
|
||||
elseif w:find("ipset:") == 1 then
|
||||
s1[#s1 + 1] = "ipset:" .. w
|
||||
else
|
||||
local _ip_or_mac = api.ip_or_mac(w)
|
||||
if _ip_or_mac == "ip" then
|
||||
s1[#s1 + 1] = "ip:" .. w
|
||||
elseif _ip_or_mac == "mac" then
|
||||
s1[#s1 + 1] = "mac:" .. w
|
||||
end
|
||||
end
|
||||
end
|
||||
if #s1 > 0 then
|
||||
source_list = table.concat(s1, "\n")
|
||||
end
|
||||
end
|
||||
if #source_list > 0 then
|
||||
local out = io.open(acl_path .. "/source_list", "a")
|
||||
out:write(source_list)
|
||||
out:close()
|
||||
end
|
||||
end
|
||||
-- Gen shell param
|
||||
for _, v1 in ipairs(l.node_order) do
|
||||
local v = l.node[v1]
|
||||
if v.enabled == "1" then
|
||||
local flag = v1
|
||||
local node = v.config
|
||||
local run_args = {}
|
||||
local config_path = api.TMP_ACL_PATH .. "/" .. flag
|
||||
local config_file = config_path .. ".json"
|
||||
local log_file = v.log == "0" and "/dev/null" or config_path .. ".log"
|
||||
add_args(run_args, "flag", flag)
|
||||
add_args(run_args, "node", node[".name"])
|
||||
add_args(run_args, "redir_port", v.redir_port)
|
||||
add_args(run_args, "socks_address", v.socks_listen)
|
||||
add_args(run_args, "socks_port", v.socks_port)
|
||||
add_args(run_args, "dns_listen_port", v.dns_port)
|
||||
add_args(run_args, "direct_dns_query_strategy", v.direct_dns_query_strategy)
|
||||
add_args(run_args, "remote_dns_protocol", v.remote_dns_protocol)
|
||||
add_args(run_args, "remote_dns_tcp_server", v.remote_dns)
|
||||
add_args(run_args, "remote_dns_udp_server", v.remote_dns)
|
||||
add_args(run_args, "remote_dns_doh", v.remote_dns_doh)
|
||||
add_args(run_args, "remote_dns_client_ip", v.remote_dns_client_ip)
|
||||
add_args(run_args, "remote_dns_detour", v.remote_dns_detour)
|
||||
add_args(run_args, "remote_dns_query_strategy", v.remote_dns_query_strategy)
|
||||
add_args(run_args, "remote_fakedns", v.remote_fakedns)
|
||||
add_args(run_args, "remote_rewrite_ttl", v.remote_rewrite_ttl)
|
||||
add_args(run_args, "config_file", config_file)
|
||||
add_args(run_args, "loglevel", v.loglevel)
|
||||
add_args(run_args, "log_file", log_file)
|
||||
|
||||
local out = io.open(api.TMP_ACL_PATH .. "/acl_node_" .. flag , "a")
|
||||
out:write(table.concat(run_args, " "))
|
||||
out:close()
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(VAR) do
|
||||
api.set_cache_var(k, v)
|
||||
end
|
||||
end
|
||||
|
||||
local acls = init_acl()
|
||||
acl_app()
|
||||
print(jsonc.stringify(acls, 1))
|
||||
@@ -211,7 +211,7 @@ gen_shunt_list() {
|
||||
[ -n "$_geoip_code" ] && {
|
||||
get_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_v4 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R
|
||||
get_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_v6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R
|
||||
log 1 "$(i18n "parse the traffic splitting rules[%s]-[geoip:%s] add to %s to complete." "${shunt_id}" "${_geoip_code}" "IPSET")"
|
||||
#log 3 "$(i18n "parse the traffic splitting rules[%s]-[geoip:%s] add to %s to complete." "${shunt_id}" "${_geoip_code}" "IPSET[${ipset_v4},${ipset_v6}]")"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,6 +230,7 @@ gen_shunt_list() {
|
||||
}
|
||||
[ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\"
|
||||
[ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\"
|
||||
set_cache_var "${node}_gen_shunt_list" "1"
|
||||
}
|
||||
|
||||
add_shunt_t_rule() {
|
||||
@@ -255,45 +256,21 @@ add_shunt_t_rule() {
|
||||
}
|
||||
|
||||
load_acl() {
|
||||
acl_json=$(lua $APP_PATH/app_acl.lua)
|
||||
acl_node
|
||||
log_i18n 1 "Access Control:"
|
||||
[ "$ENABLED_ACLS" == 1 ] && {
|
||||
acl_app
|
||||
for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do
|
||||
eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-)
|
||||
for sid in $(jsonfilter -s "${acl_json}" -e '$.acl[*].flag'); do
|
||||
eval local $(cat "${TMP_ACL_PATH}/${sid}/var")
|
||||
|
||||
mode=${mode:-0}
|
||||
tcp_no_redir_ports=${tcp_no_redir_ports:-default}
|
||||
udp_no_redir_ports=${udp_no_redir_ports:-default}
|
||||
tcp_proxy_mode="global"
|
||||
udp_proxy_mode="global"
|
||||
tcp_redir_ports=${tcp_redir_ports:-default}
|
||||
udp_redir_ports=${udp_redir_ports:-default}
|
||||
node=${node:-default}
|
||||
[ "$mode" = "0" ] && {
|
||||
tcp_no_redir_ports="1:65535"
|
||||
udp_no_redir_ports="1:65535"
|
||||
}
|
||||
[ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS
|
||||
[ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS
|
||||
[ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS
|
||||
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
|
||||
[ -z "$(get_cache_var "${node}_gen_shunt_list")" ] && [ -n "${node}" ] && gen_shunt_list "${node}" shunt_list4 shunt_list6
|
||||
[ -n "${use}" ] && local dns_redirect_port=$(get_cache_var "ACL_${use}_dns_port")
|
||||
|
||||
[ -n "$(get_cache_var "ACL_${sid}_node")" ] && node=$(get_cache_var "ACL_${sid}_node")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_redir_port")" ] && redir_port=$(get_cache_var "ACL_${sid}_redir_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
|
||||
[ -n "$node" ] && node_remark=$(config_n_get $node remarks)
|
||||
local ipt_tmp=$ipt_n
|
||||
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
|
||||
|
||||
if [ -n "$(get_cache_var "ACL_${sid}_default")" ]; then
|
||||
shunt_list4=${SHUNT_LIST4}
|
||||
shunt_list6=${SHUNT_LIST6}
|
||||
else
|
||||
# Shunt rules IP list (import when use shunt node)
|
||||
gen_shunt_list "${node}" shunt_list4 shunt_list6
|
||||
fi
|
||||
|
||||
_acl_list=${TMP_ACL_PATH}/${sid}/source_list
|
||||
|
||||
for i in $(cat $_acl_list); do
|
||||
[ "${client_proxy}" = "1" ] && {
|
||||
msg1="$(i18n "[%s]," "${remarks}")"
|
||||
for i in $(cat ${TMP_ACL_PATH}/${sid}/source_list); do
|
||||
local _ipt_source _ipv4
|
||||
local msg
|
||||
if [ -n "${interface}" ]; then
|
||||
@@ -344,41 +321,39 @@ load_acl() {
|
||||
else
|
||||
continue
|
||||
fi
|
||||
msg="$(i18n "[%s]," "${remarks}")${msg}"
|
||||
|
||||
ipt_tmp=$ipt_n
|
||||
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
|
||||
|
||||
[ "$tcp_no_redir_ports" != "disable" ] && {
|
||||
msg="${msg1}${msg}"
|
||||
|
||||
[ -n "$tcp_no_redir_ports" ] && {
|
||||
if ! has_1_65535 "$tcp_no_redir_ports"; then
|
||||
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" 2>/dev/null
|
||||
add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN"
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${tcp_no_redir_ports}")"
|
||||
else
|
||||
# It will return when it ends, so no extra rules are needed.
|
||||
tcp_proxy_mode="disable"
|
||||
no_tcp_proxy="1"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
|
||||
fi
|
||||
}
|
||||
|
||||
[ "$udp_no_redir_ports" != "disable" ] && {
|
||||
[ -n "$udp_no_redir_ports" ] && {
|
||||
if ! has_1_65535 "$udp_no_redir_ports"; then
|
||||
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null
|
||||
add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN"
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${udp_no_redir_ports}")"
|
||||
else
|
||||
# It will return when it ends, so no extra rules are needed.
|
||||
udp_proxy_mode="disable"
|
||||
no_udp_proxy="1"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
|
||||
fi
|
||||
}
|
||||
|
||||
if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$dns_redirect_port" ]; then
|
||||
if ([ -z "$no_tcp_proxy" ] || [ -z "$no_udp_proxy" ]) && [ -n "$dns_redirect_port" ]; then
|
||||
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
|
||||
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
|
||||
$ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
|
||||
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
|
||||
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && log 2 "${msg}$(i18n "Using a node that is different from the global configuration, DNS has been forcibly redirected to a dedicated DNS server.")"
|
||||
log 2 "${msg}$(i18n "DNS will redirected to the dedicated DNS server [%s]." "${dns_redirect_port}")"
|
||||
else
|
||||
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
|
||||
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
|
||||
@@ -386,8 +361,8 @@ load_acl() {
|
||||
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
|
||||
fi
|
||||
|
||||
[ "$tcp_proxy_mode" != "disable" ] && [ -n "$redir_port" ] && {
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remark}")"
|
||||
[ -z "$no_tcp_proxy" ] && [ -n "$redir_port" ] && {
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remarks}")"
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
msg2="${msg2}(TPROXY:${redir_port})"
|
||||
ipt_j="-j PSW2_RULE"
|
||||
@@ -424,8 +399,8 @@ load_acl() {
|
||||
$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -j RETURN
|
||||
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -j RETURN 2>/dev/null
|
||||
|
||||
[ "$udp_proxy_mode" != "disable" ] && [ -n "$redir_port" ] && {
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remark}")(TPROXY:${redir_port})"
|
||||
[ -z "$no_tcp_proxy" ] && [ -n "$redir_port" ] && {
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remarks}")(TPROXY:${redir_port})"
|
||||
|
||||
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP -j PSW2_RULE
|
||||
add_shunt_t_rule "${shunt_list4}" "$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" "-j PSW2_RULE" $udp_redir_ports
|
||||
@@ -442,105 +417,143 @@ load_acl() {
|
||||
}
|
||||
$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -j RETURN
|
||||
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -j RETURN 2>/dev/null
|
||||
unset ipt_tmp ipt_j _ipt_source msg msg2 _ipv4
|
||||
unset ipt_j _ipt_source msg msg2 _ipv4 no_tcp_proxy no_udp_proxy
|
||||
done
|
||||
unset enabled sid remarks sources tcp_no_redir_ports udp_no_redir_ports tcp_redir_ports udp_redir_ports node interface
|
||||
unset node_remark _acl_list
|
||||
done
|
||||
}
|
||||
|
||||
[ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ] && {
|
||||
local comment_d="$(i18n "Default")"
|
||||
msg="$(i18n "[%s]," ${comment_d})"
|
||||
local ipt_tmp=$ipt_n
|
||||
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
|
||||
|
||||
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
add_port_rules "$ip6t_m -A PSW2 $(comment "${comment_d}") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
|
||||
add_port_rules "$ipt_tmp -A PSW2 $(comment "${comment_d}") -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
|
||||
if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${TCP_NO_REDIR_PORTS}")"
|
||||
else
|
||||
TCP_PROXY_MODE="disable"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
|
||||
fi
|
||||
unset msg1
|
||||
}
|
||||
|
||||
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
add_port_rules "$ip6t_m -A PSW2 $(comment "${comment_d}") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN"
|
||||
add_port_rules "$ipt_tmp -A PSW2 $(comment "${comment_d}") -p udp" $UDP_NO_REDIR_PORTS "-j RETURN"
|
||||
if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${UDP_NO_REDIR_PORTS}")"
|
||||
else
|
||||
UDP_PROXY_MODE="disable"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
|
||||
fi
|
||||
}
|
||||
|
||||
if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ -n "$NODE" ]; then
|
||||
[ -n "$DNS_REDIRECT_PORT" ] && {
|
||||
$ipt_n -A PSW2_DNS $(comment "${comment_d}") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
|
||||
$ip6t_n -A PSW2_DNS $(comment "${comment_d}") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
|
||||
$ipt_n -A PSW2_DNS $(comment "${comment_d}") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
|
||||
$ip6t_n -A PSW2_DNS $(comment "${comment_d}") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
|
||||
[ "${local_proxy}" = "1" ] && {
|
||||
msg="$(i18n "[Local],")"
|
||||
[ -n "$tcp_no_redir_ports" ] && {
|
||||
add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $tcp_no_redir_ports "-j RETURN"
|
||||
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $tcp_no_redir_ports "-j RETURN"
|
||||
if ! has_1_65535 "$tcp_no_redir_ports"; then
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${tcp_no_redir_ports}")"
|
||||
else
|
||||
no_tcp_local_proxy="1"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
|
||||
fi
|
||||
}
|
||||
fi
|
||||
|
||||
if [ "$TCP_PROXY_MODE" != "disable" ] && [ -n "$NODE" ]; then
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "$(config_n_get $NODE remarks)")"
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
msg2="${msg2}(TPROXY:${REDIR_PORT})"
|
||||
ipt_j="-j PSW2_RULE"
|
||||
else
|
||||
msg2="${msg2}(REDIRECT:${REDIR_PORT})"
|
||||
ipt_j="$(REDIRECT $REDIR_PORT)"
|
||||
fi
|
||||
|
||||
[ "$accept_icmp" = "1" ] && {
|
||||
$ipt_n -A PSW2 $(comment "${comment_d}") -p icmp -d $FAKE_IP $(REDIRECT)
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_n -A PSW2 $(comment "${comment_d}") -p icmp" "$(REDIRECT)"
|
||||
$ipt_n -A PSW2 $(comment "${comment_d}") -p icmp $(REDIRECT)
|
||||
[ -n "$udp_no_redir_ports" ] && {
|
||||
add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $udp_no_redir_ports "-j RETURN"
|
||||
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $udp_no_redir_ports "-j RETURN"
|
||||
if ! has_1_65535 "$udp_no_redir_ports"; then
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${udp_no_redir_ports}")"
|
||||
else
|
||||
no_udp_local_proxy="1"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
|
||||
fi
|
||||
}
|
||||
|
||||
[ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && {
|
||||
$ip6t_n -A PSW2 $(comment "${comment_d}") -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT)
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_n -A PSW2 $(comment "${comment_d}") -p ipv6-icmp" "$(REDIRECT)"
|
||||
$ip6t_n -A PSW2 $(comment "${comment_d}") -p ipv6-icmp $(REDIRECT)
|
||||
}
|
||||
if [ -n "$node" ] && ([ -z "$no_tcp_local_proxy" ] || [ -z "$no_udp_local_proxy" ]); then
|
||||
[ -n "$dns_redirect_port" ] && {
|
||||
$ipt_n -A OUTPUT $(comment "PSW2_DNS") -p udp -o lo --dport 53 -j REDIRECT --to-ports $dns_redirect_port
|
||||
$ip6t_n -A OUTPUT $(comment "PSW2_DNS") -p udp -o lo --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
|
||||
$ipt_n -A OUTPUT $(comment "PSW2_DNS") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $dns_redirect_port
|
||||
$ip6t_n -A OUTPUT $(comment "PSW2_DNS") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
|
||||
log 2 "${msg}$(i18n "DNS will redirected to the dedicated DNS server [%s]." "${dns_redirect_port}")"
|
||||
}
|
||||
fi
|
||||
|
||||
$ipt_tmp -A PSW2 $(comment "${comment_d}") -p tcp -d $FAKE_IP ${ipt_j}
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_tmp -A PSW2 $(comment "${comment_d}") -p tcp" "${ipt_j}" $TCP_REDIR_PORTS
|
||||
add_port_rules "$ipt_tmp -A PSW2 $(comment "${comment_d}") -p tcp" $TCP_REDIR_PORTS "${ipt_j}"
|
||||
[ -n "${is_tproxy}" ] && $ipt_m -A PSW2 $(comment "${comment_d}") -p tcp $(REDIRECT $REDIR_PORT TPROXY)
|
||||
local comment_l="$(i18n "Local")"
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
$ip6t_m -A PSW2 $(comment "${comment_d}") -p tcp -d $FAKE_IP_6 -j PSW2_RULE
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2 $(comment "${comment_d}") -p tcp" "-j PSW2_RULE" $TCP_REDIR_PORTS
|
||||
add_port_rules "$ip6t_m -A PSW2 $(comment "${comment_d}") -p tcp" $TCP_REDIR_PORTS "-j PSW2_RULE"
|
||||
$ip6t_m -A PSW2 $(comment "${comment_d}") -p tcp $(REDIRECT $REDIR_PORT TPROXY)
|
||||
}
|
||||
# Loading local router proxy TCP
|
||||
if [ -n "$node" ] && [ -z "$no_tcp_local_proxy" ]; then
|
||||
[ "$accept_icmp" = "1" ] && {
|
||||
$ipt_n -A OUTPUT $(dst $IPSET_DIRECT !) -p icmp -j PSW2_OUTPUT
|
||||
$ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT)
|
||||
add_shunt_t_rule "${shunt_list4}" "$ipt_n -A PSW2_OUTPUT -p icmp" "$(REDIRECT)"
|
||||
$ipt_n -A PSW2_OUTPUT -p icmp $(REDIRECT)
|
||||
}
|
||||
|
||||
log 2 "${msg2}"
|
||||
fi
|
||||
[ "$accept_icmpv6" = "1" ] && {
|
||||
$ip6t_n -A OUTPUT $(dst $IPSET_DIRECT6 !) -p ipv6-icmp -j PSW2_OUTPUT
|
||||
$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT)
|
||||
add_shunt_t_rule "${shunt_list6}" "$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp" "$(REDIRECT)"
|
||||
$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp $(REDIRECT)
|
||||
}
|
||||
|
||||
if [ "$UDP_PROXY_MODE" != "disable" ] && [ -n "$NODE" ]; then
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "$(config_n_get $NODE remarks)")(TPROXY:${REDIR_PORT})"
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remarks}")"
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
msg2="${msg2}(TPROXY:${redir_port})"
|
||||
ipt_j="-j PSW2_RULE"
|
||||
else
|
||||
msg2="${msg2}(REDIRECT:${redir_port})"
|
||||
ipt_j="$(REDIRECT $redir_port)"
|
||||
fi
|
||||
|
||||
$ipt_m -A PSW2 $(comment "${comment_d}") -p udp -d $FAKE_IP -j PSW2_RULE
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_m -A PSW2 $(comment "${comment_d}") -p udp" "-j PSW2_RULE" $UDP_REDIR_PORTS
|
||||
add_port_rules "$ipt_m -A PSW2 $(comment "${comment_d}") -p udp" $UDP_REDIR_PORTS "-j PSW2_RULE"
|
||||
$ipt_m -A PSW2 $(comment "${comment_d}") -p udp $(REDIRECT $REDIR_PORT TPROXY)
|
||||
$ipt_tmp -A PSW2_OUTPUT -p tcp -d $FAKE_IP ${ipt_j}
|
||||
add_shunt_t_rule "${shunt_list4}" "$ipt_tmp -A PSW2_OUTPUT -p tcp" "${ipt_j}" $tcp_redir_ports
|
||||
add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $tcp_redir_ports "${ipt_j}"
|
||||
[ -z "${is_tproxy}" ] && $ipt_n -A OUTPUT $(dst $IPSET_DIRECT !) -p tcp -j PSW2_OUTPUT
|
||||
[ -n "${is_tproxy}" ] && {
|
||||
$ipt_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo $(REDIRECT $redir_port TPROXY)
|
||||
$ipt_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo -j RETURN
|
||||
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT !) -p tcp -j PSW2_OUTPUT"
|
||||
}
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
$ip6t_m -A PSW2 $(comment "${comment_d}") -p udp -d $FAKE_IP_6 -j PSW2_RULE
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2 $(comment "${comment_d}") -p udp" "-j PSW2_RULE" $UDP_REDIR_PORTS
|
||||
add_port_rules "$ip6t_m -A PSW2 $(comment "${comment_d}") -p udp" $UDP_REDIR_PORTS "-j PSW2_RULE"
|
||||
$ip6t_m -A PSW2 $(comment "${comment_d}") -p udp $(REDIRECT $REDIR_PORT TPROXY)
|
||||
}
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
$ip6t_m -A PSW2_OUTPUT -p tcp -d $FAKE_IP_6 -j PSW2_RULE
|
||||
add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2_OUTPUT -p tcp" "-j PSW2_RULE" $tcp_redir_ports
|
||||
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $tcp_redir_ports "-j PSW2_RULE"
|
||||
$ip6t_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo $(REDIRECT $redir_port TPROXY)
|
||||
$ip6t_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo -j RETURN
|
||||
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT6 !) -p tcp -j PSW2_OUTPUT"
|
||||
}
|
||||
|
||||
log 2 "${msg2}"
|
||||
fi
|
||||
}
|
||||
[ -d "${TMP_IFACE_PATH}" ] && {
|
||||
for iface in $(ls ${TMP_IFACE_PATH}); do
|
||||
$ipt_n -A PSW2_OUTPUT -o $iface -p tcp -j RETURN
|
||||
$ipt_m -A PSW2_OUTPUT -o $iface -p tcp -j RETURN
|
||||
done
|
||||
}
|
||||
log 2 "${msg2}"
|
||||
fi
|
||||
|
||||
# Loading local router proxy UDP
|
||||
if [ -n "$node" ] && [ -z "$no_udp_local_proxy" ]; then
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remarks}")(TPROXY:${redir_port})"
|
||||
$ipt_m -A PSW2_OUTPUT -p udp -d $FAKE_IP -j PSW2_RULE
|
||||
add_shunt_t_rule "${shunt_list4}" "$ipt_m -A PSW2_OUTPUT -p udp" "-j PSW2_RULE" $udp_redir_ports
|
||||
add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $udp_redir_ports "-j PSW2_RULE"
|
||||
$ipt_m -A PSW2 $(comment "${comment_l}") -p udp -i lo $(REDIRECT $redir_port TPROXY)
|
||||
$ipt_m -A PSW2 $(comment "${comment_l}") -p udp -i lo -j RETURN
|
||||
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT !) -p udp -j PSW2_OUTPUT"
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
$ip6t_m -A PSW2_OUTPUT -p udp -d $FAKE_IP_6 -j PSW2_RULE
|
||||
add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2_OUTPUT -p udp" "-j PSW2_RULE" $udp_redir_ports
|
||||
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $udp_redir_ports "-j PSW2_RULE"
|
||||
$ip6t_m -A PSW2 $(comment "${comment_l}") -p udp -i lo $(REDIRECT $redir_port TPROXY)
|
||||
$ip6t_m -A PSW2 $(comment "${comment_l}") -p udp -i lo -j RETURN
|
||||
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT6 !) -p udp -j PSW2_OUTPUT"
|
||||
}
|
||||
|
||||
[ -d "${TMP_IFACE_PATH}" ] && {
|
||||
for iface in $(ls ${TMP_IFACE_PATH}); do
|
||||
$ipt_n -A PSW2_OUTPUT -o $iface -p udp -j RETURN
|
||||
$ipt_m -A PSW2_OUTPUT -o $iface -p udp -j RETURN
|
||||
done
|
||||
}
|
||||
|
||||
log 2 "${msg2}"
|
||||
fi
|
||||
|
||||
$ipt_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
|
||||
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN"
|
||||
|
||||
$ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
|
||||
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN"
|
||||
|
||||
$ipt_m -A PSW2 -p tcp --dport 53 -j ACCEPT
|
||||
$ipt_m -A PSW2 -p udp --dport 53 -j ACCEPT
|
||||
$ip6t_m -A PSW2 -p tcp --dport 53 -j ACCEPT
|
||||
$ip6t_m -A PSW2 -p udp --dport 53 -j ACCEPT
|
||||
|
||||
unset msg msg2 comment_l
|
||||
}
|
||||
unset dns_redirect_port ipt_tmp
|
||||
unset $(cat "${TMP_ACL_PATH}/${sid}/var" | awk -F '=' '{print $1}' | tr "\n" " ")
|
||||
done
|
||||
}
|
||||
|
||||
filter_haproxy() {
|
||||
@@ -684,15 +697,12 @@ add_firewall_rule() {
|
||||
done
|
||||
}
|
||||
|
||||
# Shunt rules IP list (import when use shunt node)
|
||||
gen_shunt_list "${NODE}" SHUNT_LIST4 SHUNT_LIST6
|
||||
|
||||
# Filter all node IPs
|
||||
filter_vpsip > /dev/null 2>&1 &
|
||||
filter_haproxy > /dev/null 2>&1 &
|
||||
|
||||
accept_icmp=$(config_t_get global_forwarding accept_icmp 0)
|
||||
accept_icmpv6=$(config_t_get global_forwarding accept_icmpv6 0)
|
||||
accept_icmp=$(config_n_get @global_forwarding[0] accept_icmp 0)
|
||||
accept_icmpv6=$(config_n_get @global_forwarding[0] accept_icmpv6 0)
|
||||
|
||||
if [ "${TCP_PROXY_WAY}" = "redirect" ]; then
|
||||
unset is_tproxy
|
||||
@@ -720,7 +730,7 @@ add_firewall_rule() {
|
||||
$ipt_n -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
|
||||
|
||||
$ipt_n -N PSW2_DNS
|
||||
if [ $(config_t_get global dns_redirect "1") = "0" ]; then
|
||||
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
|
||||
#Only hijack when dest address is local IP
|
||||
$ipt_n -I PREROUTING -m set --match-set $IPSET_DIRECT src $(dst $IPSET_LOCAL) -j PSW2_DNS
|
||||
else
|
||||
@@ -763,7 +773,7 @@ add_firewall_rule() {
|
||||
}
|
||||
|
||||
$ip6t_n -N PSW2_DNS
|
||||
if [ $(config_t_get global dns_redirect "1") = "0" ]; then
|
||||
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
|
||||
#Only hijack when dest address is local IP
|
||||
$ip6t_n -I PREROUTING -m set --match-set $IPSET_DIRECT6 src $(dst $IPSET_LOCAL6) -j PSW2_DNS
|
||||
else
|
||||
@@ -809,134 +819,6 @@ add_firewall_rule() {
|
||||
ip -6 rule add fwmark ${FWMARK} table 999 priority 999
|
||||
ip -6 route add local ::/0 dev lo table 999
|
||||
|
||||
[ "$ENABLED_DEFAULT_ACL" == 1 ] && {
|
||||
local ipt_tmp=$ipt_n
|
||||
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
|
||||
|
||||
TCP_LOCALHOST_PROXY=$LOCALHOST_PROXY
|
||||
UDP_LOCALHOST_PROXY=$LOCALHOST_PROXY
|
||||
|
||||
msg="$(i18n "[Local],")"
|
||||
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
|
||||
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $TCP_NO_REDIR_PORTS "-j RETURN"
|
||||
if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then
|
||||
log 1 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${TCP_NO_REDIR_PORTS}")"
|
||||
else
|
||||
unset TCP_LOCALHOST_PROXY
|
||||
log 1 "${msg}$(i18n "not proxy all %s" "TCP")"
|
||||
fi
|
||||
}
|
||||
|
||||
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN"
|
||||
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $UDP_NO_REDIR_PORTS "-j RETURN"
|
||||
if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
|
||||
log 1 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${UDP_NO_REDIR_PORTS}")"
|
||||
else
|
||||
unset UDP_LOCALHOST_PROXY
|
||||
log 1 "${msg}$(i18n "not proxy all %s" "UDP")"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -n "$NODE" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then
|
||||
[ -n "$DNS_REDIRECT_PORT" ] && {
|
||||
$ipt_n -A OUTPUT $(comment "PSW2_DNS") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
|
||||
$ip6t_n -A OUTPUT $(comment "PSW2_DNS") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
|
||||
$ipt_n -A OUTPUT $(comment "PSW2_DNS") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
|
||||
$ip6t_n -A OUTPUT $(comment "PSW2_DNS") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
|
||||
}
|
||||
fi
|
||||
|
||||
local comment_l="$(i18n "Local")"
|
||||
|
||||
# Loading local router proxy TCP
|
||||
if [ -n "$NODE" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
|
||||
[ "$accept_icmp" = "1" ] && {
|
||||
$ipt_n -A OUTPUT $(dst $IPSET_DIRECT !) -p icmp -j PSW2_OUTPUT
|
||||
$ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT)
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_n -A PSW2_OUTPUT -p icmp" "$(REDIRECT)"
|
||||
$ipt_n -A PSW2_OUTPUT -p icmp $(REDIRECT)
|
||||
}
|
||||
|
||||
[ "$accept_icmpv6" = "1" ] && {
|
||||
$ip6t_n -A OUTPUT $(dst $IPSET_DIRECT6 !) -p ipv6-icmp -j PSW2_OUTPUT
|
||||
$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT)
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp" "$(REDIRECT)"
|
||||
$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp $(REDIRECT)
|
||||
}
|
||||
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
ipt_j="-j PSW2_RULE"
|
||||
else
|
||||
ipt_j="$(REDIRECT $REDIR_PORT)"
|
||||
fi
|
||||
|
||||
$ipt_tmp -A PSW2_OUTPUT -p tcp -d $FAKE_IP ${ipt_j}
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_tmp -A PSW2_OUTPUT -p tcp" "${ipt_j}" $TCP_REDIR_PORTS
|
||||
add_port_rules "$ipt_tmp -A PSW2_OUTPUT -p tcp" $TCP_REDIR_PORTS "${ipt_j}"
|
||||
[ -z "${is_tproxy}" ] && $ipt_n -A OUTPUT $(dst $IPSET_DIRECT !) -p tcp -j PSW2_OUTPUT
|
||||
[ -n "${is_tproxy}" ] && {
|
||||
$ipt_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo $(REDIRECT $REDIR_PORT TPROXY)
|
||||
$ipt_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo -j RETURN
|
||||
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT !) -p tcp -j PSW2_OUTPUT"
|
||||
}
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
$ip6t_m -A PSW2_OUTPUT -p tcp -d $FAKE_IP_6 -j PSW2_RULE
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2_OUTPUT -p tcp" "-j PSW2_RULE" $TCP_REDIR_PORTS
|
||||
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p tcp" $TCP_REDIR_PORTS "-j PSW2_RULE"
|
||||
$ip6t_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo $(REDIRECT $REDIR_PORT TPROXY)
|
||||
$ip6t_m -A PSW2 $(comment "${comment_l}") -p tcp -i lo -j RETURN
|
||||
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT6 !) -p tcp -j PSW2_OUTPUT"
|
||||
}
|
||||
|
||||
[ -d "${TMP_IFACE_PATH}" ] && {
|
||||
for iface in $(ls ${TMP_IFACE_PATH}); do
|
||||
$ipt_n -A PSW2_OUTPUT -o $iface -p tcp -j RETURN
|
||||
$ipt_m -A PSW2_OUTPUT -o $iface -p tcp -j RETURN
|
||||
done
|
||||
}
|
||||
fi
|
||||
|
||||
# Loading local router proxy UDP
|
||||
if [ -n "$NODE" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then
|
||||
$ipt_m -A PSW2_OUTPUT -p udp -d $FAKE_IP -j PSW2_RULE
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_m -A PSW2_OUTPUT -p udp" "-j PSW2_RULE" $UDP_REDIR_PORTS
|
||||
add_port_rules "$ipt_m -A PSW2_OUTPUT -p udp" $UDP_REDIR_PORTS "-j PSW2_RULE"
|
||||
$ipt_m -A PSW2 $(comment "${comment_l}") -p udp -i lo $(REDIRECT $REDIR_PORT TPROXY)
|
||||
$ipt_m -A PSW2 $(comment "${comment_l}") -p udp -i lo -j RETURN
|
||||
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT !) -p udp -j PSW2_OUTPUT"
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
$ip6t_m -A PSW2_OUTPUT -p udp -d $FAKE_IP_6 -j PSW2_RULE
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2_OUTPUT -p udp" "-j PSW2_RULE" $UDP_REDIR_PORTS
|
||||
add_port_rules "$ip6t_m -A PSW2_OUTPUT -p udp" $UDP_REDIR_PORTS "-j PSW2_RULE"
|
||||
$ip6t_m -A PSW2 $(comment "${comment_l}") -p udp -i lo $(REDIRECT $REDIR_PORT TPROXY)
|
||||
$ip6t_m -A PSW2 $(comment "${comment_l}") -p udp -i lo -j RETURN
|
||||
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) $(dst $IPSET_DIRECT6 !) -p udp -j PSW2_OUTPUT"
|
||||
}
|
||||
|
||||
[ -d "${TMP_IFACE_PATH}" ] && {
|
||||
for iface in $(ls ${TMP_IFACE_PATH}); do
|
||||
$ipt_n -A PSW2_OUTPUT -o $iface -p udp -j RETURN
|
||||
$ipt_m -A PSW2_OUTPUT -o $iface -p udp -j RETURN
|
||||
done
|
||||
}
|
||||
fi
|
||||
|
||||
$ipt_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
|
||||
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN"
|
||||
|
||||
$ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
|
||||
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN"
|
||||
|
||||
$ipt_m -A PSW2 -p tcp --dport 53 -j ACCEPT
|
||||
$ipt_m -A PSW2 -p udp --dport 53 -j ACCEPT
|
||||
$ip6t_m -A PSW2 -p tcp --dport 53 -j ACCEPT
|
||||
$ip6t_m -A PSW2 -p udp --dport 53 -j ACCEPT
|
||||
}
|
||||
|
||||
load_acl
|
||||
|
||||
filter_direct_node_list > /dev/null 2>&1 &
|
||||
@@ -1062,7 +944,7 @@ start() {
|
||||
stop() {
|
||||
[ -z "$(command -v log_i18n)" ] && . "$UTILS_PATH"
|
||||
del_firewall_rule
|
||||
[ $(config_t_get global flush_set "0") = "1" ] && {
|
||||
[ $(config_n_get @global[0] flush_set "0") = "1" ] && {
|
||||
uci -q delete ${CONFIG}.@global[0].flush_set
|
||||
uci -q commit ${CONFIG}
|
||||
flush_ipset
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
. /usr/share/passwall2/utils.sh
|
||||
LOCK_FILE=${LOCK_PATH}/${CONFIG}_monitor.lock
|
||||
|
||||
ENABLED=$(config_t_get global enabled 0)
|
||||
ENABLED=$(config_n_get @global[0] enabled 0)
|
||||
[ "$ENABLED" != 1 ] && return 1
|
||||
ENABLED=$(config_t_get global_delay start_daemon 0)
|
||||
ENABLED=$(config_n_get @global_delay[0] start_daemon 0)
|
||||
[ "$ENABLED" != 1 ] && return 1
|
||||
sleep 58s
|
||||
while [ "$ENABLED" -eq 1 ]; do
|
||||
|
||||
@@ -252,7 +252,7 @@ gen_shunt_list() {
|
||||
[ -n "$_geoip_code" ] && {
|
||||
get_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $nftset_v4 "0"
|
||||
get_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $nftset_v6 "0"
|
||||
log 1 "$(i18n "parse the traffic splitting rules[%s]-[geoip:%s] add to %s to complete." "${shunt_id}" "${_geoip_code}" "NFTSET")"
|
||||
#log 3 "$(i18n "parse the traffic splitting rules[%s]-[geoip:%s] add to %s to complete." "${shunt_id}" "${_geoip_code}" "NFTSET[${nftset_v4},${nftset_v6}]")"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,6 +271,7 @@ gen_shunt_list() {
|
||||
}
|
||||
[ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\"
|
||||
[ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\"
|
||||
set_cache_var "${node}_gen_shunt_list" "1"
|
||||
}
|
||||
|
||||
add_shunt_t_rule() {
|
||||
@@ -293,45 +294,18 @@ add_shunt_t_rule() {
|
||||
}
|
||||
|
||||
load_acl() {
|
||||
[ "$ENABLED_ACLS" == 1 ] && {
|
||||
log_i18n 1 "Access Control:"
|
||||
acl_app
|
||||
for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do
|
||||
eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-)
|
||||
acl_json=$(lua $APP_PATH/app_acl.lua)
|
||||
acl_node
|
||||
log_i18n 1 "Access Control:"
|
||||
for sid in $(jsonfilter -s "${acl_json}" -e '$.acl[*].flag'); do
|
||||
eval $(cat "${TMP_ACL_PATH}/${sid}/var")
|
||||
|
||||
mode=${mode:-0}
|
||||
tcp_no_redir_ports=${tcp_no_redir_ports:-default}
|
||||
udp_no_redir_ports=${udp_no_redir_ports:-default}
|
||||
tcp_proxy_mode="global"
|
||||
udp_proxy_mode="global"
|
||||
tcp_redir_ports=${tcp_redir_ports:-default}
|
||||
udp_redir_ports=${udp_redir_ports:-default}
|
||||
node=${node:-default}
|
||||
[ "$mode" = "0" ] && {
|
||||
tcp_no_redir_ports="1:65535"
|
||||
udp_no_redir_ports="1:65535"
|
||||
}
|
||||
[ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS
|
||||
[ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS
|
||||
[ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS
|
||||
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
|
||||
[ -z "$(get_cache_var "${node}_gen_shunt_list")" ] && [ -n "${node}" ] && gen_shunt_list "${node}" shunt_list4 shunt_list6
|
||||
[ -n "${use}" ] && local dns_redirect_port=$(get_cache_var "ACL_${use}_dns_port")
|
||||
|
||||
[ -n "$(get_cache_var "ACL_${sid}_node")" ] && node=$(get_cache_var "ACL_${sid}_node")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_redir_port")" ] && redir_port=$(get_cache_var "ACL_${sid}_redir_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
|
||||
[ -n "$node" ] && node_remark=$(config_n_get $node remarks)
|
||||
|
||||
if [ -n "$(get_cache_var "ACL_${sid}_default")" ]; then
|
||||
shunt_list4=${SHUNT_LIST4}
|
||||
shunt_list6=${SHUNT_LIST6}
|
||||
else
|
||||
# Shunt rules IP list (import when use shunt node)
|
||||
gen_shunt_list "${node}" shunt_list4 shunt_list6
|
||||
fi
|
||||
|
||||
_acl_list=${TMP_ACL_PATH}/${sid}/source_list
|
||||
|
||||
for i in $(cat $_acl_list); do
|
||||
[ "${client_proxy}" = "1" ] && {
|
||||
msg1="$(i18n "[%s]," "${remarks}")"
|
||||
for i in $(cat ${TMP_ACL_PATH}/${sid}/source_list); do
|
||||
local _ipt_source _ipv4
|
||||
local msg
|
||||
if [ -n "${interface}" ]; then
|
||||
@@ -375,40 +349,38 @@ load_acl() {
|
||||
else
|
||||
continue
|
||||
fi
|
||||
msg="$(i18n "[%s]," "${remarks}")${msg}"
|
||||
msg="${msg1}${msg}"
|
||||
|
||||
[ "$tcp_no_redir_ports" != "disable" ] && {
|
||||
[ -n "$tcp_no_redir_ports" ] && {
|
||||
if ! has_1_65535 "$tcp_no_redir_ports"; then
|
||||
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
|
||||
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ${_ipt_source} meta l4proto tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${tcp_no_redir_ports}")"
|
||||
else
|
||||
# It will return when it ends, so no extra rules are needed.
|
||||
tcp_proxy_mode="disable"
|
||||
no_tcp_proxy="1"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
|
||||
fi
|
||||
}
|
||||
|
||||
[ "$udp_no_redir_ports" != "disable" ] && {
|
||||
[ -n "$udp_no_redir_ports" ] && {
|
||||
if ! has_1_65535 "$udp_no_redir_ports"; then
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\""
|
||||
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" 2>/dev/null
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${udp_no_redir_ports}")"
|
||||
else
|
||||
# It will return when it ends, so no extra rules are needed.
|
||||
udp_proxy_mode="disable"
|
||||
no_udp_proxy="1"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
|
||||
fi
|
||||
}
|
||||
|
||||
if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$dns_redirect_port" ]; then
|
||||
[ -n "$dns_redirect_port" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
|
||||
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && log 2 "${msg}$(i18n "Using a node that is different from the global configuration, DNS has been forcibly redirected to a dedicated DNS server.")"
|
||||
}
|
||||
if ([ -z "$no_tcp_proxy" ] || [ -z "$no_udp_proxy" ]) && [ -n "$dns_redirect_port" ]; then
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
|
||||
log 2 "${msg}$(i18n "DNS will redirected to the dedicated DNS server [%s]." "${dns_redirect_port}")"
|
||||
else
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
|
||||
@@ -416,8 +388,8 @@ load_acl() {
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
|
||||
fi
|
||||
|
||||
[ "$tcp_proxy_mode" != "disable" ] && [ -n "$redir_port" ] && {
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remark}")"
|
||||
[ -z "$no_tcp_proxy" ] && [ -n "$redir_port" ] && {
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remarks}")"
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
msg2="${msg2}(TPROXY:${redir_port})"
|
||||
nft_chain="PSW2_MANGLE"
|
||||
@@ -458,8 +430,8 @@ load_acl() {
|
||||
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp ${_ipt_source} counter return comment \"$remarks\""
|
||||
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} counter return comment \"$remarks\"" 2>/dev/null
|
||||
|
||||
[ "$udp_proxy_mode" != "disable" ] && [ -n "$redir_port" ] && {
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remark}")(TPROXY:${redir_port})"
|
||||
[ -z "$no_tcp_proxy" ] && [ -n "$redir_port" ] && {
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remarks}")(TPROXY:${redir_port})"
|
||||
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} ip daddr $FAKE_IP counter jump PSW2_RULE comment \"$remarks\""
|
||||
add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip daddr" "counter jump PSW2_RULE" "$remarks"
|
||||
@@ -476,108 +448,140 @@ load_acl() {
|
||||
}
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} counter return comment \"$remarks\""
|
||||
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} counter return comment \"$remarks\"" 2>/dev/null
|
||||
unset nft_chain nft_j _ipt_source msg msg2 _ipv4
|
||||
unset nft_chain nft_j _ipt_source msg msg2 _ipv4 no_tcp_proxy no_udp_proxy
|
||||
done
|
||||
unset enabled sid remarks sources tcp_proxy_mode udp_proxy_mode tcp_no_redir_ports udp_no_redir_ports tcp_redir_ports udp_redir_ports node interface
|
||||
unset redir_port node_remark _acl_list
|
||||
done
|
||||
}
|
||||
|
||||
[ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ] && {
|
||||
local comment="$(i18n "Default")"
|
||||
msg="$(i18n "[%s]," ${comment})"
|
||||
|
||||
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"${comment}\""
|
||||
if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${TCP_NO_REDIR_PORTS}")"
|
||||
else
|
||||
TCP_PROXY_MODE="disable"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
|
||||
fi
|
||||
unset msg1
|
||||
}
|
||||
[ "${local_proxy}" = "1" ] && {
|
||||
msg="$(i18n "[Local],")"
|
||||
[ -n "$tcp_no_redir_ports" ] && {
|
||||
nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $tcp_no_redir_ports "tcp dport") counter return"
|
||||
if ! has_1_65535 "$tcp_no_redir_ports"; then
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${tcp_no_redir_ports}")"
|
||||
else
|
||||
no_tcp_local_proxy="1"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
|
||||
fi
|
||||
}
|
||||
[ -n "$udp_no_redir_ports" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $udp_no_redir_ports "udp dport") counter return"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $udp_no_redir_ports "udp dport") counter return"
|
||||
if ! has_1_65535 "$udp_no_redir_ports"; then
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${udp_no_redir_ports}")"
|
||||
else
|
||||
no_udp_local_proxy="1"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
|
||||
fi
|
||||
}
|
||||
|
||||
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return comment \"${comment}\""
|
||||
if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
|
||||
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${UDP_NO_REDIR_PORTS}")"
|
||||
else
|
||||
UDP_PROXY_MODE="disable"
|
||||
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
|
||||
if [ -n "$node" ] && ([ -z "$no_tcp_local_proxy" ] || [ -z "$no_udp_local_proxy" ]); then
|
||||
[ -n "$dns_redirect_port" ] && {
|
||||
nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$dns_redirect_port comment \"PSW2_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$dns_redirect_port comment \"PSW2_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$dns_redirect_port comment \"PSW2_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$dns_redirect_port comment \"PSW2_DNS\""
|
||||
log 2 "${msg}$(i18n "DNS will redirected to the dedicated DNS server [%s]." "${dns_redirect_port}")"
|
||||
}
|
||||
fi
|
||||
|
||||
local comment_l="$(i18n "Local")"
|
||||
|
||||
# Loading local router proxy TCP
|
||||
if [ -n "$node" ] && [ -z "$no_tcp_local_proxy" ]; then
|
||||
[ "$accept_icmp" = "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr $FAKE_IP counter redirect"
|
||||
add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr" "counter redirect"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp counter redirect"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp counter return"
|
||||
}
|
||||
|
||||
[ "$accept_icmpv6" = "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 counter redirect"
|
||||
add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr" "counter redirect"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 counter redirect"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 counter return"
|
||||
}
|
||||
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remarks}")"
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
msg2="${msg2}(TPROXY:${redir_port})"
|
||||
nft_chain="PSW2_OUTPUT_MANGLE"
|
||||
nft_j="counter jump PSW2_RULE"
|
||||
else
|
||||
msg2="${msg2}(REDIRECT:${redir_port})"
|
||||
nft_chain="PSW2_OUTPUT_NAT"
|
||||
nft_j="$(REDIRECT $redir_port)"
|
||||
fi
|
||||
|
||||
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr $FAKE_IP ${nft_j}"
|
||||
add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $tcp_redir_ports "tcp dport") ip daddr" "${nft_j}"
|
||||
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $tcp_redir_ports "tcp dport") ${nft_j}"
|
||||
[ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME nat_output ip daddr != @$NFTSET_DIRECT ip protocol tcp counter jump PSW2_OUTPUT_NAT"
|
||||
[ -n "${is_tproxy}" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp iif lo $(REDIRECT $redir_port TPROXY4) comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp iif lo counter return comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT ip protocol tcp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\""
|
||||
}
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 jump PSW2_RULE"
|
||||
add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $tcp_redir_ports "tcp dport") ip6 daddr" "counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $tcp_redir_ports "tcp dport") counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo $(REDIRECT $redir_port TPROXY6) comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo counter return comment \"${comment_l}\""
|
||||
}
|
||||
|
||||
[ -d "${TMP_IFACE_PATH}" ] && {
|
||||
for iface in $(ls ${TMP_IFACE_PATH}); do
|
||||
nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp oif $iface counter return"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol tcp oif $iface counter return"
|
||||
done
|
||||
}
|
||||
log 2 "${msg2}"
|
||||
fi
|
||||
|
||||
# Loading local router proxy UDP
|
||||
if [ -n "$node" ] && [ -z "$no_udp_local_proxy" ]; then
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remarks}")(TPROXY:${redir_port})"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE"
|
||||
add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $udp_redir_ports "udp dport") ip daddr" "counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $udp_redir_ports "udp dport") counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo $(REDIRECT $redir_port TPROXY4) comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo counter return comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT ip protocol udp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\""
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 jump PSW2_RULE"
|
||||
add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $udp_redir_ports "udp dport") ip6 daddr" "counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $udp_redir_ports "udp dport") counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo $(REDIRECT $redir_port TPROXY6) comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo counter return comment \"${comment_l}\""
|
||||
}
|
||||
|
||||
[ -d "${TMP_IFACE_PATH}" ] && {
|
||||
for iface in $(ls ${TMP_IFACE_PATH}); do
|
||||
nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol udp oif $iface counter return"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol udp oif $iface counter return"
|
||||
done
|
||||
}
|
||||
|
||||
log 2 "${msg2}"
|
||||
fi
|
||||
|
||||
nft "add rule $NFTABLE_NAME mangle_output oif lo counter return comment \"PSW2_OUTPUT_MANGLE\""
|
||||
nft "add rule $NFTABLE_NAME mangle_output meta mark ${FWMARK} counter return comment \"PSW2_OUTPUT_MANGLE\""
|
||||
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp udp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
|
||||
|
||||
unset msg msg2 comment_l
|
||||
}
|
||||
|
||||
if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ -n "$NODE" ]; then
|
||||
[ -n "$DNS_REDIRECT_PORT" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"${comment}\""
|
||||
}
|
||||
fi
|
||||
|
||||
if [ "$TCP_PROXY_MODE" != "disable" ] && [ -n "$NODE" ]; then
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "$(config_n_get $NODE remarks)")"
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
msg2="${msg2}(TPROXY:${REDIR_PORT})"
|
||||
nft_chain="PSW2_MANGLE"
|
||||
nft_j="counter jump PSW2_RULE"
|
||||
else
|
||||
msg2="${msg2}(REDIRECT:${REDIR_PORT})"
|
||||
nft_chain="PSW2_NAT"
|
||||
nft_j="$(REDIRECT $REDIR_PORT)"
|
||||
fi
|
||||
|
||||
[ "$accept_icmp" = "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ip daddr $FAKE_IP $(REDIRECT) comment \"${comment}\""
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ip daddr" "$(REDIRECT)" "${comment}"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp $(REDIRECT) comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp return comment \"${comment}\""
|
||||
}
|
||||
|
||||
[ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"${comment}\""
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr" "$(REDIRECT)" "${comment}"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 $(REDIRECT) comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 return comment \"${comment}\""
|
||||
}
|
||||
|
||||
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr $FAKE_IP ${nft_j} comment \"${comment}\""
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip daddr" "${nft_j}" "${comment}"
|
||||
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ${nft_j} comment \"${comment}\""
|
||||
[ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp $(REDIRECT $REDIR_PORT TPROXY4) comment \"${comment}\""
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 jump PSW2_RULE comment \"${comment}\""
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr" "${nft_j}" "${comment}"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") counter jump PSW2_RULE comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(REDIRECT $REDIR_PORT TPROXY) comment \"${comment}\""
|
||||
}
|
||||
|
||||
log 2 "${msg2}"
|
||||
fi
|
||||
|
||||
if [ "$UDP_PROXY_MODE" != "disable" ] && [ -n "$NODE" ]; then
|
||||
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "$(config_n_get $NODE remarks)")(TPROXY:${REDIR_PORT})"
|
||||
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE comment \"${comment}\""
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") ip daddr" "counter jump PSW2_RULE" "${comment}"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(REDIRECT $REDIR_PORT TPROXY4) comment \"${comment}\""
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 jump PSW2_RULE comment \"${comment}\""
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr" "counter jump PSW2_RULE" "${comment}"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE comment \"${comment}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(REDIRECT $REDIR_PORT TPROXY) comment \"${comment}\""
|
||||
}
|
||||
|
||||
log 2 "${msg2}"
|
||||
udp_flag=1
|
||||
fi
|
||||
}
|
||||
unset dns_redirect_port
|
||||
unset $(cat "${TMP_ACL_PATH}/${sid}/var" | awk -F '=' '{print $1}' | tr "\n" " ")
|
||||
done
|
||||
}
|
||||
|
||||
filter_haproxy() {
|
||||
@@ -746,9 +750,6 @@ add_firewall_rule() {
|
||||
done
|
||||
}
|
||||
|
||||
# Shunt rules IP list (import when use shunt node)
|
||||
gen_shunt_list "${NODE}" SHUNT_LIST4 SHUNT_LIST6
|
||||
|
||||
# Filter all node IPs
|
||||
filter_vpsip > /dev/null 2>&1 &
|
||||
filter_haproxy > /dev/null 2>&1 &
|
||||
@@ -756,8 +757,8 @@ add_firewall_rule() {
|
||||
filter_vps_addr $(config_n_get $NODE address) > /dev/null 2>&1 &
|
||||
filter_vps_addr $(config_n_get $NODE download_address) > /dev/null 2>&1 &
|
||||
|
||||
accept_icmp=$(config_t_get global_forwarding accept_icmp 0)
|
||||
accept_icmpv6=$(config_t_get global_forwarding accept_icmpv6 0)
|
||||
accept_icmp=$(config_n_get @global_forwarding[0] accept_icmp 0)
|
||||
accept_icmpv6=$(config_n_get @global_forwarding[0] accept_icmpv6 0)
|
||||
|
||||
if [ "${TCP_PROXY_WAY}" = "redirect" ]; then
|
||||
unset is_tproxy
|
||||
@@ -771,7 +772,7 @@ add_firewall_rule() {
|
||||
|
||||
nft "add chain $NFTABLE_NAME PSW2_DNS"
|
||||
nft "flush chain $NFTABLE_NAME PSW2_DNS"
|
||||
if [ $(config_t_get global dns_redirect "1") = "0" ]; then
|
||||
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
|
||||
#Only hijack when dest address is local IP
|
||||
nft "insert rule $NFTABLE_NAME dstnat ip saddr @${NFTSET_DIRECT} ip daddr @${NFTSET_LOCAL} jump PSW2_DNS"
|
||||
nft "insert rule $NFTABLE_NAME dstnat ip6 saddr @${NFTSET_DIRECT6} ip6 daddr @${NFTSET_LOCAL6} jump PSW2_DNS"
|
||||
@@ -881,128 +882,6 @@ add_firewall_rule() {
|
||||
ip -6 route add local ::/0 dev lo table 999
|
||||
}
|
||||
|
||||
[ "$ENABLED_DEFAULT_ACL" == 1 ] && {
|
||||
TCP_LOCALHOST_PROXY=$LOCALHOST_PROXY
|
||||
UDP_LOCALHOST_PROXY=$LOCALHOST_PROXY
|
||||
|
||||
msg="$(i18n "[Local],")"
|
||||
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return"
|
||||
if ! has_1_65535 "$TCP_NO_REDIR_PORTS"; then
|
||||
log 1 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${TCP_NO_REDIR_PORTS}")"
|
||||
else
|
||||
unset TCP_LOCALHOST_PROXY
|
||||
log 1 "${msg}$(i18n "not proxy all %s" "TCP")"
|
||||
fi
|
||||
}
|
||||
|
||||
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return"
|
||||
if ! has_1_65535 "$UDP_NO_REDIR_PORTS"; then
|
||||
log 1 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${UDP_NO_REDIR_PORTS}")"
|
||||
else
|
||||
unset UDP_LOCALHOST_PROXY
|
||||
log 1 "${msg}$(i18n "not proxy all %s" "UDP")"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -n "$NODE" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then
|
||||
[ -n "$DNS_REDIRECT_PORT" ] && {
|
||||
nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2_DNS\""
|
||||
}
|
||||
fi
|
||||
|
||||
local comment_l="$(i18n "Local")"
|
||||
|
||||
# Loading local router proxy TCP
|
||||
if [ -n "$NODE" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
|
||||
[ "$accept_icmp" = "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr $FAKE_IP counter redirect"
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr" "counter redirect"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp counter redirect"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp counter return"
|
||||
}
|
||||
|
||||
[ "$accept_icmpv6" = "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 counter redirect"
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr" "counter redirect"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 counter redirect"
|
||||
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 counter return"
|
||||
}
|
||||
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
nft_chain="PSW2_OUTPUT_MANGLE"
|
||||
nft_j="counter jump PSW2_RULE"
|
||||
else
|
||||
nft_chain="PSW2_OUTPUT_NAT"
|
||||
nft_j="$(REDIRECT $REDIR_PORT)"
|
||||
fi
|
||||
|
||||
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr $FAKE_IP ${nft_j}"
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip daddr" "${nft_j}"
|
||||
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ${nft_j}"
|
||||
[ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME nat_output ip daddr != @$NFTSET_DIRECT ip protocol tcp counter jump PSW2_OUTPUT_NAT"
|
||||
[ -n "${is_tproxy}" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp iif lo $(REDIRECT $REDIR_PORT TPROXY4) comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp iif lo counter return comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT ip protocol tcp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\""
|
||||
}
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 jump PSW2_RULE"
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr" "counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo $(REDIRECT $REDIR_PORT TPROXY6) comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo counter return comment \"${comment_l}\""
|
||||
}
|
||||
|
||||
[ -d "${TMP_IFACE_PATH}" ] && {
|
||||
for iface in $(ls ${TMP_IFACE_PATH}); do
|
||||
nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp oif $iface counter return"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol tcp oif $iface counter return"
|
||||
done
|
||||
}
|
||||
fi
|
||||
|
||||
# Loading local router proxy UDP
|
||||
if [ -n "$NODE" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE"
|
||||
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") ip daddr" "counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo $(REDIRECT $REDIR_PORT TPROXY4) comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo counter return comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT ip protocol udp counter jump PSW2_OUTPUT_MANGLE comment \"PSW2_OUTPUT_MANGLE\""
|
||||
|
||||
[ "$PROXY_IPV6" == "1" ] && {
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 jump PSW2_RULE"
|
||||
add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr" "counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo $(REDIRECT $REDIR_PORT TPROXY6) comment \"${comment_l}\""
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo counter return comment \"${comment_l}\""
|
||||
}
|
||||
|
||||
[ -d "${TMP_IFACE_PATH}" ] && {
|
||||
for iface in $(ls ${TMP_IFACE_PATH}); do
|
||||
nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol udp oif $iface counter return"
|
||||
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip protocol udp oif $iface counter return"
|
||||
done
|
||||
}
|
||||
fi
|
||||
|
||||
nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT oif lo counter return comment \"PSW2_OUTPUT_MANGLE\""
|
||||
nft "add rule $NFTABLE_NAME mangle_output ip daddr != @$NFTSET_DIRECT meta mark ${FWMARK} counter return comment \"PSW2_OUTPUT_MANGLE\""
|
||||
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp udp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
|
||||
}
|
||||
|
||||
load_acl
|
||||
|
||||
filter_direct_node_list > /dev/null 2>&1 &
|
||||
@@ -1093,7 +972,7 @@ start() {
|
||||
stop() {
|
||||
[ -z "$(command -v log_i18n)" ] && . "$UTILS_PATH"
|
||||
del_firewall_rule
|
||||
[ $(config_t_get global flush_set "0") = "1" ] && {
|
||||
[ $(config_n_get @global[0] flush_set "0") = "1" ] && {
|
||||
uci -q delete ${CONFIG}.@global[0].flush_set
|
||||
uci -q commit ${CONFIG}
|
||||
#flush_table
|
||||
|
||||
@@ -75,7 +75,7 @@ test_node() {
|
||||
local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
|
||||
[ -n "${_type}" ] && {
|
||||
check_process
|
||||
local _tmp_port=$(get_new_port 48800 tcp,udp)
|
||||
local _tmp_port=$(get_new_port 48800)
|
||||
NO_REC_PROCESS=1 $APP_FILE run_socks flag="test_node_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=test_node_${node_id}.json
|
||||
sleep 2s
|
||||
local curlx="socks5h://127.0.0.1:${_tmp_port}"
|
||||
|
||||
@@ -29,7 +29,6 @@ local has_ss_rust = api.is_finded("sslocal")
|
||||
local has_ssr = api.is_finded("ssr-local") and api.is_finded("ssr-redir")
|
||||
local has_singbox = api.finded_com("sing-box")
|
||||
local has_xray = api.finded_com("xray")
|
||||
local has_hysteria2 = api.finded_com("hysteria")
|
||||
local DEFAULT_ALLOWINSECURE = true
|
||||
local DEFAULT_FILTER_KEYWORD_MODE = uci_get("@global_subscribe[0]", "filter_keyword_mode") or "0"
|
||||
local DEFAULT_FILTER_KEYWORD_DISCARD_LIST = uci_get("@global_subscribe[0]", "filter_discard_list") or {}
|
||||
@@ -39,12 +38,11 @@ local DEFAULT_SS_TYPE = api.get_core("ss_type", {{has_ss_rust,"shadowsocks-rust"
|
||||
local DEFAULT_TROJAN_TYPE = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local DEFAULT_VMESS_TYPE = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local DEFAULT_VLESS_TYPE = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
|
||||
local DEFAULT_HYSTERIA2_TYPE = api.get_core("hysteria2_type", {{has_hysteria2,"hysteria2"},{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local DEFAULT_HYSTERIA2_TYPE = api.get_core("hysteria2_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local core_has = {
|
||||
["xray"] = has_xray,
|
||||
["sing-box"] = has_singbox,
|
||||
["shadowsocks-rust"] = has_ss_rust,
|
||||
["hysteria2"] = has_hysteria2
|
||||
}
|
||||
-- Determine whether to filter node keywords
|
||||
local function is_filter_keyword(sub_cfg, value)
|
||||
@@ -1771,15 +1769,6 @@ local function processData(szType, content, add_mode, group, sub_cfg)
|
||||
result.protocol = "hysteria2"
|
||||
result.use_finalmask = (params.fm and params.fm ~= "") and "1" or nil
|
||||
result.finalmask = (params.fm and params.fm ~= "") and api.base64Encode(params.fm) or nil
|
||||
elseif has_hysteria2 then
|
||||
result.type = "Hysteria2"
|
||||
for k1, v1 in pairs(result) do
|
||||
if k1:find("hysteria2_") == 1 then
|
||||
local s = split(k1, "hysteria2_")
|
||||
result[s[2]] = v1
|
||||
result[k1] = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", "Hysteria2", "Hysteria2"))
|
||||
return nil
|
||||
|
||||
@@ -17,8 +17,8 @@ do
|
||||
|
||||
if [ "$CFG_UPDATE_INT" -ne 0 ]; then
|
||||
|
||||
restart_week_mode=$(config_t_get global_delay restart_week_mode)
|
||||
restart_interval_mode=$(config_t_get global_delay restart_interval_mode)
|
||||
restart_week_mode=$(config_n_get @global_delay[0] restart_week_mode)
|
||||
restart_interval_mode=$(config_n_get @global_delay[0] restart_interval_mode)
|
||||
restart_interval_mode=$(expr "$restart_interval_mode" \* 60)
|
||||
if [ -n "$restart_week_mode" ]; then
|
||||
[ "$restart_week_mode" = "8" ] && {
|
||||
@@ -26,8 +26,8 @@ do
|
||||
}
|
||||
fi
|
||||
|
||||
rules_update_week_mode=$(config_t_get global_rules update_week_mode)
|
||||
rules_update_interval_mode=$(config_t_get global_rules update_interval_mode)
|
||||
rules_update_week_mode=$(config_n_get @global_rules[0] update_week_mode)
|
||||
rules_update_interval_mode=$(config_n_get @global_rules[0] update_interval_mode)
|
||||
rules_update_interval_mode=$(expr "$rules_update_interval_mode" \* 60)
|
||||
if [ -n "$rules_update_week_mode" ]; then
|
||||
[ "$rules_update_week_mode" = "8" ] && {
|
||||
|
||||
@@ -46,11 +46,11 @@ url_test_node() {
|
||||
local node_id=$1
|
||||
local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
|
||||
[ -n "${_type}" ] && {
|
||||
local _tmp_port=$(get_new_port 48900 tcp,udp)
|
||||
local _tmp_port=$(get_new_port 48900)
|
||||
NO_REC_PROCESS=1 /usr/share/${CONFIG}/app.sh run_socks flag="url_test_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=url_test_${node_id}.json
|
||||
sleep 2s
|
||||
local curlx="socks5h://127.0.0.1:${_tmp_port}"
|
||||
local probeUrl=$(config_t_get global_other url_test_url https://www.google.com/generate_204)
|
||||
local probeUrl=$(config_n_get @global_other[0] url_test_url https://www.google.com/generate_204)
|
||||
result=$(curl --connect-timeout 3 --max-time 5 -o /dev/null -I -skL -w "%{http_code}:%{time_pretransfer}" -x ${curlx} "${probeUrl}")
|
||||
# End the SS plugin process
|
||||
local pid_file="${TMP_PATH}/url_test_${node_id}_plugin.pid"
|
||||
|
||||
@@ -33,11 +33,6 @@ config_t_get() {
|
||||
echo "${ret:=${3}}"
|
||||
}
|
||||
|
||||
config_t_set() {
|
||||
local index=${4:-0}
|
||||
local ret=$(uci -q set "${CONFIG}.@${1}[${index}].${2}=${3}" 2>/dev/null)
|
||||
}
|
||||
|
||||
eval_set_val() {
|
||||
for i in $@; do
|
||||
for j in $i; do
|
||||
@@ -157,9 +152,9 @@ get_geoip() {
|
||||
local geoip_type_flag=""
|
||||
local output_path="${geo_output_path}/geoip-${geoip_code}-$2"
|
||||
[ ! -s "${output_path}" ] && {
|
||||
local geoip_path="$(config_t_get global_rules v2ray_location_asset)"
|
||||
local geoip_path="$(config_n_get @global_rules[0] v2ray_location_asset)"
|
||||
geoip_path="${geoip_path%*/}/geoip.dat"
|
||||
local bin="$(first_type $(config_t_get global_app geoview_file) geoview)"
|
||||
local bin="$(first_type $(config_n_get @global_app[0] geoview_file) geoview)"
|
||||
[ -n "$bin" ] && [ -s "$geoip_path" ] || { echo ""; return; }
|
||||
case "$2" in
|
||||
"ipv4") geoip_type_flag="-ipv6=false" ;;
|
||||
@@ -299,7 +294,7 @@ get_new_port() {
|
||||
local default_start_port=2001
|
||||
local min_port=1025
|
||||
local max_port=49151
|
||||
local port=$1
|
||||
local port=$1 #Required parameter; please pass "auto" if you want it to be automatic.
|
||||
local last_get_new_port_auto
|
||||
if [ "$1" == "auto" ]; then
|
||||
last_get_new_port_auto=$(get_cache_var "last_get_new_port_auto")
|
||||
@@ -313,17 +308,28 @@ get_new_port() {
|
||||
[ "$port" -lt $min_port -o "$port" -gt $max_port ] && port=$default_start_port
|
||||
local protocol=$(echo $2 | tr 'A-Z' 'a-z')
|
||||
local result=$(check_port_exists $port $protocol)
|
||||
[ -n "$(get_cache_var "get_port_${port}")" ] && {
|
||||
# exist, continue get.
|
||||
# Make the following result logic true.
|
||||
result=1
|
||||
}
|
||||
if [ "$result" != 0 ]; then
|
||||
local temp=
|
||||
if [ "$port" -lt $max_port ]; then
|
||||
# If the port is smaller than the maximum port, then increment by 1 and continue.
|
||||
temp=$(expr $port + 1)
|
||||
elif [ "$port" -gt $min_port ]; then
|
||||
# If the port is greater than the minimum port, then decrement by 1 and continue.
|
||||
temp=$(expr $port - 1)
|
||||
else
|
||||
# Otherwise, reassign the default starting port.
|
||||
temp=$default_start_port
|
||||
fi
|
||||
# Recursion, until it obtains an unused port.
|
||||
get_new_port $temp $protocol
|
||||
else
|
||||
# Set cache, mark this port as already obtained, so it should not be obtained again.
|
||||
set_cache_var "get_port_${port}" "1"
|
||||
[ "$1" == "auto" ] && set_cache_var "last_get_new_port_auto" "$port"
|
||||
echo $port
|
||||
fi
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.1.8-r1
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.2.0-r1
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for shadowrt
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2022 jjm2473@gmail.com
|
||||
|
||||
DEFAULT_OVERLAY_FS="ext4"
|
||||
OVERLAY_LABEL="etc"
|
||||
|
||||
OVERLAY_FS=${DEFAULT_OVERLAY_FS}
|
||||
OVERLAY_DEV=
|
||||
|
||||
log() {
|
||||
echo "$1" >&2
|
||||
}
|
||||
|
||||
inlog() {
|
||||
$@ >&2
|
||||
}
|
||||
|
||||
. /lib/functions/istoreos-boot.sh
|
||||
|
||||
CONFIRM=n
|
||||
REBOOT=n
|
||||
|
||||
confirm()
|
||||
{
|
||||
[ "$1" = "y" ] && return 0
|
||||
echo "This will erase all settings and remove any installed packages. Are you sure? [N/y]"
|
||||
read CONFIRM
|
||||
[ "$CONFIRM" = "y" -o "$CONFIRM" = "Y" ] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
do_reset_nofs()
|
||||
{
|
||||
get_overlay_partition || exit 1
|
||||
|
||||
if [ -z "$OVERLAY_DEV" ]; then
|
||||
echo "Unable to determine overlay partition" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "RESET" = "$FSTYPE" ]; then
|
||||
echo "Already resetted" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "DIR" = "$FSTYPE" ]; then
|
||||
touch /$OVERLAY_DEV/.reset
|
||||
sync /$OVERLAY_DEV
|
||||
return 0
|
||||
fi
|
||||
# if ! blkid -o device -t LABEL=$OVERLAY_LABEL "$OVERLAY_DEV" >/dev/null; then
|
||||
# echo "Overlay partition $OVERLAY_DEV not labeled $OVERLAY_LABEL" >&2
|
||||
# return 1
|
||||
# fi
|
||||
|
||||
echo "RESET000" | dd of="$OVERLAY_DEV" bs=512 count=1 conv=notrunc,sync,fsync 2>/dev/null
|
||||
echo 3 > /proc/sys/vm/drop_caches
|
||||
return 0
|
||||
}
|
||||
|
||||
do_reset_ext_overlay()
|
||||
{
|
||||
[ -d /ext_overlay ] && mountpoint -q /ext_overlay || return 0
|
||||
rm -f /ext_overlay/etc/.extroot-uuid
|
||||
touch /ext_overlay/.reset
|
||||
sync /ext_overlay
|
||||
}
|
||||
|
||||
do_reset()
|
||||
{
|
||||
if [ -f /.recovery_mode ]; then
|
||||
mount_root || ( echo "/overlay mount failed!" ; exit 1 )
|
||||
rm -rf /overlay/upper
|
||||
mkdir /overlay/upper
|
||||
sync /overlay
|
||||
else
|
||||
do_reset_nofs
|
||||
do_reset_ext_overlay
|
||||
fi
|
||||
if [ -f /lib/upgrade/keep.d/grub ]; then
|
||||
cat /lib/upgrade/keep.d/grub | while read; do
|
||||
rm -f "$REPLY"
|
||||
done
|
||||
fi
|
||||
[ "$REBOOT" = "y" ] && reboot
|
||||
exit 0
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
key="$1"
|
||||
case $key in
|
||||
-y) CONFIRM=y ;;
|
||||
-r) REBOOT=y ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
confirm $CONFIRM && do_reset
|
||||
exit 0
|
||||
@@ -1,98 +1,3 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2022 jjm2473@gmail.com
|
||||
|
||||
DEFAULT_OVERLAY_FS="ext4"
|
||||
OVERLAY_LABEL="etc"
|
||||
|
||||
OVERLAY_FS=${DEFAULT_OVERLAY_FS}
|
||||
OVERLAY_DEV=
|
||||
|
||||
log() {
|
||||
echo "$1" >&2
|
||||
}
|
||||
|
||||
inlog() {
|
||||
$@ >&2
|
||||
}
|
||||
|
||||
. /lib/functions/istoreos-boot.sh
|
||||
|
||||
CONFIRM=n
|
||||
REBOOT=n
|
||||
|
||||
confirm()
|
||||
{
|
||||
[ "$1" = "y" ] && return 0
|
||||
echo "This will erase all settings and remove any installed packages. Are you sure? [N/y]"
|
||||
read CONFIRM
|
||||
[ "$CONFIRM" = "y" -o "$CONFIRM" = "Y" ] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
do_reset_nofs()
|
||||
{
|
||||
get_overlay_partition || exit 1
|
||||
|
||||
if [ -z "$OVERLAY_DEV" ]; then
|
||||
echo "Unable to determine overlay partition" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "RESET" = "$FSTYPE" ]; then
|
||||
echo "Already resetted" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "DIR" = "$FSTYPE" ]; then
|
||||
touch /$OVERLAY_DEV/.reset
|
||||
sync /$OVERLAY_DEV
|
||||
return 0
|
||||
fi
|
||||
# if ! blkid -o device -t LABEL=$OVERLAY_LABEL "$OVERLAY_DEV" >/dev/null; then
|
||||
# echo "Overlay partition $OVERLAY_DEV not labeled $OVERLAY_LABEL" >&2
|
||||
# return 1
|
||||
# fi
|
||||
|
||||
echo "RESET000" | dd of="$OVERLAY_DEV" bs=512 count=1 conv=notrunc,sync,fsync 2>/dev/null
|
||||
echo 3 > /proc/sys/vm/drop_caches
|
||||
return 0
|
||||
}
|
||||
|
||||
do_reset_ext_overlay()
|
||||
{
|
||||
[ -d /ext_overlay ] && mountpoint -q /ext_overlay || return 0
|
||||
rm -f /ext_overlay/etc/.extroot-uuid
|
||||
touch /ext_overlay/.reset
|
||||
sync /ext_overlay
|
||||
}
|
||||
|
||||
do_reset()
|
||||
{
|
||||
if [ -f /.recovery_mode ]; then
|
||||
mount_root || ( echo "/overlay mount failed!" ; exit 1 )
|
||||
rm -rf /overlay/upper
|
||||
mkdir /overlay/upper
|
||||
sync /overlay
|
||||
else
|
||||
do_reset_nofs
|
||||
do_reset_ext_overlay
|
||||
fi
|
||||
if [ -f /lib/upgrade/keep.d/grub ]; then
|
||||
cat /lib/upgrade/keep.d/grub | while read; do
|
||||
rm -f "$REPLY"
|
||||
done
|
||||
fi
|
||||
[ "$REBOOT" = "y" ] && reboot
|
||||
exit 0
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
key="$1"
|
||||
case $key in
|
||||
-y) CONFIRM=y ;;
|
||||
-r) REBOOT=y ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
confirm $CONFIRM && do_reset
|
||||
exit 0
|
||||
/sbin/factoryreset $@
|
||||
+96
-35
@@ -8,6 +8,13 @@ OVERLAY_LABEL="etc"
|
||||
OVERLAY_FS=${DEFAULT_OVERLAY_FS}
|
||||
OVERLAY_DEV=
|
||||
|
||||
APK=false
|
||||
PKG_BASE=usr/lib/opkg/info
|
||||
[ -s /etc/apk/arch ] && {
|
||||
APK=true
|
||||
PKG_BASE=lib/apk/packages
|
||||
}
|
||||
|
||||
log() {
|
||||
echo "<1>mount_root: $1" >/dev/kmsg
|
||||
}
|
||||
@@ -136,6 +143,28 @@ update_overlay_lower_uuid() {
|
||||
return 1
|
||||
}
|
||||
|
||||
OPENWRT_RELEASE=""
|
||||
openwrt_release() {
|
||||
if [ -z "$OPENWRT_RELEASE" ]; then
|
||||
OPENWRT_RELEASE=`grep 'DISTRIB_RELEASE=' /etc/openwrt_release 2>/dev/null | sed -E "s/.*='(.+)'.*/\1/"`
|
||||
[ -z "$OPENWRT_RELEASE" ] && OPENWRT_RELEASE="UNKNOWN"
|
||||
fi
|
||||
echo "$OPENWRT_RELEASE"
|
||||
}
|
||||
|
||||
update_overlay_lower_release() {
|
||||
local realrelease=`openwrt_release`
|
||||
local lastrelease="NULL"
|
||||
if [ -f "$1/.rootfs-release" ]; then
|
||||
lastrelease=`cat "$1/.rootfs-release"`
|
||||
fi
|
||||
if [ "$realrelease" != "$lastrelease" ]; then
|
||||
echo "$realrelease" >"$1/.rootfs-release"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
clean_overlayfs_origin() {
|
||||
local line
|
||||
cd "$1"
|
||||
@@ -172,11 +201,11 @@ clean_overlayfs_redundant_whiteout_marker()
|
||||
clean_overlayfs_redundant_whiteout_marker_luci()
|
||||
{
|
||||
local line
|
||||
[ -d "$1/upper/usr/lib/lua/luci" ] || return 0
|
||||
cd "$1/upper/usr/lib/lua"
|
||||
find luci -xdev -type c -perm 0 -user 0 -group 0 | while read; do
|
||||
[ -d "$1/upper/usr/lib/lua/luci" ] || [ -d "$1/upper/usr/share/luci/menu.d" ] || return 0
|
||||
cd "$1/upper"
|
||||
find usr/lib/lua/luci usr/share/luci/menu.d -xdev -type c -perm 0 -user 0 -group 0 | while read; do
|
||||
line="$REPLY"
|
||||
[ ! -e "/usr/lib/lua/$line" -a \( -z "$2" -o ! -e "$2/upper/usr/lib/lua/$line" \) ] && \
|
||||
[ ! -e "/$line" -a \( -z "$2" -o ! -e "$2/upper/$line" \) ] && \
|
||||
rm -f "$line"
|
||||
done
|
||||
cd - >/dev/null 2>&1
|
||||
@@ -193,28 +222,38 @@ clean_os_version_files()
|
||||
|
||||
nonconf_files_of_pkg() {
|
||||
local pkgname="$1"
|
||||
if [ -s /usr/lib/opkg/info/${pkgname}.conffiles ]; then
|
||||
grep -hvxFf /usr/lib/opkg/info/${pkgname}.conffiles \
|
||||
/usr/lib/opkg/info/${pkgname}.list
|
||||
if [ -s /$PKG_BASE/${pkgname}.conffiles ]; then
|
||||
grep -hvxFf /$PKG_BASE/${pkgname}.conffiles \
|
||||
/$PKG_BASE/${pkgname}.list
|
||||
else
|
||||
cat /usr/lib/opkg/info/${pkgname}.list
|
||||
cat /$PKG_BASE/${pkgname}.list
|
||||
fi
|
||||
}
|
||||
|
||||
_pkg_exists() {
|
||||
local pkgname="$1"
|
||||
if $APK; then
|
||||
[ -f "/$PKG_BASE/${pkgname}.list" ] && return 0
|
||||
else
|
||||
[ -f "/$PKG_BASE/${pkgname}.control" ] && return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
clean_pkg_content() {
|
||||
local overlay="$1"
|
||||
local pkgname="$2"
|
||||
local line
|
||||
|
||||
if [ -f /usr/lib/opkg/info/${pkgname}.control ]; then
|
||||
if [ -f /usr/lib/opkg/info/${pkgname}.list ]; then
|
||||
if _pkg_exists ${pkgname} ; then
|
||||
if [ -f /$PKG_BASE/${pkgname}.list ]; then
|
||||
nonconf_files_of_pkg "${pkgname}" | grep -v '^/etc/uci-defaults/' | while read; do
|
||||
line="$REPLY"
|
||||
rm -f "$overlay/upper/${line}"
|
||||
done
|
||||
rm -f $overlay/upper/usr/lib/opkg/info/${pkgname}.list
|
||||
rm -f "$overlay/upper/$PKG_BASE/${pkgname}.list"
|
||||
fi
|
||||
rm -f $overlay/upper/usr/lib/opkg/info/${pkgname}.*
|
||||
rm -f "$overlay/upper/$PKG_BASE/${pkgname}.*"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -225,10 +264,17 @@ pkg_depends_rec() {
|
||||
local deps
|
||||
|
||||
echo "${pkgname}" | grep -q '^kmod-' && return
|
||||
_pkg_exists ${pkgname} && [ ! -f /tmp/reset_core_packages/${pkgname} ] || return
|
||||
touch /tmp/reset_core_packages/${pkgname}
|
||||
|
||||
if [ -f /usr/lib/opkg/info/${pkgname}.control -a ! -f /tmp/reset_core_packages/${pkgname} ]; then
|
||||
if $APK; then
|
||||
deps=`apk info --installed --recursive -R "${pkgname}" | grep -v 'depends on:' | grep . | sort -u`
|
||||
for dep in $deps ; do
|
||||
dep=${dep%%[@=<>~]*}
|
||||
[ -f /tmp/reset_core_packages/${dep} ] || echo "${dep}" | grep -q '^kmod-' || touch /tmp/reset_core_packages/${dep}
|
||||
done
|
||||
else
|
||||
deps=`grep '^Depends: ' /usr/lib/opkg/info/${pkgname}.control | sed -e 's/^Depends: //' -e 's/ ([^)]*)//g' -e 's/,/ /g'`
|
||||
touch /tmp/reset_core_packages/${pkgname}
|
||||
for dep in $deps ; do
|
||||
pkg_depends_rec "$dep"
|
||||
done
|
||||
@@ -254,8 +300,7 @@ list_core_packages()
|
||||
reset_core_packages()
|
||||
{
|
||||
local overlay="$1"
|
||||
local running_ver=$(grep 'DISTRIB_RELEASE=' /etc/openwrt_release 2>/dev/null | sed -E "s/.*='(.+)'.*/\1/")
|
||||
[ "v$(cat "$overlay/.upgrading" 2>/dev/null)" = "v$running_ver" ] && return
|
||||
update_overlay_lower_release "$overlay" || return
|
||||
local pkg
|
||||
[ -d /tmp/reset_core_packages ] || list_core_packages
|
||||
echo "Reset packages in $overlay: `ls /tmp/reset_core_packages/ | xargs echo`" | dd bs=960 2>/dev/null
|
||||
@@ -267,6 +312,8 @@ reset_core_packages()
|
||||
|
||||
clean_kmods()
|
||||
{
|
||||
# apk system will clean kmods on isos_upgrade
|
||||
$APK && return 0
|
||||
local DUMMY_VERSION=0.0.0-r1
|
||||
if [ -d "$1/upper/usr/lib/opkg/info" ]; then
|
||||
local compat=`grep -m1 '^Version: ' /usr/lib/opkg/info/kernel.control | sed 's/^Version: //'`
|
||||
@@ -320,13 +367,17 @@ prepare_primary_overlay()
|
||||
|
||||
prepare_primary_overlay_after_merge()
|
||||
{
|
||||
local upgrading=false
|
||||
update_overlay_lower_uuid /overlay && upgrading=true
|
||||
if [ -d /overlay/upper ]; then
|
||||
if update_overlay_lower_uuid /overlay || [ -f /overlay/.upgrading ] ; then
|
||||
if $upgrading ; then
|
||||
clean_os_version_files /overlay
|
||||
reset_core_packages /overlay
|
||||
touch /overlay/.upgrading
|
||||
mkdir -p /overlay/upper/etc/uci-defaults
|
||||
rm -f /overlay/upper/etc/uci-defaults/.upgrading
|
||||
touch /overlay/upper/etc/uci-defaults/.upgrading
|
||||
fi
|
||||
if [ -f /overlay/.upgrading -o -f /overlay/.merged ] ; then
|
||||
if $upgrading || [ -f /overlay/.merged ] ; then
|
||||
if is_overlayfs_use_xattr ; then
|
||||
clean_overlayfs_origin /overlay/upper
|
||||
clean_overlayfs_redundant_opaque /overlay/upper
|
||||
@@ -336,13 +387,13 @@ prepare_primary_overlay_after_merge()
|
||||
clean_overlayfs_redundant_whiteout_marker_luci /overlay
|
||||
fi
|
||||
else
|
||||
update_overlay_lower_uuid /overlay
|
||||
update_overlay_lower_release "/overlay"
|
||||
fi
|
||||
if [ -f /overlay/upper/usr/lib/opkg/.upgrading ]; then
|
||||
if [ -f /overlay/upper/etc/uci-defaults/.upgrading ]; then
|
||||
clean_kmods /overlay
|
||||
fi
|
||||
|
||||
rm -f /overlay/.upgrading /overlay/.merged
|
||||
rm -f /overlay/.merged
|
||||
|
||||
mkdir -p /overlay/upper /overlay/work
|
||||
}
|
||||
@@ -393,10 +444,13 @@ prepare_ext_overlay()
|
||||
{
|
||||
local newoverlaydir=$1
|
||||
local overlaydir=$2
|
||||
local upgrading=false
|
||||
update_overlay_lower_uuid "$newoverlaydir" && upgrading=true
|
||||
|
||||
if [ -f "$newoverlaydir/.reset" ]; then
|
||||
rm -rf "$newoverlaydir/upper"
|
||||
rm -f "$newoverlaydir/.commit" "$newoverlaydir/.reset"
|
||||
update_overlay_lower_release "$newoverlaydir"
|
||||
elif [ -f "$newoverlaydir/.commit" ]; then
|
||||
if [ -d "$newoverlaydir/upper" ]; then
|
||||
apply_overlayfs_opaque "$newoverlaydir" "$overlaydir"
|
||||
@@ -406,28 +460,35 @@ prepare_ext_overlay()
|
||||
rmdir "$overlaydir/upper/ext_overlay"
|
||||
rm -rf "$newoverlaydir/upper"
|
||||
mkdir -m 0755 -p "$newoverlaydir/upper/ext_overlay"
|
||||
rm -f "$overlaydir/upper/etc/uci-defaults/.upgrading" "$overlaydir/.rootfs-uuid" "$overlaydir/.rootfs-release"
|
||||
update_overlay_lower_release "$newoverlaydir"
|
||||
}
|
||||
rm -f "$newoverlaydir/.commit"
|
||||
else
|
||||
prepare_primary_overlay_after_merge
|
||||
touch "$overlaydir/.clean"
|
||||
if [ -f "$newoverlaydir/upper/usr/lib/opkg/.upgrading" ]; then
|
||||
clean_kmods "$newoverlaydir"
|
||||
fi
|
||||
if [ -f "$newoverlaydir/.upgrading" ]; then
|
||||
clean_os_version_files "$newoverlaydir"
|
||||
reset_core_packages "$newoverlaydir"
|
||||
is_overlayfs_use_xattr && clean_overlayfs_origin "$newoverlaydir/upper"
|
||||
fi
|
||||
if [ -d "$newoverlaydir/upper" -a \( -f "$newoverlaydir/upper/usr/lib/opkg/.upgrading" -o ! -f "$overlaydir/.sandbox" \) ]; then
|
||||
clean_overlayfs_redundant_whiteout_marker "$newoverlaydir" "$overlaydir"
|
||||
if [ -d "$newoverlaydir/upper" ]; then
|
||||
if $upgrading; then
|
||||
clean_kmods "$newoverlaydir"
|
||||
clean_os_version_files "$newoverlaydir"
|
||||
reset_core_packages "$newoverlaydir"
|
||||
mkdir -p "$newoverlaydir/upper/etc/uci-defaults"
|
||||
rm -f "$newoverlaydir/upper/etc/uci-defaults/.upgrading"
|
||||
touch "$newoverlaydir/upper/etc/uci-defaults/.upgrading"
|
||||
is_overlayfs_use_xattr && clean_overlayfs_origin "$newoverlaydir/upper"
|
||||
elif [ -c "$newoverlaydir/upper/etc/uci-defaults/.upgrading" -a ! -f "$overlaydir/upper/etc/uci-defaults/.upgrading" ]; then
|
||||
rm -f "$newoverlaydir/upper/etc/uci-defaults/.upgrading"
|
||||
fi
|
||||
if $upgrading || [ ! -f "$overlaydir/.sandbox" ]; then
|
||||
clean_overlayfs_redundant_whiteout_marker "$newoverlaydir" "$overlaydir"
|
||||
else
|
||||
clean_overlayfs_redundant_whiteout_marker_luci "$newoverlaydir" "$overlaydir"
|
||||
fi
|
||||
else
|
||||
clean_overlayfs_redundant_whiteout_marker_luci "$newoverlaydir" "$overlaydir"
|
||||
update_overlay_lower_release "$newoverlaydir"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f "$newoverlaydir/.upgrading"
|
||||
|
||||
( mkdir -m 0755 -p $newoverlaydir/upper/ext_overlay && \
|
||||
mkdir -m 0755 -p $newoverlaydir/work ) || return 1
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ for file in \
|
||||
/lib/board \
|
||||
/sbin/ujail \
|
||||
/usr/lib/opkg/info/luci-app-oaf.control \
|
||||
/lib/apk/packages/luci-app-oaf.list \
|
||||
/usr/libexec/fan-control \
|
||||
/usr/sbin/sandbox
|
||||
do
|
||||
|
||||
@@ -117,6 +117,7 @@ sh -c 'mount --bind /tmp/proconly.txt /proc/$$/mounts && exec mount -o rw,remoun
|
||||
rm -f /tmp/proconly.txt
|
||||
|
||||
|
||||
# Apk system means that openwrt version is newer than 24.10, there is not such issue on newer openwrt version, so we just check opkg system.
|
||||
PROCD_VER=`grep -o '^Version: [0-9]*' /rom/usr/lib/opkg/info/procd.control | cut -d' ' -f2`
|
||||
if [ -n "$PROCD_VER" -a "$PROCD_VER" -lt 2024 ]; then
|
||||
# workaround procd < 2024 infite loop on resolving rootfs type, e.g. `ubus call system board`
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.18-r1
|
||||
PKG_RELEASE:=2
|
||||
PKG_VERSION:=1.1.0-r1
|
||||
PKG_RELEASE:=3
|
||||
|
||||
LUCI_TITLE:=LuCI support for SysTools
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -158,6 +158,7 @@ level=$1
|
||||
|
||||
echo "Try Level $level"
|
||||
|
||||
# Apk system means that openwrt is newer enough, so we don't need to check the odhcpd version on apk system
|
||||
odhcpd_version=$(grep -o 'Version: [0-9]*' /usr/lib/opkg/info/odhcpd-ipv6only.control | cut -d' ' -f2)
|
||||
if [ -n "$odhcpd_version" -a "$odhcpd_version" -lt 2025 ]; then
|
||||
echo "odhcpd version $odhcpd_version detected, enabling NDP bug workaround"
|
||||
@@ -166,7 +167,10 @@ fi
|
||||
|
||||
# nat
|
||||
if [ "$level" = $LEVEL_NAT ]; then
|
||||
if opkg status kmod-ipt-nat6 | grep '^Status: ' | grep -Fwq installed ; then
|
||||
if [ -f /etc/apk/arch ]; then
|
||||
apk query --installed --field version kmod-ipt-nat6 | grep -q 'Version:\s*[1-9]' || \
|
||||
apk add kmod-ipt-nat6 || exit 1
|
||||
elif opkg status kmod-ipt-nat6 | grep '^Status: ' | grep -Fwq installed ; then
|
||||
echo "kmod-ipt-nat6 found"
|
||||
else
|
||||
echo "kmod-ipt-nat6 not found, installing"
|
||||
|
||||
@@ -1,18 +1,33 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2025 jjm2473@gmail.com
|
||||
|
||||
(
|
||||
cd /usr/lib/opkg/info
|
||||
grep -lm1 '^Version: 0.0.0-r1$' kmod-*.control 2>/dev/null | sed 's/.control$//'
|
||||
) > /tmp/incompat_kmods.txt
|
||||
APK=false
|
||||
[ -f /etc/apk/arch ] && APK=true
|
||||
|
||||
if $APK; then
|
||||
apk list --installed --manifest 'kmod-*' | grep ' 0.0.0-r1$' | cut -d' ' -f1 > /tmp/incompat_kmods.txt
|
||||
else
|
||||
(
|
||||
cd /usr/lib/opkg/info
|
||||
grep -lm1 '^Version: 0.0.0-r1$' kmod-*.control 2>/dev/null | sed 's/.control$//'
|
||||
) > /tmp/incompat_kmods.txt
|
||||
fi
|
||||
|
||||
if [ -s /tmp/incompat_kmods.txt ]; then
|
||||
echo "The following incompatible kernel modules were found:"
|
||||
cat /tmp/incompat_kmods.txt
|
||||
echo "=====END====="
|
||||
echo "Try installing from opkg"
|
||||
opkg update
|
||||
opkg install $(cat /tmp/incompat_kmods.txt)
|
||||
if $APK; then
|
||||
echo "Try installing from apk"
|
||||
# doing `apk fix` twice, because the first time install the version 0.0.0-r1, which is always not exist, but it's side effect mark the package uninstalled, the second time will install the latest version.
|
||||
# `apk add --force-reinstall` works too, but it will change world file, which may not be desired.
|
||||
apk fix -r $(cat /tmp/incompat_kmods.txt) >/dev/null 2>&1
|
||||
apk fix -r $(cat /tmp/incompat_kmods.txt)
|
||||
else
|
||||
echo "Try installing from opkg"
|
||||
opkg update
|
||||
opkg install $(cat /tmp/incompat_kmods.txt)
|
||||
fi
|
||||
rm -f /tmp/incompat_kmods.txt
|
||||
echo "If you encounter network problems, please try again"
|
||||
echo "If it says some packages are unknown, it may be because they have been removed. Just ignore it."
|
||||
|
||||
@@ -1,48 +1,49 @@
|
||||
#!/bin/sh
|
||||
|
||||
APK=false
|
||||
PKG_BASE=usr/lib/opkg/info
|
||||
PKG_EXT=control
|
||||
|
||||
[ -s /etc/apk/arch ] && {
|
||||
APK=true
|
||||
PKG_BASE=lib/apk/packages
|
||||
PKG_EXT=list
|
||||
}
|
||||
|
||||
nonconf_files_of_pkg() {
|
||||
local pkgname="$1"
|
||||
if [ -s /rom/usr/lib/opkg/info/${pkgname}.conffiles ]; then
|
||||
grep -hvxFf /rom/usr/lib/opkg/info/${pkgname}.conffiles \
|
||||
/rom/usr/lib/opkg/info/${pkgname}.list
|
||||
if [ -s /rom/$PKG_BASE/${pkgname}.conffiles ]; then
|
||||
grep -hvxFf /rom/$PKG_BASE/${pkgname}.conffiles \
|
||||
/rom/$PKG_BASE/${pkgname}.list
|
||||
else
|
||||
cat /rom/usr/lib/opkg/info/${pkgname}.list
|
||||
cat /rom/$PKG_BASE/${pkgname}.list
|
||||
fi
|
||||
}
|
||||
|
||||
reset_pkg() {
|
||||
local pkgname="$1"
|
||||
local line
|
||||
local dep
|
||||
local deps
|
||||
echo "${pkgname}" | grep -q '^kernel$
|
||||
^libc$
|
||||
^libgcc1$
|
||||
^libatomic1$
|
||||
^busybox$' && return
|
||||
if [ -f /rom/usr/lib/opkg/info/${pkgname}.control -a \
|
||||
\( -e /overlay/upper/usr/lib/opkg/info/${pkgname}.control -o \
|
||||
-e /ext_overlay/upper/usr/lib/opkg/info/${pkgname}.control \) ]; then
|
||||
if [ -f /rom/$PKG_BASE/${pkgname}.$PKG_EXT -a \
|
||||
\( -e /overlay/upper/$PKG_BASE/${pkgname}.$PKG_EXT -o \
|
||||
-e /ext_overlay/upper/$PKG_BASE/${pkgname}.$PKG_EXT \) ]; then
|
||||
echo "reset ${pkgname}"
|
||||
if [ -f /rom/usr/lib/opkg/info/${pkgname}.list ]; then
|
||||
if [ -f /rom/$PKG_BASE/${pkgname}.list ]; then
|
||||
nonconf_files_of_pkg "${pkgname}" | while read; do
|
||||
line="$REPLY"
|
||||
line="$REPLY"
|
||||
rm -f "/overlay/upper/${line}" "/ext_overlay/upper/${line}"
|
||||
done
|
||||
rm -f /overlay/upper/usr/lib/opkg/info/${pkgname}.list /ext_overlay/upper/usr/lib/opkg/info/${pkgname}.list
|
||||
rm -f /overlay/upper/$PKG_BASE/${pkgname}.list /ext_overlay/upper/$PKG_BASE/${pkgname}.list
|
||||
fi
|
||||
deps=`grep '^Depends: ' /rom/usr/lib/opkg/info/${pkgname}.control | sed -e 's/^Depends: //' -e 's/ ([^)]*)//g' -e 's/,/ /g'`
|
||||
# avoid loop deps
|
||||
rm -f /overlay/upper/usr/lib/opkg/info/${pkgname}.control /ext_overlay/upper/usr/lib/opkg/info/${pkgname}.control
|
||||
for dep in $deps ; do
|
||||
reset_pkg "$dep"
|
||||
done
|
||||
rm -f /overlay/upper/usr/lib/opkg/info/${pkgname}.* /ext_overlay/upper/usr/lib/opkg/info/${pkgname}.*
|
||||
fi
|
||||
}
|
||||
|
||||
ls_all_rom_pkgs() {
|
||||
( cd /rom/usr/lib/opkg/info ; find . -maxdepth 1 -name '*.control' | sed -E 's#./(.*).control#\1#g' )
|
||||
( cd /rom/$PKG_BASE ; find . -maxdepth 1 -name "*.$PKG_EXT" | sed -E 's#./(.*).'"$PKG_EXT"'#\1#g' )
|
||||
}
|
||||
|
||||
reset_all_rom() {
|
||||
@@ -55,7 +56,13 @@ reset_all_rom() {
|
||||
|
||||
reset_all_rom
|
||||
|
||||
touch /overlay/upper/usr/lib/opkg/.upgrading
|
||||
if $APK; then
|
||||
rm -f /overlay/upper/etc/uci-defaults/.upgrading /ext_overlay/upper/etc/uci-defaults/.upgrading
|
||||
touch /overlay/upper/etc/uci-defaults/.upgrading 2>/dev/null
|
||||
else
|
||||
rm -f /overlay/upper/usr/lib/opkg/.upgrading /ext_overlay/upper/usr/lib/opkg/.upgrading
|
||||
touch /overlay/upper/usr/lib/opkg/.upgrading 2>/dev/null
|
||||
fi
|
||||
|
||||
echo "done, please reboot, it will reboot in 10s"
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-wwand
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/ddimension/luci-app-wwand.git
|
||||
PKG_SOURCE_VERSION:=b4dcc07ae3ebae8fcc80a335de35f6fde19fbd85
|
||||
PKG_SOURCE_DATE:=2026-08-21
|
||||
PKG_SOURCE_VERSION:=c9c2e1870b094cdc7bdd9013a7e4862e030b9500
|
||||
PKG_SOURCE_DATE:=2026-08-23
|
||||
PKG_MIRROR_HASH:=skip
|
||||
|
||||
PKG_LICENSE:=GPL-2.0-only
|
||||
|
||||
Loaded 100 of 119 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user