mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-29 20:25:13 +08:00
🎨 Sync 2026-09-15 23:44:06
This commit is contained in:
1 parent
1a3656348a
commit
75e213b656
19 files changed
+130
-152
No files matched your search
+2
-2
@@ -6,11 +6,11 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=cloudreve
|
||||
PKG_VERSION:=4.18.0
|
||||
PKG_RELEASE:=17
|
||||
PKG_RELEASE:=18
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/cloudreve/Cloudreve.git
|
||||
PKG_SOURCE_VERSION:=ade1866be54a3614bc643ab5f513e93a1e0dc82f
|
||||
PKG_SOURCE_VERSION:=e03a104a7d42a1fa46c697f57b66e550189350ea
|
||||
PKG_MIRROR_HASH:=skip
|
||||
|
||||
PKG_LICENSE:=GPL-3.0-only
|
||||
|
||||
@@ -12,7 +12,7 @@ LUCI_DEPENDS:=+luci-base +logd +jsonfilter
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
PKG_VERSION:=0.1.41
|
||||
PKG_RELEASE:=15
|
||||
PKG_RELEASE:=16
|
||||
|
||||
# Reproducible build: honor SOURCE_DATE_EPOCH from the build environment (set by docker-sdk.sh / CI).
|
||||
ifdef SOURCE_DATE_EPOCH
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
* While paused, ingest grows up to fetchLinesMax. Live mode caps at rowLimit.
|
||||
* On resume, merge (do not replace) so pause-accumulated rows survive the first
|
||||
* live poll — see issue #43 pause→resume data loss.
|
||||
* live poll.
|
||||
*/
|
||||
|
||||
function ingestCap(paused, rowLimit, fetchLinesMax) {
|
||||
|
||||
@@ -12,13 +12,13 @@ return baseclass.extend({
|
||||
APP_VERSION: '0.1.41',
|
||||
ROW_LIMIT_OPTIONS: [25, 50, 100, 250, 500, 1000, 2000],
|
||||
DEFAULT_ROW_LIMIT: 100,
|
||||
/* Row pass/deny tint (#40): classic green/red default; accessible teal/orange */
|
||||
/* Row pass/deny tint: classic green/red default; accessible teal/orange */
|
||||
ROW_TINT_OPTIONS: ['off', 'classic', 'accessible'],
|
||||
DEFAULT_ROW_TINT: 'classic',
|
||||
FETCH_LINES_MAX: 2000 /* ubus poll / logd ring cap (~2000 lines ≈ typical ring) */,
|
||||
/* DOM budget: ~250 new/updated rows painted per second on typical LuCI routers */
|
||||
RENDER_CAP_PER_SEC: 250,
|
||||
/* #306 Layer 2 — measured client RTT → poll cadence (seconds). */
|
||||
/* Layer 2 — measured client RTT → poll cadence (seconds). */
|
||||
POLL_CADENCE_FAST_S: 1,
|
||||
POLL_CADENCE_MID_S: 2,
|
||||
POLL_CADENCE_SLOW_S: 5,
|
||||
|
||||
@@ -24,7 +24,7 @@ const callFwlivePoll = rpc.declare({
|
||||
object: 'fwlive',
|
||||
method: 'poll',
|
||||
params: ['addresses']
|
||||
/* Full reply object kept so reply.error reaches fetchEntries (#233). */
|
||||
/* Full reply object kept so reply.error reaches fetchEntries. */
|
||||
});
|
||||
|
||||
const callFwliveRules = rpc.declare({
|
||||
@@ -36,7 +36,7 @@ const callFwliveResolve = rpc.declare({
|
||||
object: 'fwlive',
|
||||
method: 'resolve',
|
||||
params: ['addresses']
|
||||
/* Full reply kept so disabled:"load" reaches the view (#306 Layer 2). */
|
||||
/* Full reply kept so disabled:"load" reaches the view. */
|
||||
});
|
||||
|
||||
const callFwliveLoggingStatus = rpc.declare({
|
||||
@@ -98,11 +98,11 @@ return view.extend({
|
||||
sessionSeen: null,
|
||||
pauseBufferLoading: false,
|
||||
paused: false,
|
||||
/* One-shot: first live poll after unpause merges instead of replacing (#43). */
|
||||
/* One-shot: first live poll after unpause merges instead of replacing. */
|
||||
resumeMerge: false,
|
||||
pollFn: null,
|
||||
pollDataInFlight: false,
|
||||
/* #306 Layer 2 — visibility / RTT cadence / shed surfacing. */
|
||||
/* Layer 2 — visibility / RTT cadence / shed surfacing. */
|
||||
pollEpoch: 0,
|
||||
pollCadenceSec: 1,
|
||||
rttStreakKind: null,
|
||||
@@ -473,7 +473,7 @@ return view.extend({
|
||||
const res = await callFwliveRules();
|
||||
this.rulesMap = (res && res.rules) || {};
|
||||
this.firewallBackend = (res && res.backend) || 'nft';
|
||||
/* Bounds / mktemp failures are reply.error — same idea as poll (#245). */
|
||||
/* Bounds / mktemp failures are reply.error — same idea as poll. */
|
||||
this.lastRulesError = (res && res.error) || null;
|
||||
if (this.lastRulesError) console.warn('fwlive rules map error:', this.lastRulesError);
|
||||
} catch (e) {
|
||||
@@ -829,7 +829,7 @@ return view.extend({
|
||||
return typeof document !== 'undefined' && !!document.hidden;
|
||||
},
|
||||
|
||||
/* Classify one RTT sample into hysteresis buckets (#306).
|
||||
/* Classify one RTT sample into hysteresis buckets.
|
||||
* error and >1.5s share the slow/degraded streak so mixed failures still trip N=3. */
|
||||
rttKindFromMs(ms, errored) {
|
||||
if (errored) return 'slow';
|
||||
@@ -1099,7 +1099,7 @@ return view.extend({
|
||||
const limit = this.rowLimit;
|
||||
const suffix = this.statusSuffix();
|
||||
/* While paused the buffer can grow past the display limit — count matches
|
||||
* over the full buffer so "matching" is not capped at visibleRows (#83). */
|
||||
* over the full buffer so "matching" is not capped at visibleRows. */
|
||||
let shown = matchCount;
|
||||
if (this.paused) {
|
||||
const filters = this.readFilters();
|
||||
@@ -1206,7 +1206,7 @@ return view.extend({
|
||||
|
||||
if (wasPaused && !this.paused) {
|
||||
this.followLive = true;
|
||||
/* Merge pause buffer with the first live poll — do not replace (#43). */
|
||||
/* Merge pause buffer with the first live poll — do not replace. */
|
||||
this.resumeMerge = true;
|
||||
const epoch = this.pollEpoch;
|
||||
this.fetchEntries()
|
||||
@@ -1671,7 +1671,7 @@ return view.extend({
|
||||
}
|
||||
} finally {
|
||||
/* Only the owning epoch clears — a stale hidden-era poll must not
|
||||
* drop the catch-up guard after resume (Grok #331). Resume clears
|
||||
* drop the catch-up guard after resume. Resume clears
|
||||
* explicitly before starting the catch-up poll. */
|
||||
if (epoch === this.pollEpoch) this.pollDataInFlight = false;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2025-2026 Lucas Albers <lucas.b.albers@gmail.com>
|
||||
#
|
||||
# Layer 1 adaptive poll cap (#306). Sourced by rpcd/fwlive.
|
||||
# Layer 1 adaptive poll cap. Sourced by rpcd/fwlive.
|
||||
# Always on unless test/triage override (no UCI / no product config):
|
||||
# FWLIVE_ADAPTIVE=0|false|off|no
|
||||
# or sentinel ${FWLIVE_ADAPTIVE_OFF_FILE:-<state-dir>/fwlive-adaptive-off}
|
||||
@@ -18,10 +18,10 @@
|
||||
# flock, lock busy, or corrupt state. Lock-busy ⇒ unlocked last-writer-wins is
|
||||
# acceptable (state stays one valid JSON line; ordering is not guaranteed).
|
||||
# Failed ubus log.read must NOT call record() — a ~0 ms failure is not "cold"
|
||||
# health and must not clear an existing hot/shed cap (#329 Hermes Q1).
|
||||
# health and must not clear an existing hot/shed cap.
|
||||
# Outside the measured duration interval: plan (pre), record/merge (post).
|
||||
# messages_received is 0 in Layer 1 — do not ash-scan the filter JSON after
|
||||
# end_cs (Grok #329 P1); accurate count belongs in the filter or a later layer.
|
||||
# end_cs; accurate count belongs in the filter or a later layer.
|
||||
|
||||
FWLIVE_ADAPTIVE_STATE_FILE="${FWLIVE_ADAPTIVE_STATE_FILE:-/var/run/fwlive-state.json}"
|
||||
# Optional overrides; when unset, lock/off paths are siblings of the current state.
|
||||
@@ -238,7 +238,7 @@ fwlive_adaptive_with_lock() {
|
||||
"$@"
|
||||
return $?
|
||||
fi
|
||||
# Create lock at 0600 (logging.lock #167 — world-readable fd can take LOCK_EX).
|
||||
# Create lock at 0600 (world-readable fd can take LOCK_EX).
|
||||
if [ ! -e "$_lock" ]; then
|
||||
if ! ( umask 077; : >"$_lock" ) 2>/dev/null; then
|
||||
"$@"
|
||||
@@ -424,7 +424,7 @@ fwlive_adaptive_merge_reply() {
|
||||
}
|
||||
|
||||
# Count log[*] via "msg" keys — helper for tests / future filter-side count.
|
||||
# NOT called on the poll hot path (Grok #329 P1): ash-scanning a 2000-entry
|
||||
# NOT called on the poll hot path: ash-scanning a 2000-entry
|
||||
# reply after end_cs is unmeasured overhead that cannot shed itself.
|
||||
fwlive_adaptive_count_log() {
|
||||
_json=$1
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
# Log messages are treated as data (jsonfilter + awk stdin); never interpolated
|
||||
# into shell command strings. Usage: ubus call log read '...' | fwlive-log-filter.sh
|
||||
#
|
||||
# Perf (#219): one jsonfilter for @.log[*] plus one awk classify. Process
|
||||
# Perf: one jsonfilter for @.log[*] plus one awk classify. Process
|
||||
# count is constant per poll, not O(entries).
|
||||
#
|
||||
# Entry point (pipeline). The classifier sibling is sourced and must not set
|
||||
# strict mode itself (#291 C3).
|
||||
# strict mode itself.
|
||||
set -eu
|
||||
# shellcheck disable=SC3040
|
||||
(set -o pipefail) 2>/dev/null && set -o pipefail
|
||||
@@ -26,7 +26,7 @@ FILTER_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
. "$FILTER_DIR/fwlive-is-firewall-event.sh"
|
||||
|
||||
# The classifier is a package asset, not generated at request time. Fail
|
||||
# closed if an incomplete install or a damaged package removed it (#321).
|
||||
# closed if an incomplete install or a damaged package removed it.
|
||||
if [ ! -r "$CLASSIFY_AWK" ]; then
|
||||
printf '%s' '{"log":[],"error":"classifier_missing"}'
|
||||
exit 1
|
||||
@@ -35,8 +35,8 @@ fi
|
||||
printf '%s' '{"log":['
|
||||
# Prefer stdin over -s: Linux MAX_ARG_STRLEN is 128KiB; a raised logd ring
|
||||
# (or paused FETCH_LINES_MAX poll) can exceed that and make jsonfilter fail
|
||||
# while this script still printed {"log":[]} and exited 0 (#234).
|
||||
# jsonfilter miss / empty @.log is not fatal; must still close JSON (#220).
|
||||
# set -e + pipefail cannot apply to this pipeline (#291 C3).
|
||||
# while this script still printed {"log":[]} and exited 0.
|
||||
# jsonfilter miss / empty @.log is not fatal; must still close JSON.
|
||||
# set -e + pipefail cannot apply to this pipeline.
|
||||
jsonfilter -e '@.log[*]' 2>/dev/null | _fwlive_filter_json_entries || true
|
||||
printf '%s' ']}'
|
||||
@@ -7,13 +7,13 @@
|
||||
# Sourced library (rpcd plugin, package prerm). Do not `set -euo pipefail`
|
||||
# here: prerm is best-effort (`restore ... || logger`; exit 0) and callers
|
||||
# expect soft failures. The rpcd entry point enables strict mode; critical
|
||||
# paths use explicit `|| return 1` / `|| true` (#244, #291 C3).
|
||||
# paths use explicit `|| return 1` / `|| true`.
|
||||
|
||||
NF_LOG_IPV4='/proc/sys/net/netfilter/nf_log/2'
|
||||
NF_LOG_IPV6='/proc/sys/net/netfilter/nf_log/10'
|
||||
|
||||
# Serialize the WAN logging read->compute->set->commit window across
|
||||
# concurrent ubus write-ACL callers (#151): each toggle re-reads the current
|
||||
# concurrent ubus write-ACL callers: each toggle re-reads the current
|
||||
# firewall.<zone>.log bit, computes a target, then uci set + uci commit. Two
|
||||
# concurrent callers could otherwise interleave and last-commit-wins.
|
||||
#
|
||||
@@ -28,7 +28,7 @@ WAN_LOG_LOCK_FILE="${FWLIVE_WAN_LOG_LOCK_FILE:-/etc/fwlive/logging.lock}"
|
||||
WAN_LOG_BASELINE_FILE="${FWLIVE_WAN_LOG_BASELINE_FILE:-/etc/fwlive/wan-log-baseline}"
|
||||
|
||||
# RFC 8259 string escape. Lives here so prerm can source this file
|
||||
# standalone (#222). rpcd sources us and must not redefine this.
|
||||
# standalone. rpcd sources us and must not redefine this.
|
||||
json_escape() {
|
||||
# Escape for JSON string content per RFC 8259 (including remaining C0 controls).
|
||||
# Slurp stdin as one string. Default awk RS is newline — RS="" is
|
||||
@@ -67,8 +67,8 @@ json_escape() {
|
||||
}'
|
||||
}
|
||||
|
||||
# Production lock dir must be owned by euid with no group/other write (#204).
|
||||
# Avoid GNU/BusyBox `stat -c` — stock OpenWrt omits FEATURE_STAT_FORMAT (#232).
|
||||
# Production lock dir must be owned by euid with no group/other write.
|
||||
# Avoid GNU/BusyBox `stat -c` — stock OpenWrt omits FEATURE_STAT_FORMAT.
|
||||
wan_log_lock_dir_safe() {
|
||||
dir="$1"
|
||||
[ -n "$dir" ] || return 1
|
||||
@@ -86,10 +86,10 @@ wan_log_lock_dir_safe() {
|
||||
# Acquire the exclusive logging lock on fd 9. Blocks until free; fails closed
|
||||
# (return 1) only if the lock file cannot be opened or flock is unavailable.
|
||||
# Create/tighten the lock to 0600 so unprivileged UIDs cannot take LOCK_EX on
|
||||
# a world-readable fd (issue #167 / flock(2) allows exclusive locks on O_RDONLY).
|
||||
# a world-readable fd (flock(2) allows exclusive locks on O_RDONLY).
|
||||
acquire_wan_log_lock() {
|
||||
# Fail closed on symlinks: chmod/chown/exec O_TRUNC follow the target as root
|
||||
# (#204). Default lock lives under /etc/fwlive (root-only), not world-writable
|
||||
# Default lock lives under /etc/fwlive (root-only), not world-writable
|
||||
# /var/lock. Re-check after create/tighten (TOCTOU).
|
||||
lock_dir="$(dirname "$WAN_LOG_LOCK_FILE")"
|
||||
[ -L "$lock_dir" ] && return 1
|
||||
@@ -107,7 +107,7 @@ acquire_wan_log_lock() {
|
||||
# Probe in a subshell first: a failed `exec` redirection aborts a POSIX
|
||||
# non-interactive shell outright, so `|| return 1` on the real exec would
|
||||
# never run — and `2>/dev/null` on the same exec would permanently
|
||||
# silence this process's stderr on the success path (#244).
|
||||
# silence this process's stderr on the success path.
|
||||
( exec 9>>"$WAN_LOG_LOCK_FILE" ) 2>/dev/null || return 1
|
||||
exec 9>>"$WAN_LOG_LOCK_FILE"
|
||||
flock 9 2>/dev/null || {
|
||||
@@ -124,16 +124,16 @@ release_wan_log_lock() {
|
||||
|
||||
find_wan_zone_section() {
|
||||
# Match anonymous (@zone[N]) and named (e.g. wan) sections whose name option
|
||||
# is 'wan'. Prefer the first section whose type is zone (issue #168); skip
|
||||
# is 'wan'. Prefer the first section whose type is zone; skip
|
||||
# non-zone sections that happen to share name='wan'.
|
||||
# uci missing / no wan zone is empty, not fatal. pipefail + set -e
|
||||
# cannot apply to this pipeline (#291 C3).
|
||||
# cannot apply to this pipeline.
|
||||
_zones=$(uci -q show firewall 2>/dev/null \
|
||||
| sed -n "s/^firewall\.\([^.]*\)\.name='wan'$/\1/p") || true
|
||||
for zone in $_zones; do
|
||||
[ -n "$zone" ] || continue
|
||||
# uci -q get exits 1 on a missing section. Capture with || true so
|
||||
# set -e cannot abort inside "$(…)" before || continue (#291 C3).
|
||||
# set -e cannot abort inside "$(…)" before || continue.
|
||||
_type=$(uci -q get "firewall.${zone}" 2>/dev/null || true)
|
||||
[ "$_type" = "zone" ] || continue
|
||||
printf '%s' "$zone"
|
||||
@@ -143,7 +143,7 @@ find_wan_zone_section() {
|
||||
}
|
||||
|
||||
firewall_changes_pending() {
|
||||
# uci miss is "no pending changes". set -e cannot apply (#291 C3).
|
||||
# uci miss is "no pending changes". set -e cannot apply.
|
||||
pending="$(uci -q changes firewall 2>/dev/null || true)"
|
||||
[ -n "$pending" ]
|
||||
}
|
||||
@@ -151,7 +151,7 @@ firewall_changes_pending() {
|
||||
wan_zone_log_value() {
|
||||
zone="$1"
|
||||
[ -n "$zone" ] || return 1
|
||||
# Unset option is a valid empty value; uci -q get exits 1 (#291 C3).
|
||||
# Unset option is a valid empty value; uci -q get exits 1.
|
||||
uci -q get "firewall.${zone}.log" 2>/dev/null || true
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ uci_canonical_firewall_section() {
|
||||
| sed -n '1s/^firewall\.\([^=.]*\)=.*/\1/p'
|
||||
}
|
||||
|
||||
# True when two firewall section ids refer to the same WAN zone (issue #239).
|
||||
# True when two firewall section ids refer to the same WAN zone.
|
||||
# Compare canonical cfg ids — do NOT treat every name=wan zone as identical
|
||||
# (duplicate wan sections would under-match foreign .log deltas as ours).
|
||||
wan_firewall_zone_same() {
|
||||
@@ -196,7 +196,7 @@ wan_log_staged_line_section() {
|
||||
esac
|
||||
}
|
||||
|
||||
# Zone ids that may appear in `uci changes` for firewall.<id>.log (issue #239).
|
||||
# Zone ids that may appear in `uci changes` for firewall.<id>.log.
|
||||
wan_log_staged_zone_ids() {
|
||||
_zone="$1"
|
||||
_staged="$2"
|
||||
@@ -296,7 +296,7 @@ maybe_snapshot_wan_log_baseline() {
|
||||
restore_wan_log_baseline() {
|
||||
path="$(wan_log_baseline_path)"
|
||||
[ -f "$path" ] || return 0
|
||||
# Empty file is a valid "option was unset" baseline (#291 C3).
|
||||
# Empty file is a valid "option was unset" baseline.
|
||||
baseline=$(cat "$path" 2>/dev/null || true)
|
||||
zone=$(find_wan_zone_section)
|
||||
if [ -z "$zone" ]; then
|
||||
@@ -417,18 +417,18 @@ collect_logging_blockers() {
|
||||
check_nf_log_ipv6 || logging_blockers_append 'nf_log_ipv6_missing'
|
||||
|
||||
# Report via LOGGING_BLOCKERS, not exit status: return 1 would abort
|
||||
# build_logging_status_json under set -e (#291 C3).
|
||||
# build_logging_status_json under set -e.
|
||||
return 0
|
||||
}
|
||||
|
||||
collect_logging_warnings() {
|
||||
LOGGING_WARNINGS=''
|
||||
|
||||
# rpcd/fwlive run_with_timeout fail-closes to 127 without timeout (#229).
|
||||
# rpcd/fwlive run_with_timeout fail-closes to 127 without timeout.
|
||||
# Warnings are diagnostics only — do not gate the enable-logging CTA.
|
||||
command -v timeout >/dev/null 2>&1 || logging_warnings_append 'timeout_missing'
|
||||
|
||||
# Report via LOGGING_WARNINGS, not exit status (#291 C3).
|
||||
# Report via LOGGING_WARNINGS, not exit status.
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -444,9 +444,9 @@ json_null_or_string() {
|
||||
|
||||
build_logging_status_json() {
|
||||
zone=$(find_wan_zone_section)
|
||||
# Empty zone / unset log bit are valid; set -e cannot apply (#291 C3).
|
||||
# Empty zone / unset log bit are valid; set -e cannot apply.
|
||||
log_val=$(wan_zone_log_value "$zone") || log_val=
|
||||
# Unset log_limit is a valid empty value; uci -q get exits 1 (#291 C3).
|
||||
# Unset log_limit is a valid empty value; uci -q get exits 1.
|
||||
limit_val=
|
||||
if [ -n "$zone" ]; then
|
||||
limit_val=$(uci -q get "firewall.${zone}.log_limit" 2>/dev/null || true)
|
||||
@@ -491,7 +491,7 @@ restore_wan_zone_log() {
|
||||
zone="$1"
|
||||
previous="$2"
|
||||
[ -n "$zone" ] || return 1
|
||||
# Refuse to publish unrelated staged firewall deltas (issue #168).
|
||||
# Refuse to publish unrelated staged firewall deltas.
|
||||
if firewall_changes_pending; then
|
||||
logger -t fwlive "WAN log rollback skipped: firewall changes pending" 2>/dev/null || true
|
||||
return 1
|
||||
@@ -508,7 +508,7 @@ restore_wan_zone_log() {
|
||||
# closes the read->compute->set->commit window so a concurrent toggle cannot
|
||||
# commit between our read and our write (no lost update / no stale overwrite).
|
||||
#
|
||||
# TOCTOU hardening (#191): UCI staging is global per config file, so a
|
||||
# TOCTOU hardening: UCI staging is global per config file, so a
|
||||
# non-cooperating writer (another admin's `uci set`, the LuCI firewall page)
|
||||
# can stage a delta AFTER the toggle's early firewall_changes_pending check.
|
||||
# Staging and committing therefore live INSIDE this function — the only path
|
||||
@@ -544,7 +544,7 @@ commit_wan_log_change() {
|
||||
zone_json="$2"
|
||||
target="$3"
|
||||
|
||||
# Last-moment guard (#191): runs before OUR delta is staged, so a
|
||||
# Last-moment guard: runs before OUR delta is staged, so a
|
||||
# non-empty changes list here can only be a foreign writer's race.
|
||||
if firewall_changes_pending; then
|
||||
logger -t fwlive "WAN log toggle aborted at commit gate: firewall changes staged by another writer" 2>/dev/null || true
|
||||
@@ -568,7 +568,7 @@ commit_wan_log_change() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# Post-stage guard (#191): anything besides our log option is foreign.
|
||||
# Post-stage guard: anything besides our log option is foreign.
|
||||
# Undo our staging only (set previous / delete to match committed); leave
|
||||
# foreign deltas untouched and abort without commit.
|
||||
_staged=$(uci -q changes firewall 2>/dev/null || true)
|
||||
@@ -589,8 +589,8 @@ commit_wan_log_change() {
|
||||
# firewall_changes_pending from this package's own orphaned write —
|
||||
# but ONLY when nothing foreign is staged: `uci revert firewall` is
|
||||
# config-wide (uci has no option-level revert), and reverting would
|
||||
# clobber a concurrent writer's uncommitted delta (CodeRabbit/luna
|
||||
# fold, #191). With foreign staging present, leave it and warn.
|
||||
# clobber a concurrent writer's uncommitted delta. With foreign
|
||||
# staging present, leave it and warn.
|
||||
_staged=$(uci -q changes firewall 2>/dev/null || true)
|
||||
_total=$(printf '%s\n' "$_staged" | grep -c . 2>/dev/null || true)
|
||||
_ours=$(wan_log_count_our_staged_lines "$zone" "$_staged")
|
||||
@@ -603,7 +603,7 @@ commit_wan_log_change() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Post-commit verification (#191): confirm the committed config really
|
||||
# Post-commit verification: confirm the committed config really
|
||||
# carries what we wrote (empty target = option must now be gone/empty).
|
||||
# A mismatch means another writer overtook the commit: warn loudly but do
|
||||
# NOT blind-revert (that would destroy unrelated committed data); the
|
||||
@@ -619,7 +619,7 @@ commit_wan_log_change() {
|
||||
# would block a concurrent toggle until the holder exits — BusyBox flock has
|
||||
# no -w timeout).
|
||||
#
|
||||
# The ROLLBACK re-acquires the lock (luna fold 2026-08-10): read->compare->
|
||||
# The ROLLBACK re-acquires the lock: read->compare->
|
||||
# restore is only atomic when no other writer can commit between the read and
|
||||
# the restore. All writers hold the same flock, so re-acquiring it makes the
|
||||
# decision-and-restore a serialized unit. The lock is held only for the few
|
||||
@@ -686,7 +686,7 @@ enable_wan_logging() {
|
||||
# The log bit is re-read AFTER acquiring the lock so the target is computed
|
||||
# from the latest committed value; a concurrent toggle cannot interleave.
|
||||
# Staging + commit live inside commit_wan_log_change behind its last-moment
|
||||
# firewall_changes_pending re-check (#191): a foreign writer racing between
|
||||
# firewall_changes_pending re-check: a foreign writer racing between
|
||||
# the early check above and the commit aborts the toggle instead of having
|
||||
# its half-finished delta published with our log bit.
|
||||
if ! acquire_wan_log_lock; then
|
||||
@@ -740,7 +740,7 @@ disable_wan_logging() {
|
||||
# The log bit is re-read AFTER acquiring the lock so the target is computed
|
||||
# from the latest committed value; a concurrent toggle cannot interleave.
|
||||
# Staging + commit live inside commit_wan_log_change behind its last-moment
|
||||
# firewall_changes_pending re-check (#191): a foreign writer racing between
|
||||
# firewall_changes_pending re-check: a foreign writer racing between
|
||||
# the early check above and the commit aborts the toggle instead of having
|
||||
# its half-finished delta published with our log bit.
|
||||
if ! acquire_wan_log_lock; then
|
||||
|
||||
@@ -23,7 +23,7 @@ ADAPTIVE_SH="$LIBEXEC_DIR/fwlive-adaptive-cap.sh"
|
||||
RESOLVE_MAX=32
|
||||
# Per-lookup nslookup timeout (integer seconds — BusyBox `timeout` truncates
|
||||
# fractional values to 0 on OpenWrt 23.05/1.36, so 0.5 would silently
|
||||
# degrade to no timeout; luna fold 2026-08-10). The wall-clock budget
|
||||
# degrade to no timeout.. The wall-clock budget
|
||||
# below is the real whole-call bound; this per-lookup cap only prevents a
|
||||
# single hung resolver from dominating the budget. LAN/local-resolver
|
||||
# lookups are single-digit ms, so 1s is ample. Passed as argv to
|
||||
@@ -42,7 +42,7 @@ NFT_TIMEOUT=5
|
||||
# CLI-only iptables fixture path for __rulesmap_iptables (no arbitrary paths).
|
||||
RULESMAP_IPTABLES_FILE='/tmp/rulesmap'
|
||||
|
||||
# json_escape lives in fwlive-logging.sh so prerm can source that file alone (#222).
|
||||
# json_escape lives in fwlive-logging.sh so prerm can source that file alone.
|
||||
# shellcheck disable=SC1090,SC1091 # LOGGING_SH resolves to sibling ../fwlive-logging.sh
|
||||
. "$LOGGING_SH"
|
||||
# shellcheck disable=SC1090,SC1091
|
||||
@@ -52,10 +52,10 @@ slug_key() {
|
||||
echo "$1" | tr '[:upper:]' '[:lower:]' | tr ' _' '--'
|
||||
}
|
||||
|
||||
# Cap rules JSON size so a huge ruleset cannot unbound an rpcd reply (#229).
|
||||
# Cap rules JSON size so a huge ruleset cannot unbound an rpcd reply.
|
||||
RULES_MAP_MAX_KEYS=512
|
||||
RULES_MAP_MAX_BYTES=65536
|
||||
# Same wall-clock bound as nft for iptables-save / ip6tables-save (#229).
|
||||
# Same wall-clock bound as nft for iptables-save / ip6tables-save.
|
||||
# Overridable for host tests (e.g. FWLIVE_IPTABLES_TIMEOUT=1).
|
||||
IPTABLES_TIMEOUT="${FWLIVE_IPTABLES_TIMEOUT:-5}"
|
||||
|
||||
@@ -70,7 +70,7 @@ map_add() {
|
||||
# ("foo" vs "foobar") and value false positives ("see foo").
|
||||
# Quoting "$esc_key" makes the match literal (no glob escaping needed).
|
||||
# Callers apply UCI, then labeled (!fw4:) prefixes, then unlabeled
|
||||
# cosmetics so first-wins prefers authoritative names (#230).
|
||||
# cosmetics so first-wins prefers authoritative names.
|
||||
case "$OUT" in
|
||||
*"\"$esc_key\":"*) return 0 ;;
|
||||
esac
|
||||
@@ -92,7 +92,7 @@ map_add() {
|
||||
|
||||
uci_rule_names() {
|
||||
# uci missing / empty firewall config is "no names", not fatal.
|
||||
# pipefail + set -e cannot apply to this pipeline (#291 C3).
|
||||
# pipefail + set -e cannot apply to this pipeline.
|
||||
uci -q show firewall 2>/dev/null | sed -n "s/^firewall\.@rule\[[0-9]*\]\.name='\(.*\)'$/\1/p" || true
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ run_with_timeout() {
|
||||
if command -v timeout >/dev/null 2>&1; then
|
||||
timeout "$secs" "$@" 2>/dev/null
|
||||
else
|
||||
# Fail closed (#229): never run unbounded when timeout is absent.
|
||||
# Fail closed: never run unbounded when timeout is absent.
|
||||
return 127
|
||||
fi
|
||||
}
|
||||
@@ -170,7 +170,7 @@ map_uci_rule_names() {
|
||||
# Line-wise (here-doc, not an unquoted for-loop) so a name with
|
||||
# spaces stays one token. Names that fail is_uci_style_name are
|
||||
# skipped: parseRuleHint() cannot match them, and fragments of
|
||||
# "My Rule" must not shadow a real rule named Rule (#226).
|
||||
# "My Rule" must not shadow a real rule named Rule.
|
||||
# The while-read stays in the current shell (here-doc, not a
|
||||
# pipeline) so map_add mutations reach OUT.
|
||||
while IFS= read -r name || [ -n "$name" ]; do
|
||||
@@ -187,7 +187,7 @@ EOF
|
||||
}
|
||||
|
||||
# pass=labeled|unlabeled|all — labeled before unlabeled so !fw4: beats
|
||||
# an earlier cosmetic for the same prefix under first-wins (#230).
|
||||
# an earlier cosmetic for the same prefix under first-wins.
|
||||
map_from_nft_stream() {
|
||||
pass="${1:-all}"
|
||||
while IFS= read -r line; do
|
||||
@@ -255,7 +255,7 @@ _fwlive_tmp_dir_ok() {
|
||||
# Fail closed unless the dump dir is a real directory with the sticky
|
||||
# bit. Without sticky, another uid can unlink a just-created mktemp
|
||||
# file and replace it with a symlink before we reopen with `>` as
|
||||
# root (same class as #204). Optional $1 is for CLI tests; production
|
||||
# root (same class as the WAN logging lock). Optional $1 is for CLI tests; production
|
||||
# always uses /tmp.
|
||||
dir="${1:-/tmp}"
|
||||
[ -n "$dir" ] || return 1
|
||||
@@ -288,7 +288,7 @@ build_rules_map() {
|
||||
backend=$(detect_firewall_backend)
|
||||
|
||||
# UCI first, then labeled stream prefixes, then unlabeled cosmetics
|
||||
# (#230). First-wins keeps UCI over nft and !fw4: over cosmetic.
|
||||
# First-wins keeps UCI over nft and !fw4: over cosmetic.
|
||||
map_uci_rule_names
|
||||
|
||||
case "$backend" in
|
||||
@@ -435,16 +435,16 @@ fetch_firewall_logs() {
|
||||
shed_flag=${2:-0}
|
||||
# Adaptive plan prints: lines shed bucket
|
||||
start_cs=$(fwlive_adaptive_clock_cs)
|
||||
# Drop dead oneshot flag — only consumed on logd's stream branch (#306).
|
||||
# Drop dead oneshot flag — only consumed on logd's stream branch.
|
||||
if ! raw=$(ubus call log read "{\"lines\":$lines,\"stream\":false}" 2>/dev/null); then
|
||||
# Do not record ~0 ms as cold: failure is not healthy fast processing
|
||||
# and must not clear an existing hot/shed cap (#329 Hermes Q1).
|
||||
# and must not clear an existing hot/shed cap.
|
||||
out='{"log":[],"error":"log_read_failed"}'
|
||||
fwlive_adaptive_merge_reply "$out" "$shed_flag" "$lines" 0 0
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Do not swallow a filter failure into a silent empty table (#220).
|
||||
# Do not swallow a filter failure into a silent empty table.
|
||||
# If the filter exits non-zero but still printed JSON, keep it.
|
||||
# Empty success is not valid poll JSON — the shipped filter always
|
||||
# prints {"log":[...]}, but a stub/regression must not emit a blank body.
|
||||
@@ -455,12 +455,12 @@ fetch_firewall_logs() {
|
||||
fi
|
||||
[ -n "$out" ] || out='{"log":[],"error":"filter_empty"}'
|
||||
end_cs=$(fwlive_adaptive_clock_cs)
|
||||
# Uptime wrap / skew: end < start — do not record as cold (Grok #329 P2).
|
||||
# Uptime wrap / skew: end < start — do not record as cold.
|
||||
if [ "$end_cs" -ge "$start_cs" ]; then
|
||||
_dur=$(((end_cs - start_cs) * 10))
|
||||
fwlive_adaptive_record "$_dur" "$lines"
|
||||
fi
|
||||
# Layer 1: messages_received stays 0 — no post-filter ash count (Grok #329 P1).
|
||||
# Layer 1: messages_received stays 0 — no post-filter ash count.
|
||||
_trunc=0
|
||||
[ "$shed_flag" = 1 ] && _trunc=1
|
||||
[ "$lines" -lt "$requested" ] && _trunc=1
|
||||
@@ -502,7 +502,7 @@ resolve_hostname() {
|
||||
[ -n "$ip" ] || return 1
|
||||
is_resolvable_address "$ip" || return 1
|
||||
command -v nslookup >/dev/null 2>&1 || return 1
|
||||
# timeout/nslookup miss is "no PTR", not a plugin abort (#291 C3).
|
||||
# timeout/nslookup miss is "no PTR", not a plugin abort.
|
||||
out=$(run_with_timeout "$RESOLVE_TIMEOUT" nslookup "$ip") || return 1
|
||||
[ -n "$out" ] || return 1
|
||||
name=$(parse_nslookup_name "$out") || return 1
|
||||
@@ -510,7 +510,7 @@ resolve_hostname() {
|
||||
printf '%s' "$name"
|
||||
}
|
||||
|
||||
# Strict IPv4/IPv6 validation before nslookup (issue #190): the old char-class
|
||||
# Strict IPv4/IPv6 validation before nslookup: the old char-class
|
||||
# check admitted hostname-shaped tokens of hex chars + dots/colons
|
||||
# (e.g. "dead.beef.cafe.baad"), letting the resolver fall back to upstream DNS
|
||||
# queries chosen by an authenticated session. Validate the real address
|
||||
@@ -523,7 +523,7 @@ is_resolvable_address() {
|
||||
# Reject anything outside the address alphabet BEFORE awk, so embedded
|
||||
# newlines/whitespace (which awk would treat as record separators) can
|
||||
# never let a valid first record mask trailing garbage that still reaches
|
||||
# nslookup (#190, CodeRabbit/luna fold): nslookup only ever sees a single
|
||||
# nslookup: nslookup only ever sees a single
|
||||
# token. Note the check intentionally allows only hex/colon/dot.
|
||||
case "$addr" in
|
||||
*[!0-9a-fA-F:.]*) return 1 ;;
|
||||
@@ -596,7 +596,7 @@ is_resolvable_address() {
|
||||
}
|
||||
|
||||
resolve_addresses() {
|
||||
# Missing resolver must not look like "no PTR" (#218). Check before
|
||||
# Missing resolver must not look like "no PTR". Check before
|
||||
# starting the budget clock or reading stdin.
|
||||
if ! command -v nslookup >/dev/null 2>&1; then
|
||||
command -v logger >/dev/null 2>&1 && logger -t fwlive "nslookup not found; resolve disabled"
|
||||
@@ -604,14 +604,14 @@ resolve_addresses() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Load shed: previous poll was hot (#306 Layer 1).
|
||||
# Load shed: previous poll was hot.
|
||||
if fwlive_adaptive_is_hot; then
|
||||
printf '{"names":{},"disabled":"load"}'
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Wall-clock budget clock starts at the TRUE function entry (luna
|
||||
# folds 2026-08-10): the budget must bound the whole call — including
|
||||
# Wall-clock budget clock starts at the TRUE function entry: the
|
||||
# budget must bound the whole call — including
|
||||
# read_rpc_input (stalled stdin must not escape the budget) and json
|
||||
# parsing. `date +%s` can jump under NTP sync — accepted (worst case
|
||||
# the budget over- or under-runs by the jump; worker starvation is
|
||||
@@ -657,12 +657,12 @@ resolve_addresses() {
|
||||
# never START a lookup past the budget.
|
||||
now=$(date +%s)
|
||||
[ $((now - start)) -ge "$RESOLVE_BUDGET" ] && break
|
||||
# Missing/empty element: set -u cannot read bare $ip (#291 C3).
|
||||
# Missing/empty element: set -u cannot read bare $ip.
|
||||
if ! is_resolvable_address "${ip:-}"; then
|
||||
continue
|
||||
fi
|
||||
# NXDOMAIN / timeout: resolve_hostname returns 1. set -e
|
||||
# cannot apply to this assignment (#291 C3).
|
||||
# cannot apply to this assignment.
|
||||
name=$(resolve_hostname "$ip") || name=
|
||||
if [ -n "$name" ]; then
|
||||
map_add "$ip" "$name"
|
||||
@@ -729,7 +729,7 @@ run_selftest() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Issue #190: hostname-shaped tokens of hex chars + dots/colons passed the
|
||||
# hostname-shaped tokens of hex chars + dots/colons passed the
|
||||
# old char-class check and made the resolver fall back to upstream DNS. Each case
|
||||
# below must REJECT (and would be ACCEPTED by the reverted char-class code).
|
||||
if is_resolvable_address 'ab.cd.ef.01'; then
|
||||
@@ -757,7 +757,7 @@ run_selftest() {
|
||||
echo 'is_resolvable_address: expected accept IPv6-mapped ::ffff:192.0.2.1' >&2
|
||||
return 1
|
||||
fi
|
||||
# Multi-line input must be rejected wholesale (CodeRabbit/luna fold): awk
|
||||
# Multi-line input must be rejected wholesale: awk
|
||||
# reads newline-separated records, so a valid first record must not mask
|
||||
# trailing garbage that would still reach nslookup.
|
||||
if is_resolvable_address "$(printf '192.0.2.1\nnot-an-address')"; then
|
||||
@@ -849,7 +849,7 @@ Address: 127.0.0.1:53")
|
||||
|
||||
run_logging_selftest || return 1
|
||||
|
||||
# Strict-mode smoke (#291 C3): status JSON uses soft-fail helpers
|
||||
# Strict-mode smoke: status JSON uses soft-fail helpers
|
||||
# (uci miss, empty WAN zone). Must not abort under dash/ash set -e.
|
||||
_status=$(build_logging_status_json) || {
|
||||
echo "build_logging_status_json: aborted under set -e" >&2
|
||||
@@ -950,7 +950,7 @@ case "${1:-}" in
|
||||
build_rules_map
|
||||
;;
|
||||
poll)
|
||||
# rpcd may omit argv $3 and pass JSON on stdin (#291 C3).
|
||||
# rpcd may omit argv $3 and pass JSON on stdin.
|
||||
poll_logs "${3:-}"
|
||||
;;
|
||||
resolve)
|
||||
|
||||
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.9.9
|
||||
PKG_RELEASE:=274
|
||||
PKG_RELEASE:=275
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -20,7 +20,10 @@ for _, k in ipairs(com.order) do
|
||||
if k ~= "chinadns-ng" then
|
||||
o = s:option(Value, k:gsub("%-","_") .. "_file", translatef("%s App Path", v.name))
|
||||
o.default = v.default_path or ("/usr/bin/" .. k)
|
||||
o.rmempty = false
|
||||
o.placeholder = o.default
|
||||
function o:remove(section)
|
||||
self:write(section, self.default)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -408,16 +408,16 @@ load_acl() {
|
||||
else
|
||||
[ -n "${DIRECT_DNSMASQ_PORT}" ] && dns_redirect=${DIRECT_DNSMASQ_PORT}
|
||||
fi
|
||||
if [ -n "${dns_redirect}" ]; then
|
||||
if ([ -n "$tcp_port" ] || [ -n "$udp_port" ]) && [ -n "$dns_redirect" ]; then
|
||||
$ipt_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
|
||||
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
|
||||
$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
|
||||
$ipt_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
|
||||
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
|
||||
$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
|
||||
$ipt_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect}
|
||||
[ "$_ipv4" != "1" ] && $ip6t_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null
|
||||
$ip6t_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null
|
||||
$ipt_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect}
|
||||
[ "$_ipv4" != "1" ] && $ip6t_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null
|
||||
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}节点不同于全局配置,DNS 重定向到专用服务器[${dns_redirect}]。"
|
||||
$ip6t_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null
|
||||
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}节点不同于全局配置,DNS 重定向到专用服务器[${dns_redirect}]"
|
||||
fi
|
||||
|
||||
[ -n "$tcp_port" ] || [ -n "$udp_port" ] && {
|
||||
@@ -597,7 +597,7 @@ load_acl() {
|
||||
[ -n "${DIRECT_DNSMASQ_PORT}" ] && DNS_REDIRECT=${DIRECT_DNSMASQ_PORT}
|
||||
fi
|
||||
|
||||
if [ -n "${DNS_REDIRECT}" ]; then
|
||||
if ([ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ]) && [ -n "$DNS_REDIRECT" ]; then
|
||||
$ipt_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN
|
||||
$ip6t_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN 2>/dev/null
|
||||
$ipt_m -A PSW $(comment "默认") -p tcp --dport 53 -j RETURN
|
||||
@@ -606,6 +606,7 @@ load_acl() {
|
||||
$ip6t_n -A PSW_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports ${DNS_REDIRECT} 2>/dev/null
|
||||
$ipt_n -A PSW_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports ${DNS_REDIRECT}
|
||||
$ip6t_n -A PSW_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports ${DNS_REDIRECT} 2>/dev/null
|
||||
echolog " - ${msg}DNS 重定向到专用服务器[${DNS_REDIRECT}]"
|
||||
fi
|
||||
|
||||
[ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ] && {
|
||||
|
||||
@@ -471,26 +471,13 @@ load_acl() {
|
||||
fi
|
||||
|
||||
if ([ -n "$tcp_port" ] || [ -n "$udp_port" ]) && [ -n "$dns_redirect" ]; then
|
||||
if [ "$PROXY_IPV6" = "1" ]; then
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
|
||||
else
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} udp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp ${_ipt_source} tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
|
||||
fi
|
||||
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}节点不同于全局配置,DNS 重定向到专用服务器[${dns_redirect}]。"
|
||||
else
|
||||
if [ "$PROXY_IPV6" = "1" ]; then
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
|
||||
else
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
|
||||
fi
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
|
||||
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}节点不同于全局配置,DNS 重定向到专用服务器[${dns_redirect}]"
|
||||
fi
|
||||
|
||||
[ -n "$tcp_port" ] || [ -n "$udp_port" ] && {
|
||||
@@ -670,25 +657,13 @@ load_acl() {
|
||||
fi
|
||||
|
||||
if ([ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ]) && [ -n "$DNS_REDIRECT" ]; then
|
||||
if [ "$PROXY_IPV6" = "1" ]; then
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT comment \"默认\""
|
||||
else
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp udp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT comment \"默认\""
|
||||
fi
|
||||
else
|
||||
if [ "$PROXY_IPV6" = "1" ]; then
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp udp dport 53 counter return comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter return comment \"默认\""
|
||||
else
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp udp dport 53 counter return comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp tcp dport 53 counter return comment \"默认\""
|
||||
fi
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp udp dport 53 counter return comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp tcp dport 53 counter return comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter return comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp tcp dport 53 counter return comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp udp dport 53 counter redirect to :${DNS_REDIRECT} comment \"默认\""
|
||||
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter redirect to :${DNS_REDIRECT} comment \"默认\""
|
||||
echolog " - ${msg}DNS 重定向到专用服务器[${DNS_REDIRECT}]"
|
||||
fi
|
||||
|
||||
[ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ] && {
|
||||
@@ -1333,15 +1308,8 @@ add_firewall_rule() {
|
||||
|
||||
if [ -n "$NODE" ] && ([ -n "${LOCALHOST_TCP_PROXY_MODE}" ] || [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then
|
||||
[ -n "$DNS_REDIRECT_PORT" ] && {
|
||||
if [ "$PROXY_IPV6" == "1" ]; then
|
||||
#nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
|
||||
#nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
|
||||
nft "add rule $NFTABLE_NAME nat_output oif lo meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output oif lo meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
|
||||
else
|
||||
nft "add rule $NFTABLE_NAME nat_output oif lo ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output oif lo ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
|
||||
fi
|
||||
nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
|
||||
nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
|
||||
}
|
||||
fi
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=26.9.12
|
||||
PKG_RELEASE:=122
|
||||
PKG_RELEASE:=123
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -14,7 +14,10 @@ local k, v
|
||||
for k, v in pairs(com) do
|
||||
o = s:option(Value, k:gsub("%-","_") .. "_file", translatef("%s App Path", v.name))
|
||||
o.default = v.default_path or ("/usr/bin/" .. k)
|
||||
o.rmempty = false
|
||||
o.placeholder = o.default
|
||||
function o:remove(section)
|
||||
self:write(section, self.default)
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "tips", " ")
|
||||
|
||||
@@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_NAME:=luci-app-ssr-plus
|
||||
PKG_VERSION:=196
|
||||
PKG_RELEASE:=72
|
||||
PKG_RELEASE:=73
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||
|
||||
@@ -696,6 +696,12 @@ local function build_dns_section(dns_mode, user_dns)
|
||||
if not result["default-nameserver"] then
|
||||
result["default-nameserver"] = get_fastest_dns()
|
||||
end
|
||||
if not result["direct-nameserver"] then
|
||||
result["direct-nameserver"] = get_fastest_dns()
|
||||
end
|
||||
if result["direct-nameserver-follow-policy"] == nil then
|
||||
result["direct-nameserver-follow-policy"] = false
|
||||
end
|
||||
if result["respect-rules"] == nil then
|
||||
result["respect-rules"] = true
|
||||
end
|
||||
@@ -740,6 +746,8 @@ local function build_dns_section(dns_mode, user_dns)
|
||||
result["respect-rules"] = nil
|
||||
result["fallback-filter"] = nil
|
||||
result["nameserver-policy"] = nil
|
||||
result["direct-nameserver"] = nil
|
||||
result["direct-nameserver-follow-policy"] = nil
|
||||
end
|
||||
|
||||
local upstreams = build_dns_upstreams()
|
||||
|
||||
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=LuCI Status Pages
|
||||
LUCI_DEPENDS:=+luci-base +luci-app-oui +libiwinfo +rpcd-mod-iwinfo +rpcd-mod-rrdns +ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-socket
|
||||
|
||||
PKG_RELEASE:=10
|
||||
PKG_RELEASE:=11
|
||||
PKG_BUILD_DEPENDS:=iwinfo
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
|
||||
@@ -88,11 +88,6 @@ return baseclass.extend({
|
||||
_('Architecture'), (cpuinfo.cpuinfo || boardinfo.system) + ' ' + cpubench.cpubench,
|
||||
_('Target Platform'), (L.isObject(boardinfo.release) ? boardinfo.release.target : ''),
|
||||
_('Firmware Version'), (L.isObject(boardinfo.release) ? boardinfo.release.description + ' / ' : '') + (luciversion || ''),
|
||||
? '%s%s / '.format(
|
||||
boardinfo.release.description || '',
|
||||
boardinfo.release.revision ? boardinfo.release.revision : ''
|
||||
)
|
||||
: '') + (luciversion || ''),
|
||||
_('Kernel Version'), boardinfo.kernel,
|
||||
_('Local Time'), datestr,
|
||||
_('Uptime'), systeminfo.uptime ? '%t'.format(systeminfo.uptime) : null,
|
||||
|
||||
Reference in new issue
Block a user