Compare commits

...
8 Commits
Author SHA1 Message Date
action b109228443 update 2026-09-15 17:08:00 2026-09-15 17:08:00 +08:00
action bb8ab7ae16 update 2026-09-15 11:00:48 2026-09-15 11:00:48 +08:00
action c323f3b64e update 2026-09-15 01:28:15 2026-09-15 01:28:15 +08:00
action fcd7d31b29 update 2026-09-14 17:28:54 2026-09-14 17:28:54 +08:00
action 87faec277a update 2026-09-14 10:58:48 2026-09-14 10:58:48 +08:00
action d341a782d4 update 2026-09-14 06:01:57 2026-09-14 06:01:57 +08:00
action 205be274cd update 2026-09-14 02:28:52 2026-09-14 02:28:52 +08:00
action 622dd92021 update 2026-09-13 23:28:56 2026-09-13 23:28:56 +08:00
51 changed files with 941 additions and 695 deletions
+2 -2
View File
@@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=brook PKG_NAME:=brook
PKG_VERSION:=20260101.0 PKG_VERSION:=20270101
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/txthinking/brook/tar.gz/v$(PKG_VERSION)? PKG_SOURCE_URL:=https://codeload.github.com/txthinking/brook/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=8ddba4ed9ae9d10928e169f8121c6791e0e3c2907fa27d6e0055fe434f6e700e PKG_HASH:=43d8e5476918daa2d35fc63e8b0c94c0c1df8577f1d09103a3ab0f6141f29c0f
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org> PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
PKG_LICENSE:=GPL-3.0 PKG_LICENSE:=GPL-3.0
+4 -4
View File
@@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=clashoo PKG_NAME:=clashoo
PKG_SHORT_SHA:=dca26db PKG_SHORT_SHA:=ab405ba
PKG_COMMIT_DATE:=2026.09.11 PKG_COMMIT_DATE:=2026.09.14
PKG_VERSION:=$(PKG_COMMIT_DATE)~$(PKG_SHORT_SHA) PKG_VERSION:=$(PKG_COMMIT_DATE)~$(PKG_SHORT_SHA)
PKG_RELEASE:=1 PKG_RELEASE:=1
@@ -11,8 +11,8 @@ PKG_SOURCE:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA).tar.gz
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA) PKG_SOURCE_SUBDIR:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-alpha-$(PKG_SHORT_SHA) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-alpha-$(PKG_SHORT_SHA)
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-clashoo/releases/download/mihomo-src PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-clashoo/releases/download/mihomo-src
PKG_SOURCE_VERSION:=dca26db017bcde90071f3e16f97b12fafbccfa31 PKG_SOURCE_VERSION:=ab405bad5beeeac8b003bb01f60f134f6df54471
PKG_HASH:=593e53b3aeb52bbd3f49ddf4ae7773ce340bf2e984a9d5634a6385fa3041b5a2 PKG_HASH:=bd7a8035d67755720178a8fd2c49a9d82a4578493aae80ae46d5e6d3141cfaee
PKG_BUILD_VERSION:=alpha-$(PKG_SHORT_SHA) PKG_BUILD_VERSION:=alpha-$(PKG_SHORT_SHA)
PKG_LICENSE:=GPL3.0+ PKG_LICENSE:=GPL3.0+
@@ -939,6 +939,7 @@ set clashoo_china6 {
2402:7240::/32, 2402:7240::/32,
2402:72a0::/32, 2402:72a0::/32,
2402:72c0::/32, 2402:72c0::/32,
2402:73e0::/32,
2402:7540::/32, 2402:7540::/32,
2402:75c0::/32, 2402:75c0::/32,
2402:7740::/32, 2402:7740::/32,
@@ -1246,11 +1247,12 @@ set clashoo_china6 {
2403:6280::/32, 2403:6280::/32,
2403:62c0::/32, 2403:62c0::/32,
2403:6380::/42, 2403:6380::/42,
2403:6380:41::/48,
2403:6380:43::/48, 2403:6380:43::/48,
2403:6380:44::/46, 2403:6380:44::/46,
2403:6380:48::/45, 2403:6380:48::/45,
2403:6380:50::/44, 2403:6380:50::/44,
2403:6380:70::/44, 2403:6380:60::/43,
2403:6380:80::/41, 2403:6380:80::/41,
2403:6380:100::/40, 2403:6380:100::/40,
2403:6380:200::/39, 2403:6380:200::/39,
@@ -2036,7 +2038,7 @@ set clashoo_china6 {
2406:840:a18::/45, 2406:840:a18::/45,
2406:840:a20::/44, 2406:840:a20::/44,
2406:840:a30::/48, 2406:840:a30::/48,
2406:840:a32::/47, 2406:840:a33::/48,
2406:840:a34::/46, 2406:840:a34::/46,
2406:840:a38::/45, 2406:840:a38::/45,
2406:840:a40::/42, 2406:840:a40::/42,
@@ -2337,7 +2339,10 @@ set clashoo_china6 {
2406:840:e57f::/48, 2406:840:e57f::/48,
2406:840:e580::/41, 2406:840:e580::/41,
2406:840:e610::/44, 2406:840:e610::/44,
2406:840:e620::/43, 2406:840:e622::/47,
2406:840:e624::/46,
2406:840:e628::/45,
2406:840:e630::/44,
2406:840:e640::/43, 2406:840:e640::/43,
2406:840:e660::/46, 2406:840:e660::/46,
2406:840:e664::/47, 2406:840:e664::/47,
@@ -2448,6 +2453,10 @@ set clashoo_china6 {
2406:840:f600::/42, 2406:840:f600::/42,
2406:840:f640::/43, 2406:840:f640::/43,
2406:840:f670::/44, 2406:840:f670::/44,
2406:840:f680::/47,
2406:840:f682::/48,
2406:840:f684::/46,
2406:840:f688::/45,
2406:840:f690::/44, 2406:840:f690::/44,
2406:840:f6a0::/43, 2406:840:f6a0::/43,
2406:840:f6c0::/42, 2406:840:f6c0::/42,
@@ -3039,7 +3048,6 @@ set clashoo_china6 {
2408:4008::/29, 2408:4008::/29,
2408:4010::/30, 2408:4010::/30,
2408:4014::/31, 2408:4014::/31,
2408:4016:1::/48,
2408:4016:2::/47, 2408:4016:2::/47,
2408:4016:4::/46, 2408:4016:4::/46,
2408:4016:8::/45, 2408:4016:8::/45,
@@ -920,7 +920,9 @@ set clashoo_china {
59.153.136.0/22, 59.153.136.0/22,
59.153.152.0/22, 59.153.152.0/22,
59.153.164.0/22, 59.153.164.0/22,
59.153.168.0/21, 59.153.168.0/22,
59.153.173.0/24,
59.153.174.0/23,
59.153.176.0/20, 59.153.176.0/20,
59.153.192.0/22, 59.153.192.0/22,
59.155.0.0/16, 59.155.0.0/16,
@@ -951,6 +953,7 @@ set clashoo_china {
61.29.128.0/18, 61.29.128.0/18,
61.29.192.0/19, 61.29.192.0/19,
61.29.224.0/20, 61.29.224.0/20,
61.29.251.0/24,
61.45.128.0/18, 61.45.128.0/18,
61.45.224.0/20, 61.45.224.0/20,
61.47.128.0/18, 61.47.128.0/18,
@@ -2186,6 +2189,7 @@ set clashoo_china {
103.143.132.0/22, 103.143.132.0/22,
103.143.174.0/23, 103.143.174.0/23,
103.143.228.0/23, 103.143.228.0/23,
103.144.41.0/24,
103.144.66.0/23, 103.144.66.0/23,
103.144.70.0/23, 103.144.70.0/23,
103.144.72.0/23, 103.144.72.0/23,
@@ -2341,7 +2345,7 @@ set clashoo_china {
103.176.244.0/23, 103.176.244.0/23,
103.177.28.0/23, 103.177.28.0/23,
103.177.44.0/23, 103.177.44.0/23,
103.177.70.0/23, 103.177.71.0/24,
103.177.162.0/23, 103.177.162.0/23,
103.178.240.0/23, 103.178.240.0/23,
103.179.76.0/22, 103.179.76.0/22,
@@ -2754,6 +2758,7 @@ set clashoo_china {
103.238.24.0/21, 103.238.24.0/21,
103.238.32.0/21, 103.238.32.0/21,
103.238.40.0/22, 103.238.40.0/22,
103.238.46.0/23,
103.238.48.0/21, 103.238.48.0/21,
103.238.56.0/22, 103.238.56.0/22,
103.238.88.0/21, 103.238.88.0/21,
@@ -3224,7 +3229,10 @@ set clashoo_china {
114.112.228.0/24, 114.112.228.0/24,
114.112.230.0/23, 114.112.230.0/23,
114.112.234.0/23, 114.112.234.0/23,
114.112.240.0/20, 114.112.240.0/21,
114.112.248.0/22,
114.112.252.0/23,
114.112.255.0/24,
114.113.0.0/17, 114.113.0.0/17,
114.113.128.0/21, 114.113.128.0/21,
114.113.140.0/22, 114.113.140.0/22,
@@ -3394,7 +3402,9 @@ set clashoo_china {
117.134.128.0/18, 117.134.128.0/18,
117.134.205.0/24, 117.134.205.0/24,
117.134.207.0/24, 117.134.207.0/24,
117.134.208.0/20, 117.134.208.0/23,
117.134.212.0/23,
117.134.216.0/21,
117.134.232.0/21, 117.134.232.0/21,
117.134.240.0/20, 117.134.240.0/20,
117.135.0.0/16, 117.135.0.0/16,
@@ -3746,7 +3756,6 @@ set clashoo_china {
123.49.236.0/24, 123.49.236.0/24,
123.49.240.0/24, 123.49.240.0/24,
123.49.242.0/23, 123.49.242.0/23,
123.49.245.0/24,
123.49.248.0/21, 123.49.248.0/21,
123.50.160.0/19, 123.50.160.0/19,
123.52.0.0/14, 123.52.0.0/14,
@@ -3981,7 +3990,14 @@ set clashoo_china {
140.179.0.0/16, 140.179.0.0/16,
140.205.0.0/16, 140.205.0.0/16,
140.206.0.0/15, 140.206.0.0/15,
140.210.0.0/16, 140.210.0.0/20,
140.210.16.0/21,
140.210.24.0/22,
140.210.28.0/23,
140.210.30.0/24,
140.210.32.0/19,
140.210.64.0/18,
140.210.128.0/17,
140.224.0.0/16, 140.224.0.0/16,
140.237.0.0/16, 140.237.0.0/16,
140.240.0.0/16, 140.240.0.0/16,
@@ -4214,6 +4230,7 @@ set clashoo_china {
163.47.4.0/22, 163.47.4.0/22,
163.52.28.0/23, 163.52.28.0/23,
163.52.76.0/23, 163.52.76.0/23,
163.52.108.0/23,
163.53.0.0/20, 163.53.0.0/20,
163.53.36.0/22, 163.53.36.0/22,
163.53.40.0/21, 163.53.40.0/21,
Binary file not shown.
Binary file not shown.
+4 -4
View File
@@ -5,13 +5,13 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=dae PKG_NAME:=dae
PKG_VERSION:=2026.09.06 PKG_VERSION:=2026.09.12
PKG_RELEASE:=2 PKG_RELEASE:=1
PKG_SOURCE:=dae-src-2026.09.06-80525dabf966.tar.gz PKG_SOURCE:=dae-src-2026.09.12-187058462a1f.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=80525dabf966403524f3eac4ca46bb520ae487177b77e4b7b4482d24c2aa923e PKG_HASH:=187058462a1fd9eeb9885f4971ccf4bc81358533e71730d8509bd7968624c1c7
PKG_LICENSE:=AGPL-3.0-only PKG_LICENSE:=AGPL-3.0-only
PKG_LICENSE_FILE:=LICENSE PKG_LICENSE_FILE:=LICENSE
+4 -4
View File
@@ -5,13 +5,13 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=daed PKG_NAME:=daed
PKG_VERSION:=2026.09.06 PKG_VERSION:=2026.09.12
PKG_RELEASE:=2 PKG_RELEASE:=1
PKG_SOURCE:=daed-src-2026.09.06-62f2e24ac52a.tar.gz PKG_SOURCE:=daed-src-2026.09.12-a0181f729855.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=62f2e24ac52a6897633d0a0ed43d5a2419164ae43fa26e5c6fe11b5fe973fa61 PKG_HASH:=a0181f7298552497ed193e683a54b1df77f2d5441524d61989f3e3e3cf6eac51
PKG_LICENSE:=AGPL-3.0-only MIT PKG_LICENSE:=AGPL-3.0-only MIT
PKG_LICENSE_FILES:=LICENSE wing/LICENSE PKG_LICENSE_FILES:=LICENSE wing/LICENSE
+83 -4
View File
@@ -1,8 +1,65 @@
#!/bin/sh #!/bin/sh
# daed-cleanup.sh — reaper for stale daed kernel state.
#
# Removes:
# 1. Processes inside the `daens` netns (SIGTERM, then SIGKILL after 1s)
# 2. The `daens` network namespace itself (ip netns del, with
# umount+rm as fallback for zombie nsfs mounts)
# 3. The `dae0` veth pair in the host netns
#
# daed itself owns TC clsact detach. This opkg-side helper only
# reaps stale daens/dae0 state and never removes /sys/fs/bpf/daed.
# The pin directory is created during normal startup, so it is not
# a reliable leak indicator and must not block service lifecycle.
#
# The function stays sourceable by both init.d/daed and daed-guard.
daed_process_probe() {
if command -v pgrep >/dev/null 2>&1; then
pgrep -f '^/usr/bin/daed([[:space:]]|$)' >/dev/null 2>&1
case "$?" in
0) return 0 ;;
1) return 1 ;;
esac
fi
if command -v pidof >/dev/null 2>&1; then
pidof daed >/dev/null 2>&1
case "$?" in
0) return 0 ;;
1) return 1 ;;
esac
fi
return 2
}
daed_cleanup_runtime() { daed_cleanup_runtime() {
local pid local pid rc=0 probe_rc
# If daed userspace is currently running, do not touch the
# netns, the veth, or the eBPF dataplane. They are in active
# use; removing them would make every connection through dae
# hang.
daed_process_probe
probe_rc=$?
case "$probe_rc" in
0)
if [ "${DAED_GUARD_CLEANUP:-start}" = "start" ]; then
logger -t daed-init "cleanup: pre-start skipped because /usr/bin/daed is still running; refusing a second instance"
return 1
fi
logger -t daed-init "cleanup: post-exit skipped because another /usr/bin/daed instance is still running"
return 0
;;
1) ;;
*)
logger -t daed-init "cleanup: cannot determine whether daed is running; refusing to remove netns/veth"
return 1
;;
esac
# 1. Kill processes inside daens.
for pid in $(ip netns pids daens 2>/dev/null); do for pid in $(ip netns pids daens 2>/dev/null); do
kill "$pid" 2>/dev/null kill "$pid" 2>/dev/null
done done
@@ -14,14 +71,36 @@ daed_cleanup_runtime() {
done done
fi fi
# 2. Remove the daens netns. ip netns del can fail if a
# process still references it via /proc/<pid>/ns/net or
# because the umount has already happened. Try the
# umount/rm fallback.
if ! ip netns del daens 2>/dev/null; then if ! ip netns del daens 2>/dev/null; then
umount -l /run/netns/daens 2>/dev/null umount -l /run/netns/daens 2>/dev/null
rm -f /run/netns/daens if [ -e /run/netns/daens ] && ! rm -f /run/netns/daens 2>/dev/null; then
logger -t daed-init "cleanup: failed to remove /run/netns/daens (resource busy); a reboot may be required"
rc=1
fi
fi fi
ip link del dae0 2>/dev/null || true # 3. Remove the dae0 veth pair.
if ip link show dae0 >/dev/null 2>&1; then
if ! ip link del dae0 2>/dev/null; then
logger -t daed-init "cleanup: failed to remove dae0 veth pair"
rc=1
fi
fi
# 4. The pin root is normal persistent state. Never remove it or
# make its existence change the cleanup result.
if [ -e /sys/fs/bpf/daed ]; then
logger -t daed-init "cleanup: /sys/fs/bpf/daed exists; leaving normal pin root unchanged"
fi
# Final verification covers only netns and veth state.
[ ! -e /run/netns/daens ] || return 1 [ ! -e /run/netns/daens ] || return 1
! ip netns list 2>/dev/null | awk '$1 == "daens" { found=1 } END { exit !found }' || return 1 ! ip netns list 2>/dev/null | grep -Eq '^daens([[:space:]]|$)' || return 1
! ip link show dae0 >/dev/null 2>&1 || return 1 ! ip link show dae0 >/dev/null 2>&1 || return 1
return $rc
} }
+117 -15
View File
@@ -1,29 +1,131 @@
#!/bin/sh #!/bin/sh
# Keep daed as a child so signals can be forwarded and stale netns/veth
# state can be cleaned before start and after exit. daed owns TC detach;
# /sys/fs/bpf/daed is normal persistent state and is never removed here.
. /usr/share/daed/cleanup.sh . /usr/share/daed/cleanup.sh
# Pre-start cleanup refuses to remove runtime state while another
# daed instance is active, and fails closed if that probe is broken.
DAED_GUARD_CLEANUP=start
if ! daed_cleanup_runtime; then if ! daed_cleanup_runtime; then
echo "daed: stale network state could not be removed" >&2 echo "daed: stale /usr/bin/daed or netns state could not be verified or removed; refusing to start. Check process and netns state." >&2
logger -t daed-init "pre-start cleanup failed: refusing to start daed"
exit 1 exit 1
fi fi
# Keep daed as a child so a panic or unexpected exit is followed by an # Keep daed as a child so post-exit cleanup runs before procd can
# immediate teardown of all kernel/runtime state before procd can respawn us. # respawn it.
child_pid= child_pid=
cleanup_child() { pending_signal=
[ -n "$child_pid" ] && kill "$child_pid" 2>/dev/null shutdown_signal=
} shutdown_elapsed=0
trap cleanup_child TERM INT forced_kill=0
child_term_timeout=20
forward_signal() {
local sig="$1"
if [ -z "$child_pid" ]; then
pending_signal="$sig"
logger -t daed-init "signal $sig received before daed child started; launch cancelled"
return 0
fi
case "$sig" in
TERM|INT|QUIT)
if [ -z "$shutdown_signal" ]; then
shutdown_signal="$sig"
shutdown_elapsed=0
fi
;;
esac
kill -"$sig" "$child_pid" 2>/dev/null
}
exit_with_signal() {
local sig="$1"
trap - TERM INT HUP QUIT
kill -"$sig" "$$" 2>/dev/null
exit 1
}
child_is_running() {
local state
kill -0 "$child_pid" 2>/dev/null || return 1
state=$(awk '{ print $3 }' "/proc/$child_pid/stat" 2>/dev/null)
[ "$state" != "Z" ]
}
trap 'forward_signal TERM' TERM
trap 'forward_signal INT' INT
trap 'forward_signal HUP' HUP
trap 'forward_signal QUIT' QUIT
start_child() {
local sig
# Keep this check inside the function as well as at the call site:
# it closes the ordinary pre-start window, while the pending-signal
# path below handles a signal arriving during the background fork.
[ -z "$pending_signal" ] || return 125
/usr/bin/daed "$@" & /usr/bin/daed "$@" &
child_pid=$! child_pid=$!
wait "$child_pid" if [ -n "$pending_signal" ]; then
status=$? sig="$pending_signal"
child_pid= pending_signal=
trap - TERM INT forward_signal "$sig"
if ! daed_cleanup_runtime; then
echo "daed: runtime cleanup after exit failed" >&2
status=1
fi fi
}
if [ -n "$pending_signal" ]; then
logger -t daed-init "refusing to start daed after pending signal $pending_signal"
exit_with_signal "$pending_signal"
fi
# Best-effort OOM preference; failure must not block startup.
if ! echo -16 > /proc/self/oom_score_adj 2>/dev/null; then
logger -t daed-init "warn: failed to set /proc/self/oom_score_adj; continuing without OOM preference"
fi
if ! start_child "$@"; then
logger -t daed-init "refusing to start daed after pending signal $pending_signal"
if [ -n "$pending_signal" ]; then
exit_with_signal "$pending_signal"
fi
exit 1
fi
status=0
reaped=0
while [ "$reaped" -eq 0 ]; do
if [ -n "$shutdown_signal" ] && child_is_running; then
if [ "$shutdown_elapsed" -ge "$child_term_timeout" ]; then
if [ "$forced_kill" -eq 0 ]; then
logger -t daed-init "daed did not exit within ${child_term_timeout}s after $shutdown_signal; sending KILL"
kill -KILL "$child_pid" 2>/dev/null
forced_kill=1
fi
else
sleep 1
shutdown_elapsed=$((shutdown_elapsed + 1))
continue
fi
sleep 1
continue
fi
wait "$child_pid" 2>/dev/null
status=$?
if ! child_is_running; then
reaped=1
fi
done
child_pid=
trap - TERM INT HUP QUIT
# Post-exit cleanup runs after the child is reaped.
DAED_GUARD_CLEANUP=post-exit
cleanup_status=0
daed_cleanup_runtime || cleanup_status=$?
if [ "$cleanup_status" -ne 0 ]; then
echo "daed: runtime cleanup after exit failed" >&2
logger -t daed-init "post-exit cleanup failed; check ip netns / ip link show"
fi
if [ "$status" -ne 0 ]; then
exit "$status" exit "$status"
fi
exit "$cleanup_status"
+37 -13
View File
@@ -1,5 +1,7 @@
#!/bin/sh /etc/rc.common #!/bin/sh /etc/rc.common
# Copyright (C) 2023 Tianling Shen <cnsztl@immortalwrt.org> # Copyright (C) 2023 Tianling Shen <cnsztl@immortalwrt.org>
# daed-guard handles bounded child shutdown and post-exit netns/veth cleanup.
# Keep the log file and a pre-stop state snapshot for diagnostics.
USE_PROCD=1 USE_PROCD=1
START=99 START=99
@@ -10,18 +12,28 @@ LOG="/var/log/daed/daed.log"
. /usr/share/daed/cleanup.sh . /usr/share/daed/cleanup.sh
log() {
logger -t daed-init "$@"
}
start_service() { start_service() {
log "start: begin"
config_load "$CONF" config_load "$CONF"
local enabled local enabled
config_get_bool enabled "config" "enabled" "0" config_get_bool enabled "config" "enabled" "0"
[ "$enabled" -eq "1" ] || return 1 if [ "$enabled" -ne "1" ]; then
log "start: config disabled, exit"
return 1
fi
local listen_addr log_maxbackups log_maxsize local listen_addr log_maxbackups log_maxsize
config_get listen_addr "config" "listen_addr" "0.0.0.0:2023" config_get listen_addr "config" "listen_addr" "0.0.0.0:2023"
config_get log_maxbackups "config" "log_maxbackups" "1" config_get log_maxbackups "config" "log_maxbackups" "1"
config_get log_maxsize "config" "log_maxsize" "5" config_get log_maxsize "config" "log_maxsize" "5"
log "start: listen=$listen_addr log_maxbackups=$log_maxbackups log_maxsize=$log_maxsize"
procd_open_instance "$CONF" procd_open_instance "$CONF"
procd_set_param env DAE_LOCATION_ASSET="/usr/share/v2ray" TZ="$(uci -q get system.@system[0].zonename)" procd_set_param env DAE_LOCATION_ASSET="/usr/share/v2ray" TZ="$(uci -q get system.@system[0].zonename)"
procd_set_param command "$PROG" run procd_set_param command "$PROG" run
@@ -33,25 +45,37 @@ start_service() {
procd_set_param limits core="unlimited" procd_set_param limits core="unlimited"
procd_set_param limits nofile="1000000 1000000" procd_set_param limits nofile="1000000 1000000"
# Avoid an endless crash/respawn loop which can repeatedly reattach dae's # daed-guard escalates its child after 20 seconds. Leave time for
# data-plane hooks and make the router management plane unreachable. # reap and post-exit cleanup before procd kills the wrapper.
procd_set_param respawn 3600 5 5 procd_set_param term_timeout 30
# procd_set_param respawn: arguments are (threshold, timeout, retry).
# threshold = runtime that resets the short-lived exit counter
# timeout = seconds to wait between retries
# retry = maximum short-lived exits before procd gives up
# Reset the counter after one hour of stable runtime; otherwise retry
# after 5 seconds and stop after 10 failures.
procd_set_param respawn 3600 5 10
# daed-guard sets oom_score_adj before forking; procd has no
# oom_adj/oom_score_adj parameter.
# procd_set_param stdout 1 # procd_set_param stdout 1
procd_set_param stderr 1 procd_set_param stderr 1
procd_close_instance procd_close_instance
log "start: procd_open_instance done"
} }
stop_service() { stop_service() {
rm -f "$LOG" log "stop: begin"
daed_cleanup_runtime # Cleanup runs in daed-guard after its child exits. Record only a
} # pre-stop snapshot here; pin entries do not prove TC attachment.
local pinned="" ns_left=""
restart() { if [ -d /sys/fs/bpf/daed ]; then
stop pinned=$(ls /sys/fs/bpf/daed 2>/dev/null | tr '\n' ' ')
sleep 1 fi
daed_cleanup_runtime if ip netns list 2>/dev/null | grep -q '^daens'; then
start ns_left="daens"
fi
log "stop: pre-stop state — bpf_pin_entries=[${pinned:-none}] netns_left=[${ns_left:-none}]"
} }
service_triggers() { service_triggers() {
+11 -9
View File
@@ -1,8 +1,6 @@
# SPDX-License-Identifier: GPL-3.0-only # SPDX-License-Identifier: GPL-3.0-only
# #
# Copyright (C) 2021-2023 sirpdboy <herboy2008@gmail.com> # Copyright (C) 2021-2026 sirpdboy <herboy2008@gmail.com>
#
# This is free software, licensed under the Apache License, Version 2.0 .
# #
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
@@ -10,12 +8,12 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=ddns-go PKG_NAME:=ddns-go
PKG_VERSION:=6.17.7 PKG_VERSION:=6.17.7
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_VERSION:=6.17.7
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/jeessy2/ddns-go/tar.gz/v$(PKG_VERSION)? PKG_SOURCE_URL:=https://codeload.github.com/jeessy2/ddns-go/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=f7001004e092d9641aad5a94158e0b4cae4a53a7f5c7d96d5c6af3d246c56fcc PKG_HASH:=f7001004e092d9641aad5a94158e0b4cae4a53a7f5c7d96d5c6af3d246c56fcc
PKG_LICENSE:=MIT PKG_HASH:=f7001004e092d9641aad5a94158e0b4cae4a53a7f5c7d96d5c6af3d246c56fcc
PKG_LICENSE_FILES:=LICENSE PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org> PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
@@ -44,14 +42,18 @@ define Package/ddns-go/description
support Alidns Dnspod Cloudflare Hicloud Callback Baiducloud porkbun GoDaddy Google Domains. support Alidns Dnspod Cloudflare Hicloud Callback Baiducloud porkbun GoDaddy Google Domains.
endef endef
define Package/ddns-go/conffiles
/etc/config/ddns-go
/etc/ddns-go/ddns-go-config.yaml
endef
define Package/ddns-go/install define Package/ddns-go/install
$(call GoPackage/Package/Install/Bin,$(1)) $(call GoPackage/Package/Install/Bin,$(1))
$(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) $(CURDIR)/file/ddns-go.init $(1)/etc/init.d/ddns-go $(INSTALL_DIR) $(1)/etc/config
$(INSTALL_BIN) $(CURDIR)/files/ddns-go.init $(1)/etc/init.d/ddns-go
$(INSTALL_DIR) $(1)/etc/uci-defaults $(INSTALL_CONF) $(CURDIR)/files/ddns-go.conf $(1)/etc/config/ddns-go
$(INSTALL_BIN) $(CURDIR)/file/luci-ddns-go.uci-default $(1)/etc/uci-defaults/luci-ddns-go
endef endef
$(eval $(call GoBinPackage,ddns-go)) $(eval $(call GoBinPackage,ddns-go))
-46
View File
@@ -1,46 +0,0 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2021-2023 sirpdboy <herboy2008@gmail.com> https://github.com/sirpdboy/luci-app-ddns-go
#
# This file is part of ddns-go .
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
START=99
USE_PROCD=1
PROG=/usr/bin/ddns-go
CONFDIR=/etc/ddns-go
CONF=$CONFDIR/ddns-go-config.yaml
get_config() {
config_get_bool enabled $1 enabled 1
config_get_bool logger $1 logger 1
config_get port $1 port 9876
config_get time $1 time 300
}
init_yaml(){
[ -d $CONFDIR ] || mkdir -p $CONFDIR 2>/dev/null
cat /usr/share/ddns-go/ddns-go-default.yaml > $CONF
}
start_service() {
config_load ddns-go
config_foreach get_config basic
[ x$enabled == x1 ] || return 1
[ -s ${CONF} ] || init_yaml
logger -t ddns-go -p warn "ddns-go is start."
echo "ddns-go is start."
procd_open_instance
procd_set_param command $PROG -l :$port -f $time -c "$CONF"
[ "x$logger" == x1 ] && procd_set_param stderr 1
procd_set_param respawn
procd_close_instance
}
service_triggers() {
procd_add_reload_trigger "ddns-go"
}
-7
View File
@@ -1,7 +0,0 @@
#!/bin/sh
[ -s "/etc/ddns-go/localtime" ] && mv -f /etc/ddns-go/localtime /etc/localtime
/etc/init.d/ddns-go enable
/etc/init.d/ddns-go start
rm -f /tmp/luci*
exit 0
+9
View File
@@ -0,0 +1,9 @@
config basic 'config'
option enabled '0'
option logger '1'
option port '9876'
option time '300'
option ctimes '5'
option skipverify '0'
option delay '0'
option dns '223.5.5.5'
+85
View File
@@ -0,0 +1,85 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2021-2026 sirpdboy <herboy2008@gmail.com>
#
# This file is part of ddns-go .
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
START=99
USE_PROCD=1
NAME=ddns-go
PROG=/usr/bin/ddns-go
CONFDIR=/etc/ddns-go
CONF=$CONFDIR/ddns-go-config.yaml
init_yaml() {
[ -d "$CONFDIR" ] || mkdir -p "$CONFDIR"
chown -R ddns-go:ddns-go "$CONFDIR"
chmod 755 "$CONFDIR"
[ -f "$CONF" ] && chmod 644 "$CONF"
}
build_args() {
local cfg="$1"
local args="-c $CONF"
config_get port "$cfg" port '9876'
args="$args -l :$port"
config_get time "$cfg" time '300'
[ -n "$time" ] && args="$args -f $time"
config_get ctimes "$cfg" ctimes '5'
[ -n "$ctimes" ] && args="$args -cacheTimes $ctimes"
config_get dns "$cfg" dns '223.5.5.5'
[ -n "$dns" ] && args="$args -dns $dns"
config_get_bool noweb "$cfg" noweb 0
[ "$noweb" -eq 1 ] && args="$args -noweb"
config_get_bool skipverify "$cfg" skipverify 0
[ "$skipverify" -eq 1 ] && args="$args -skipVerify"
echo "$args"
}
start_instance() {
local cfg="$1"
local logger
config_get_bool enabled "$cfg" enabled 0
[ "$enabled" -eq 0 ] && return 0
config_get delay "$cfg" delay 0
if [ "$delay" -gt 0 ]; then
local uptime=$(awk -F. '{print $1}' /proc/uptime)
[ "$uptime" -lt 120 ] && sleep "$delay"
fi
init_yaml
local args=$(build_args "$cfg")
procd_open_instance
procd_set_param command $PROG $args
config_get_bool logger "$cfg" logger 1
procd_set_param stdout "$logger"
procd_set_param stderr "$logger"
procd_set_param user ddns-go
procd_set_param respawn
procd_close_instance
}
start_service() {
config_load "$NAME"
config_foreach start_instance 'basic'
}
service_triggers() {
procd_add_reload_trigger "$NAME"
}
+1 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-clashoo PKG_NAME:=luci-app-clashoo
PKG_VERSION:=1.30.0 PKG_VERSION:=1.30.0
PKG_RELEASE:=14 PKG_RELEASE:=15
PKG_MAINTAINER:=kenzok8 PKG_MAINTAINER:=kenzok8
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
@@ -1135,7 +1135,7 @@ return '_merged_' + s + '__' + t + '.yaml';
} }
function template_search_dirs() { function template_search_dirs() {
return [TEMPLATE_USER_DIR, TEMPLATE_DIR, '/usr/share/clashoo/config/template']; return [TEMPLATE_DIR, '/usr/share/clashoo/config/template'];
} }
function find_template_path(name) { function find_template_path(name) {
@@ -3318,6 +3318,8 @@ call: function(req) {
let tpl_src = trim(req.args?.template_source || ''); let tpl_src = trim(req.args?.template_source || '');
let sub_url = trim(req.args?.sub_url || ''); let sub_url = trim(req.args?.sub_url || '');
let output_name = ensure_yaml_name(req.args?.output_name || ''); let output_name = ensure_yaml_name(req.args?.output_name || '');
if (!output_name) output_name = 'tpl-rewrite.yaml';
let uniq_name = replace(output_name, /\.(yaml|yml)$/, '');
let set_active = (req.args?.set_active || '') == '1'; let set_active = (req.args?.set_active || '') == '1';
if (!tpl_src) if (!tpl_src)
@@ -3361,9 +3363,9 @@ return { success: false, error: 'missing_yq', message: '缺少 yq,无法注入
if (!access(exploded, "r")) { if (!access(exploded, "r")) {
system("cp -f " + shell_quote(tmp_tpl) + " " + shell_quote(exploded)); system("cp -f " + shell_quote(tmp_tpl) + " " + shell_quote(exploded));
} }
/* 替换 proxy-providers.urlrule-providers 指向规则集保持原样 */ /* 替换 proxy-providers.url 并把 provider 名改成唯一名(同步 proxy-groups 的 use*/
let inject_cmd = "URL=" + shell_quote(sub_url) let inject_cmd = "URL=" + shell_quote(sub_url) + " NAME=" + shell_quote(uniq_name)
+ " yq e '.[\"proxy-providers\"][].url = env(URL)' " + " yq e '.[\"proxy-providers\"][].url = env(URL) | (.[\"proxy-providers\"] | keys | map({\"key\": ., \"value\": strenv(NAME) + \"-\" + .}) | from_entries) as $rename | .[\"proxy-providers\"] |= with_entries(.key = $rename[.key]) | (.[\"proxy-groups\"][] | select(has(\"use\")) | .use) |= map($rename[.] // .)' "
+ shell_quote(exploded) + " > " + shell_quote(tmp_out); + shell_quote(exploded) + " > " + shell_quote(tmp_out);
if (system(inject_cmd) != 0 || !access(tmp_out, "r")) { if (system(inject_cmd) != 0 || !access(tmp_out, "r")) {
system("rm -f " + shell_quote(exploded)); system("rm -f " + shell_quote(exploded));
@@ -3371,10 +3373,6 @@ return { success: false, error: 'missing_yq', message: '缺少 yq,无法注入
} }
system("rm -f " + shell_quote(exploded)); system("rm -f " + shell_quote(exploded));
if (!output_name) {
output_name = 'tpl-rewrite.yaml';
}
let out_path = out_dir + '/' + output_name; let out_path = out_dir + '/' + output_name;
if (system('mv -f ' + shell_quote(tmp_out) + ' ' + shell_quote(out_path)) != 0) if (system('mv -f ' + shell_quote(tmp_out) + ' ' + shell_quote(out_path)) != 0)
return { success: false, error: 'write_failed', message: '写入结果文件失败' }; return { success: false, error: 'write_failed', message: '写入结果文件失败' };
@@ -3382,16 +3380,16 @@ return { success: false, error: 'write_failed', message: '写入结果文件失
/* 删除 respect-rules(模板可能设了但没提供 proxy-server-nameserver */ /* 删除 respect-rules(模板可能设了但没提供 proxy-server-nameserver */
system("sed -i '/respect-rules/d' " + shell_quote(out_path) + " 2>/dev/null"); system("sed -i '/respect-rules/d' " + shell_quote(out_path) + " 2>/dev/null");
system('rm -f ' + shell_quote(tmp_tpl)); system('rm -f ' + shell_quote(tmp_tpl));
/* 替换 直连→DIRECT(兼容不同模板的命名差异) */ /* 只把独立引用项"直连"转成 DIRECT,组名里的"直连"不动 */
system("sed -i 's/直连/DIRECT/g' " + shell_quote(out_path) + " 2>/dev/null"); system("sed -i 's/^\\( *- *\\)直连$/\\1DIRECT/' " + shell_quote(out_path) + " 2>/dev/null");
system("yq e '(.proxy-groups[].proxies) |= sub(\"直连\", \"DIRECT\")' " + shell_quote(out_path) + " -i 2>/dev/null"); system("yq e '(.proxy-groups[] | select(has(\"proxies\")) | .proxies) |= map(sub(\"^直连$\", \"DIRECT\"))' " + shell_quote(out_path) + " -i 2>/dev/null");
/* 用 mixin.uc + yq merge 叠加 UCI 覆盖(端口、routing-mark、dns 等) */ /* 用 mixin.uc + yq merge 叠加 UCI 覆盖(端口、routing-mark、dns 等) */
let mixin_script = "/usr/share/clashoo/runtime/mixin.uc"; let mixin_script = "/usr/share/clashoo/runtime/mixin.uc";
if (access(mixin_script, "r") && system("command -v yq >/dev/null 2>&1") == 0) { if (access(mixin_script, "r") && system("command -v yq >/dev/null 2>&1") == 0) {
let mixin_yaml = "/tmp/_clashoo_mixin.yaml"; let mixin_yaml = "/tmp/_clashoo_mixin.yaml";
let merged_out = out_path + ".merged"; let merged_out = out_path + ".merged";
system("ucode " + shell_quote(mixin_script) + " 2>/dev/null | yq -M -p json -o yaml > " + shell_quote(mixin_yaml) + " 2>/dev/null"); system("ucode " + shell_quote(mixin_script) + " 2>/dev/null | yq -M -p json -o yaml > " + shell_quote(mixin_yaml) + " 2>/dev/null");
system("yq -M eval-all '. as $item ireduce ({}; . * $item)' " + shell_quote(out_path) + " " + shell_quote(mixin_yaml) + " > " + shell_quote(merged_out) + " 2>/dev/null"); system("yq -M eval-all '(. as $item ireduce ({}; . * $item)) as $m | [\"port\",\"socks-port\",\"redir-port\",\"tproxy-port\",\"mixed-port\",\"allow-lan\",\"bind-address\",\"mode\",\"log-level\",\"ipv6\",\"interface-name\",\"routing-mark\",\"external-controller\",\"external-ui\",\"secret\",\"tun\",\"listeners\",\"tunnels\",\"dns\",\"hosts\",\"profile\",\"geodata-mode\",\"geodata-loader\",\"geox-url\",\"proxy-providers\",\"proxies\",\"proxy-groups\",\"rule-providers\",\"rules\",\"sub-rules\",\"ntp\",\"authentication\",\"sniffer\",\"experimental\"] as $order | ($order | to_entries | map({\"key\": .value, \"value\": .key}) | from_entries) as $rank | $m | to_entries | sort_by(.key as $k | $rank[$k] // 999) | from_entries' " + shell_quote(out_path) + " " + shell_quote(mixin_yaml) + " > " + shell_quote(merged_out) + " 2>/dev/null");
if (access(merged_out, "r")) { if (access(merged_out, "r")) {
system("mv -f " + shell_quote(merged_out) + " " + shell_quote(out_path)); system("mv -f " + shell_quote(merged_out) + " " + shell_quote(out_path));
} }
@@ -72,7 +72,7 @@ function get_adlist() {
let adblock = uci_cursor.get('mosdns', 'config', 'adblock'); let adblock = uci_cursor.get('mosdns', 'config', 'adblock');
if (adblock !== '1') { if (adblock !== '1') {
mkdir('/etc/mosdns/rule', 0755); mkdir('/var/mosdns', 0755);
exec_sys('rm -rf /etc/mosdns/rule/adlist /etc/mosdns/rule/.ad_source'); exec_sys('rm -rf /etc/mosdns/rule/adlist /etc/mosdns/rule/.ad_source');
writefile('/var/mosdns/disable-ads.txt', ''); writefile('/var/mosdns/disable-ads.txt', '');
print("/var/mosdns/disable-ads.txt\n"); print("/var/mosdns/disable-ads.txt\n");
@@ -612,21 +612,46 @@ o:value("info", "Info")
o:value("warn", "Warning") o:value("warn", "Warning")
o:value("error", "Error") o:value("error", "Error")
o = s:taboption("log", Flag, "advanced_log_feature", translate("Advanced log feature"), translate("For professionals only.")) o = s:taboption("log", DummyValue, "_node_log", translate("Log File"))
o.default = "0" o.rawhtml = true
o = s:taboption("log", Flag, "sys_log", translate("Logging to system log"), translate("Logging to the system log for more advanced functions. For example, send logs to a dedicated log server.")) o.cfgvalue = function(t, n)
o:depends("advanced_log_feature", "1") local log_file = api.TMP_PATH .. "/acl/default/global.log"
o.default = "0" local log_url = api.url("get_redir_log") .. "?id=default"
o = s:taboption("log", Value, "persist_log_path", translate("Persist log file directory"), translate("The path to the directory used to store persist log files, the \"/\" at the end can be omitted. Leave it blank to disable this feature.")) local s = "<code>%s</code>&nbsp;&nbsp;" % log_file
o:depends({ ["advanced_log_feature"] = 1, ["sys_log"] = 0 }) if api.fs.access(log_file) then
o = s:taboption("log", Value, "log_event_filter", translate("Log Event Filter"), translate("Support regular expression.")) local btn = string.format(
o:depends("advanced_log_feature", "1") '<input class="btn cbi-button cbi-button-apply" type="button" value="%s" onclick="window.open(\'%s\', \'_blank\')" />',
o = s:taboption("log", Value, "log_event_cmd", translate("Shell Command"), translate("Shell command to execute, replace log content with %s.")) translate("View Log"),
o:depends("advanced_log_feature", "1") log_url
)
s = s .. btn
end
return s
end
o:depends("log_node", "1")
o = s:taboption("log", Flag, "log_chinadns_ng", translate("Enable") .. " ChinaDNS-NG " .. translate("Log")) o = s:taboption("log", Flag, "log_chinadns_ng", translate("Enable") .. " ChinaDNS-NG " .. translate("Log"))
o.default = "0" o.default = "0"
o.rmempty = false o.rmempty = false
o:depends("dns_shunt", "chinadns-ng")
o = s:taboption("log", DummyValue, "_chinadns_ng_log", translate("Log File"))
o.rawhtml = true
o.cfgvalue = function(t, n)
local log_file = api.TMP_PATH .. "/acl/default/chinadns_ng.log"
local log_url = api.url("get_chinadns_log") .. "?flag=default"
local s = "<code>%s</code>&nbsp;&nbsp;" % log_file
if api.fs.access(log_file) then
local btn = string.format(
'<input class="btn cbi-button cbi-button-apply" type="button" value="%s" onclick="window.open(\'%s\', \'_blank\')" />',
translate("View Log"),
log_url
)
s = s .. btn
end
return s
end
o:depends("log_chinadns_ng", "1")
o = s:taboption("log", DummyValue, "_log_tips", " ") o = s:taboption("log", DummyValue, "_log_tips", " ")
o.rawhtml = true o.rawhtml = true
+14 -2
View File
@@ -163,12 +163,16 @@ function sh_uci_commit(config)
exec_call(string.format("uci -q commit %s", config)) exec_call(string.format("uci -q commit %s", config))
end end
function del_cache_var(key)
sys.call(string.format('. /usr/share/passwall2/utils.sh ; del_cache_var "%s"', key))
end
function set_cache_var(key, val) function set_cache_var(key, val)
sys.call(string.format('. /usr/share/passwall/utils.sh ; set_cache_var %s "%s"', key, val)) sys.call(string.format('. /usr/share/passwall/utils.sh ; set_cache_var "%s" "%s"', key, val))
end end
function get_cache_var(key) function get_cache_var(key)
local val = sys.exec(string.format('. /usr/share/passwall/utils.sh ; echo -n $(get_cache_var %s)', key)) local val = sys.exec(string.format('. /usr/share/passwall/utils.sh ; echo -n $(get_cache_var "%s")', key))
if val == "" then val = nil end if val == "" then val = nil end
return val return val
end end
@@ -2072,3 +2076,11 @@ function gen_wireguard_key()
} }
end end
end end
function get_socks_port_by_cache(node_id)
return get_cache_var("node_%s_socks_port" % { node_id })
end
function set_socks_port_to_cache(node_id, v)
set_cache_var("node_%s_socks_port" % { node_id }, v)
end
@@ -93,25 +93,39 @@ function gen_outbound(flag, node, tag, proxy_table)
end end
local remarks = node.remarks local remarks = node.remarks
local proxy_tag = nil local proxy_tag, fragment, record_fragment
local fragment = nil
local record_fragment = nil
local run_socks_instance = true
if proxy_table ~= nil and type(proxy_table) == "table" then if proxy_table ~= nil and type(proxy_table) == "table" then
proxy_tag = proxy_table.tag or nil proxy_tag = proxy_table.tag or nil
fragment = (proxy_table.fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil fragment = (proxy_table.fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil
record_fragment = (proxy_table.record_fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil record_fragment = (proxy_table.record_fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil
run_socks_instance = proxy_table.run_socks_instance
end end
if node.type ~= "sing-box" then if node.type ~= "sing-box" then
local relay_port = node.port if node.type == "Socks" then
local new_port = api.get_new_port() node.protocol = "socks"
local config_file = string.format("%s_%s_%s.json", flag, tag, new_port) proxy_tag = "socks <- " .. node_id
if tag and node_id and not tag:find(node_id) then else
config_file = string.format("%s_%s_%s_%s.json", flag, tag, node_id, new_port) local new_port
local run_socks_instance = true
if NO_RUN then
TMP_PORT = TMP_PORT and TMP_PORT + 1 or 3001
new_port = TMP_PORT
run_socks_instance = nil
else
local relay_port = (proxy_tag and node.port) and tostring(node.port) or ""
if relay_port == "" then
local cache = api.get_socks_port_by_cache(node_id)
if cache then
new_port = cache
run_socks_instance = nil
end
end end
if run_socks_instance then if run_socks_instance then
new_port = api.get_new_port()
local config_file = string.format("nodesocks_%s_%s.json", node_id, new_port)
if tag and node_id and not tag:find(node_id) then
config_file = string.format("nodesocks_%s_%s_%s.json", tag, node_id, new_port)
end
sys.call(string.format('/usr/share/passwall/app.sh run_socks "%s"> /dev/null', sys.call(string.format('/usr/share/passwall/app.sh run_socks "%s"> /dev/null',
string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s", string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s",
new_port, --flag new_port, --flag
@@ -119,17 +133,24 @@ function gen_outbound(flag, node, tag, proxy_table)
"127.0.0.1", --bind "127.0.0.1", --bind
new_port, --socks port new_port, --socks port
config_file, --config file config_file, --config file
(proxy_tag and relay_port) and tostring(relay_port) or "" --relay port relay_port --relay port
) )
) )
) )
if relay_port == "" then
api.set_socks_port_to_cache(node_id, new_port)
end end
end
end
if new_port then
node = { node = {
protocol = "socks", protocol = "socks",
address = "127.0.0.1", address = "127.0.0.1",
port = new_port port = new_port
} }
proxy_tag = "socks <- " .. node_id proxy_tag = "socks <- " .. node_id
end
end
else else
if proxy_tag then if proxy_tag then
node.detour = proxy_tag node.detour = proxy_tag
@@ -1140,10 +1161,11 @@ function gen_config(var)
local dns_cache = var["dns_cache"] local dns_cache = var["dns_cache"]
local dns_socks_address = var["dns_socks_address"] local dns_socks_address = var["dns_socks_address"]
local dns_socks_port = var["dns_socks_port"] local dns_socks_port = var["dns_socks_port"]
local no_run = var["no_run"]
local use_proxy_list = var["use_proxy_list"] local use_proxy_list = var["use_proxy_list"]
local use_gfw_list = var["use_gfw_list"] local use_gfw_list = var["use_gfw_list"]
local chn_list = var["chn_list"] local chn_list = var["chn_list"]
local run_in_global = var["run_in_global"]
NO_RUN = var["no_run"]
local dns_domain_rules = {} local dns_domain_rules = {}
local dns = nil local dns = nil
@@ -1337,7 +1359,9 @@ function gen_config(var)
ut_nodes = _node.urltest_node ut_nodes = _node.urltest_node
end end
-- api.log(" - 加载 Sing-Box URLTest 节点【" .. (_node.remarks or "") .. "】,子节点数量:" .. #(ut_nodes or {})) if not NO_RUN and run_in_global then
api.log(" - 加载 Sing-Box URLTest 节点【" .. (_node.remarks or "") .. "】,子节点数量:" .. #(ut_nodes or {}))
end
local valid_nodes = {} local valid_nodes = {}
for i = 1, #(ut_nodes or {}) do for i = 1, #(ut_nodes or {}) do
@@ -1352,7 +1376,7 @@ function gen_config(var)
end end
end end
if is_new_ut_node then if is_new_ut_node then
local outboundTag = gen_outbound_get_tag(flag, ut_node_id, ut_node_tag, { fragment = singbox_settings.fragment == "1" or nil, record_fragment = singbox_settings.record_fragment == "1" or nil, run_socks_instance = not no_run }) local outboundTag = gen_outbound_get_tag(flag, ut_node_id, ut_node_tag, { fragment = singbox_settings.fragment == "1" or nil, record_fragment = singbox_settings.record_fragment == "1" or nil })
if outboundTag then if outboundTag then
valid_nodes[#valid_nodes + 1] = outboundTag valid_nodes[#valid_nodes + 1] = outboundTag
end end
@@ -1455,7 +1479,6 @@ function gen_config(var)
to_node.port = new_port to_node.port = new_port
to_outbound = gen_outbound(node[".name"], to_node, tag, { to_outbound = gen_outbound(node[".name"], to_node, tag, {
tag = tag, tag = tag,
run_socks_instance = not no_run
}) })
else else
to_outbound = gen_outbound(node[".name"], to_node) to_outbound = gen_outbound(node[".name"], to_node)
@@ -1548,7 +1571,6 @@ function gen_config(var)
local proxy_table = { local proxy_table = {
fragment = singbox_settings.fragment == "1", fragment = singbox_settings.fragment == "1",
record_fragment = singbox_settings.record_fragment == "1", record_fragment = singbox_settings.record_fragment == "1",
run_socks_instance = not no_run,
} }
local preproxy_node_id = node[rule_name .. "_proxy_tag"] local preproxy_node_id = node[rule_name .. "_proxy_tag"]
if preproxy_node_id == _node_id then preproxy_node_id = nil end if preproxy_node_id == _node_id then preproxy_node_id = nil end
@@ -1832,7 +1854,6 @@ function gen_config(var)
COMMON.default_outbound_tag = gen_outbound_get_tag(flag, node or node_id, nil, { COMMON.default_outbound_tag = gen_outbound_get_tag(flag, node or node_id, nil, {
fragment = singbox_settings.fragment == "1" or nil, fragment = singbox_settings.fragment == "1" or nil,
record_fragment = singbox_settings.record_fragment == "1" or nil, record_fragment = singbox_settings.record_fragment == "1" or nil,
run_socks_instance = not no_run
}) })
end end
@@ -2293,7 +2314,7 @@ function gen_config(var)
routing_mark = 255, routing_mark = 255,
}) })
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
if not value["_flag_proxy_tag"] and not value.detour and value["_id"] and value.server and (value.server_port or value.server_ports) and not no_run then if not value["_flag_proxy_tag"] and not value.detour and value["_id"] and value.server and (value.server_port or value.server_ports) and not NO_RUN then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list")) sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end end
if not value.detour and not value.bind_interface and value.server then if not value.detour and not value.bind_interface and value.server then
@@ -2441,7 +2462,7 @@ if arg[1] then
var = jsonc.parse(arg[2]) var = jsonc.parse(arg[2])
end end
print(func(var)) print(func(var))
if (next(GEO_VAR.SITE_TAGS) or next(GEO_VAR.IP_TAGS)) and not no_run then if (next(GEO_VAR.SITE_TAGS) or next(GEO_VAR.IP_TAGS)) and not NO_RUN then
convert_geofile() convert_geofile()
end end
end end
+59 -42
View File
@@ -12,7 +12,7 @@ local GLOBAL = {
local xray_version = api.get_app_version("xray") local xray_version = api.get_app_version("xray")
local xray_min_version = "26.3.27" local xray_min_version = "26.7.11"
local function get_domain_excluded() local function get_domain_excluded()
local path = string.format("/usr/share/%s/rules/domains_excluded", api.c_config) local path = string.format("/usr/share/%s/rules/domains_excluded", api.c_config)
@@ -43,30 +43,39 @@ function gen_outbound(flag, node, tag, proxy_table)
end end
local remarks = node.remarks local remarks = node.remarks
local proxy_tag = nil local proxy_tag, dialer_proxy_tag, fragment, noise
local dialer_proxy_tag = nil
local fragment = nil
local noise = nil
local run_socks_instance = true
if proxy_table ~= nil and type(proxy_table) == "table" then if proxy_table ~= nil and type(proxy_table) == "table" then
proxy_tag = proxy_table.tag or nil proxy_tag = proxy_table.tag or nil
fragment = (proxy_table.fragment and not node.hysteria2_realms) and true or nil fragment = (proxy_table.fragment and not node.hysteria2_realms) and true or nil
noise = (proxy_table.noise and not node.hysteria2_realms) and true or nil noise = (proxy_table.noise and not node.hysteria2_realms) and true or nil
run_socks_instance = proxy_table.run_socks_instance
end end
if node.type ~= "Xray" then if node.type ~= "Xray" then
if node.type == "Socks" then if node.type == "Socks" then
node.protocol = "socks" node.protocol = "socks"
node.transport = "tcp" node.transport = "raw"
else else
local relay_port = node.port local new_port
local new_port = api.get_new_port() local run_socks_instance = true
local config_file = string.format("%s_%s_%s.json", flag, tag, new_port) if NO_RUN then
if tag and node_id and not tag:find(node_id) then TMP_PORT = TMP_PORT and TMP_PORT + 1 or 3001
config_file = string.format("%s_%s_%s_%s.json", flag, tag, node_id, new_port) new_port = TMP_PORT
run_socks_instance = nil
else
local relay_port = (proxy_tag and node.port) and tostring(node.port) or ""
if relay_port == "" then
local cache = api.get_socks_port_by_cache(node_id)
if cache then
new_port = cache
run_socks_instance = nil
end
end end
if run_socks_instance then if run_socks_instance then
new_port = api.get_new_port()
local config_file = string.format("nodesocks_%s_%s.json", node_id, new_port)
if tag and node_id and not tag:find(node_id) then
config_file = string.format("nodesocks_%s_%s_%s.json", tag, node_id, new_port)
end
sys.call(string.format('/usr/share/passwall/app.sh run_socks "%s"> /dev/null', sys.call(string.format('/usr/share/passwall/app.sh run_socks "%s"> /dev/null',
string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s", string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s",
new_port, --flag new_port, --flag
@@ -74,16 +83,23 @@ function gen_outbound(flag, node, tag, proxy_table)
"127.0.0.1", --bind "127.0.0.1", --bind
new_port, --socks port new_port, --socks port
config_file, --config file config_file, --config file
(proxy_tag and relay_port) and tostring(relay_port) or "" --relay port relay_port --relay port
) )
)) )
)
if relay_port == "" then
api.set_socks_port_to_cache(node_id, new_port)
end end
end
end
if new_port then
node = {} node = {}
node.protocol = "socks" node.protocol = "socks"
node.transport = "tcp" node.transport = "raw"
node.address = "127.0.0.1" node.address = "127.0.0.1"
node.port = new_port node.port = new_port
end end
end
node.stream_security = "none" node.stream_security = "none"
proxy_tag = "socks <- " .. node_id proxy_tag = "socks <- " .. node_id
else else
@@ -156,7 +172,7 @@ function gen_outbound(flag, node, tag, proxy_table)
} or nil, } or nil,
dialerProxy = dialer_proxy_tag, dialerProxy = dialer_proxy_tag,
}, },
[(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network" method = node.transport,
security = node.stream_security, security = node.stream_security,
tlsSettings = (node.stream_security == "tls") and { tlsSettings = (node.stream_security == "tls") and {
serverName = node.tls_serverName, serverName = node.tls_serverName,
@@ -675,7 +691,7 @@ function gen_config_server(node)
protocol = node.protocol, protocol = node.protocol,
settings = settings, settings = settings,
streamSettings = { streamSettings = {
[(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network" method = node.transport,
security = "none", security = "none",
tlsSettings = ("1" == node.tls) and { tlsSettings = ("1" == node.tls) and {
disableSystemRoot = false, disableSystemRoot = false,
@@ -857,9 +873,6 @@ function gen_config_server(node)
config.outbounds[index][k] = nil config.outbounds[index][k] = nil
end end
end end
if value.protocol == "freedom" and api.compare_versions(xray_version, "<", "26.5.3") then -- Todo is to remove it
value.settings = nil
end
end end
return config return config
@@ -897,10 +910,11 @@ function gen_config(var)
local dns_socks_address = var["dns_socks_address"] local dns_socks_address = var["dns_socks_address"]
local dns_socks_port = var["dns_socks_port"] local dns_socks_port = var["dns_socks_port"]
local loglevel = var["loglevel"] or "warning" local loglevel = var["loglevel"] or "warning"
local no_run = var["no_run"]
local use_proxy_list = var["use_proxy_list"] local use_proxy_list = var["use_proxy_list"]
local use_gfw_list = var["use_gfw_list"] local use_gfw_list = var["use_gfw_list"]
local chn_list = var["chn_list"] local chn_list = var["chn_list"]
local run_in_global = var["run_in_global"]
NO_RUN = var["no_run"]
local dns_domain_rules = {} local dns_domain_rules = {}
local dns = nil local dns = nil
@@ -1075,7 +1089,9 @@ function gen_config(var)
blc_nodes = _node.balancing_node blc_nodes = _node.balancing_node
end end
-- api.log(" - 加载 Xray 负载均衡 节点【" .. (_node.remarks or "") .. "】,子节点数量:" .. #(blc_nodes or {})) if not NO_RUN and run_in_global then
api.log(" - 加载 Xray 负载均衡 节点【" .. (_node.remarks or "") .. "】,子节点数量:" .. #(blc_nodes or {}))
end
local valid_nodes = {} local valid_nodes = {}
for i = 1, #(blc_nodes or {}) do for i = 1, #(blc_nodes or {}) do
@@ -1090,7 +1106,7 @@ function gen_config(var)
end end
end end
if is_new_blc_node then if is_new_blc_node then
local outboundTag = gen_outbound_get_tag(flag, blc_node_id, blc_node_tag, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.noise == "1" or nil, run_socks_instance = not no_run }) local outboundTag = gen_outbound_get_tag(flag, blc_node_id, blc_node_tag, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.noise == "1" or nil })
if outboundTag then if outboundTag then
valid_nodes[#valid_nodes + 1] = outboundTag valid_nodes[#valid_nodes + 1] = outboundTag
end end
@@ -1119,7 +1135,7 @@ function gen_config(var)
local fallback_node = get_node_by_id(fallback_node_id) local fallback_node = get_node_by_id(fallback_node_id)
if fallback_node then if fallback_node then
if fallback_node.protocol ~= "_balancing" then if fallback_node.protocol ~= "_balancing" then
local outboundTag = gen_outbound_get_tag(flag, fallback_node, fallback_node_id, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.noise == "1" or nil, run_socks_instance = not no_run }) local outboundTag = gen_outbound_get_tag(flag, fallback_node, fallback_node_id, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.noise == "1" or nil })
if outboundTag then if outboundTag then
fallback_node_tag = outboundTag fallback_node_tag = outboundTag
end end
@@ -1251,7 +1267,6 @@ function gen_config(var)
}) })
to_outbound = gen_outbound(node[".name"], to_node, to_node[".name"], { to_outbound = gen_outbound(node[".name"], to_node, to_node[".name"], {
tag = to_node[".name"], tag = to_node[".name"],
run_socks_instance = not no_run
}) })
else else
to_outbound = gen_outbound(node[".name"], to_node) to_outbound = gen_outbound(node[".name"], to_node)
@@ -1316,9 +1331,9 @@ function gen_config(var)
interface = node.iface interface = node.iface
} }
}, },
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check settings = {
finalRules = {{ action = "allow" }} finalRules = {{ action = "allow" }}
} or nil }
} }
sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface)) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface))
end end
@@ -1359,7 +1374,6 @@ function gen_config(var)
local proxy_table = { local proxy_table = {
fragment = xray_settings.fragment == "1", fragment = xray_settings.fragment == "1",
noise = xray_settings.noise == "1", noise = xray_settings.noise == "1",
run_socks_instance = not no_run,
} }
local preproxy_node_id = node[rule_name .. "_proxy_tag"] local preproxy_node_id = node[rule_name .. "_proxy_tag"]
if preproxy_node_id == _node_id then preproxy_node_id = nil end if preproxy_node_id == _node_id then preproxy_node_id = nil end
@@ -1561,7 +1575,6 @@ function gen_config(var)
COMMON.default_outbound_tag = gen_outbound_get_tag(flag, node or node_id, nil, { COMMON.default_outbound_tag = gen_outbound_get_tag(flag, node or node_id, nil, {
fragment = xray_settings.fragment == "1" or nil, fragment = xray_settings.fragment == "1" or nil,
noise = xray_settings.noise == "1" or nil, noise = xray_settings.noise == "1" or nil,
run_socks_instance = not no_run
}) })
if COMMON.default_outbound_tag then if COMMON.default_outbound_tag then
routing = { routing = {
@@ -1802,11 +1815,10 @@ function gen_config(var)
sockopt = { dialerProxy = (dns_outbound_tag ~= "blackhole") and dns_outbound_tag or "direct" } sockopt = { dialerProxy = (dns_outbound_tag ~= "blackhole") and dns_outbound_tag or "direct" }
} or nil, } or nil,
settings = { settings = {
address = (chn_list ~= "proxy") and "8.8.8.8" or "223.5.5.5", rewriteAddress = (chn_list ~= "proxy") and "8.8.8.8" or "223.5.5.5",
port = 53, rewritePort = 53,
network = "tcp", rewriteNetwork = "tcp",
nonIPQuery = (api.compare_versions(xray_version, "<", "26.4.25")) and "reject" or nil, -- Todo is to remove it rules = {}
rules = (api.compare_versions(xray_version, ">", "26.4.17")) and {} or nil
} }
} }
@@ -2030,9 +2042,9 @@ function gen_config(var)
local direct_outbound = { local direct_outbound = {
protocol = "freedom", protocol = "freedom",
tag = "direct", tag = "direct",
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check settings = {
finalRules = {{ action = "allow" }} finalRules = {{ action = "allow" }}
} or nil, },
streamSettings = { streamSettings = {
sockopt = { sockopt = {
mark = 255, mark = 255,
@@ -2058,7 +2070,7 @@ function gen_config(var)
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
local pt = value.protocol local pt = value.protocol
local exclude = { blackhole=1, dns=1, freedom=1, loopback=1 } local exclude = { blackhole=1, dns=1, freedom=1, loopback=1 }
if not value["_flag_proxy_tag"] and value["_id"] and pt and not exclude[pt] and not no_run then if not value["_flag_proxy_tag"] and value["_id"] and pt and not exclude[pt] and not NO_RUN then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list")) sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end end
for k, v in pairs(config.outbounds[index]) do for k, v in pairs(config.outbounds[index]) do
@@ -2136,7 +2148,7 @@ function gen_proto_config(var)
local outbound = { local outbound = {
protocol = server_proto, protocol = server_proto,
streamSettings = { streamSettings = {
network = "tcp", method = "raw",
security = "none" security = "none"
}, },
settings = { settings = {
@@ -2161,10 +2173,12 @@ function gen_proto_config(var)
table.insert(outbounds, { table.insert(outbounds, {
protocol = "freedom", protocol = "freedom",
tag = "direct", tag = "direct",
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check settings = {
finalRules = {{ action = "allow" }} finalRules = {{ action = "allow" }}
} or nil, },
streamSettings = {
sockopt = {mark = 255} sockopt = {mark = 255}
}
}) })
local config = { local config = {
@@ -2176,7 +2190,10 @@ function gen_proto_config(var)
-- 传出连接 -- 传出连接
outbounds = outbounds, outbounds = outbounds,
-- 路由 -- 路由
routing = routing routing = routing,
version = {
min = xray_min_version
}
} }
return jsonc.stringify(config, 1) return jsonc.stringify(config, 1)
end end
@@ -1402,6 +1402,7 @@ table td, .table .td {
var node_tr_html = ""; var node_tr_html = "";
for (var i = 0; i < group_nodes[group].length; i++) { for (var i = 0; i < group_nodes[group].length; i++) {
let o = group_nodes[group][i] let o = group_nodes[group][i]
let _port = o["port"] || o["hysteria_hop"] || o["hysteria2_hop"];
var newDom = node_template.cloneNode(true); var newDom = node_template.cloneNode(true);
newDom.classList.add("cbi-rowstyle-" + (i % 2 + 1)); newDom.classList.add("cbi-rowstyle-" + (i % 2 + 1));
var innerHTML = newDom.innerHTML; var innerHTML = newDom.innerHTML;
@@ -1415,17 +1416,15 @@ table td, .table .td {
} else { } else {
innerHTML = innerHTML.split("{{tcping}}").join('<span class="tcping_value" cbiid="{{id}}"><a href="javascript:void(0)" style="color:inherit">---</a></span>'); innerHTML = innerHTML.split("{{tcping}}").join('<span class="tcping_value" cbiid="{{id}}"><a href="javascript:void(0)" style="color:inherit">---</a></span>');
} }
let is_realm = (o.type === "Hysteria2" || o.protocol === 'hysteria2') && o.hysteria2_realms || false; if (o["address"] && _port) {
if (o["protocol"] === '_shunt' || is_realm) {
innerHTML = innerHTML.split("{{url_test}}").join('<span class="ping" cbiid="{{id}}">---</span>');
} else {
innerHTML = innerHTML.split("{{url_test}}").join('<span class="ping"><a href="javascript:void(0)" onclick="javascript:urltest_node(\'{{id}}\', this)" title="<%:TLS handshake test, latency for reference only%>"><%:Test%></a></span>'); innerHTML = innerHTML.split("{{url_test}}").join('<span class="ping"><a href="javascript:void(0)" onclick="javascript:urltest_node(\'{{id}}\', this)" title="<%:TLS handshake test, latency for reference only%>"><%:Test%></a></span>');
} else {
innerHTML = innerHTML.split("{{url_test}}").join('<span class="ping" cbiid="{{id}}">---</span>');
} }
innerHTML = innerHTML.split("{{id}}").join(o[".name"]); innerHTML = innerHTML.split("{{id}}").join(o[".name"]);
innerHTML = innerHTML.split("{{group}}").join(o["group"] || ""); innerHTML = innerHTML.split("{{group}}").join(o["group"] || "");
let node_remarks = get_remarks_name(o); let node_remarks = get_remarks_name(o);
if (show_node_info == "1") { if (show_node_info == "1") {
let _port = o["port"] || o["hysteria_hop"] || o["hysteria2_hop"];
if (_port) _port = _port.replace(/:/g, '-'); if (_port) _port = _port.replace(/:/g, '-');
if (o["address"] && _port) { if (o["address"] && _port) {
let _address = o["address"] let _address = o["address"]
-30
View File
@@ -1643,36 +1643,6 @@ msgstr "启用节点日志"
msgid "Log Level" msgid "Log Level"
msgstr "日志等级" msgstr "日志等级"
msgid "Advanced log feature"
msgstr "高级日志功能"
msgid "For professionals only."
msgstr "仅限专业人士使用。"
msgid "Persist log file directory"
msgstr "持久性日志文件目录"
msgid "The path to the directory used to store persist log files, the \"/\" at the end can be omitted. Leave it blank to disable this feature."
msgstr "用来存储持久性日志文件的目录路径,末尾的 “/” 可以省略。留空以禁用此功能。"
msgid "Logging to system log"
msgstr "记录到系统日志"
msgid "Logging to the system log for more advanced functions. For example, send logs to a dedicated log server."
msgstr "将日志记录到系统日志,以实现更加高级的功能。例如,把日志发送到专门的日志服务器。"
msgid "Log Event Filter"
msgstr "日志事件过滤器"
msgid "Support regular expression."
msgstr "支持正则表达式。"
msgid "Shell Command"
msgstr "Shell 命令"
msgid "Shell command to execute, replace log content with %s."
msgstr "要执行的 Shell 命令,用 %s 代替日志内容。"
msgid "Not enabled log" msgid "Not enabled log"
msgstr "未启用日志" msgstr "未启用日志"
@@ -1,17 +1,12 @@
#!/bin/sh #!/bin/sh
# Devices without a hardware RTC boot with a wrong system clock: sysfixtime can [ "$ACTION" = "step" ] || exit 0
# only restore the mtime of the newest file under /etc, so the clock is usually
# hours behind after a cold boot. passwall is then started by
# /etc/hotplug.d/iface/98-passwall on ifup, which typically happens before NTP
# has corrected the time, and time-sensitive handshakes (VMess AEAD, TLS) fail.
#
# Nothing restarts passwall once the clock is corrected, so it stays broken
# until the user restarts it manually. Restart once when ntpd reports that the
# time is valid -- the same approach dnsmasq uses for DNSSEC in
# /etc/hotplug.d/ntp/25-dnsmasqsec.
[ "$ACTION" = "stratum" ] || exit 0 offset=${offset#-}
offset=${offset%.*}
# Skip service restart if the time adjustment is less than 120 seconds.
[ "$offset" -lt 120 ] && exit 0
. /usr/share/passwall/utils.sh . /usr/share/passwall/utils.sh
@@ -23,5 +18,5 @@ NTP_LOCK_FILE="${LOCK_PATH}/${CONFIG}_ntp.lock"
echo $$ > ${NTP_LOCK_FILE} echo $$ > ${NTP_LOCK_FILE}
/etc/init.d/${CONFIG} restart >/dev/null 2>&1 & /etc/init.d/${CONFIG} restart >/dev/null 2>&1 &
logger -p notice -t network -s "${CONFIG}: restart after NTP time became valid" logger -p notice -t network -s "${CONFIG}: restart after NTP time step (${offset}s)"
} }
@@ -87,7 +87,7 @@ run_ipt2socks() {
run_singbox() { run_singbox() {
local flag type node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password local flag type node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_query_strategy direct_dns_port direct_dns_udp_server direct_dns_tcp_server remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy remote_rewrite_ttl dns_cache dns_socks_address dns_socks_port local dns_listen_port direct_dns_query_strategy direct_dns_port direct_dns_udp_server direct_dns_tcp_server remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy remote_rewrite_ttl dns_cache dns_socks_address dns_socks_port
local loglevel log_file config_file server_host server_port no_run use_proxy_list use_gfw_list chn_list local loglevel log_file config_file server_host server_port no_run use_proxy_list use_gfw_list chn_list run_in_global
eval_set_val "$@" eval_set_val "$@"
[ -z "$type" ] && { [ -z "$type" ] && {
type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
@@ -182,13 +182,17 @@ run_singbox() {
[ "$remote_fakedns" = "1" ] && json_add_string "remote_dns_fake" "1" [ "$remote_fakedns" = "1" ] && json_add_string "remote_dns_fake" "1"
[ -n "$remote_rewrite_ttl" ] && json_add_string "remote_rewrite_ttl" "${remote_rewrite_ttl}" [ -n "$remote_rewrite_ttl" ] && json_add_string "remote_rewrite_ttl" "${remote_rewrite_ttl}"
[ -n "$no_run" ] && json_add_string "no_run" "1" [ -n "$no_run" ] && json_add_string "no_run" "1"
[ -n "$run_in_global" ] && json_add_string "run_in_global" "1"
local _json_arg="$(json_dump)" local _json_arg="$(json_dump)"
lua $UTIL_SINGBOX gen_config "${_json_arg}" > $config_file lua $UTIL_SINGBOX gen_config "${_json_arg}" > $config_file
[ -n "$no_run" ] && return [ -n "$no_run" ] && return
local test_log_file=$log_file local test_log_file=$log_file
local status=0
[ "$test_log_file" = "/dev/null" ] && test_log_file="${TMP_PATH}/${config_file##*/}_test.log" [ "$test_log_file" = "/dev/null" ] && test_log_file="${TMP_PATH}/${config_file##*/}_test.log"
$SINGBOX_BIN check -c "$config_file" > $test_log_file 2>&1; local status=$? [ -n "$run_in_global" ] && {
$SINGBOX_BIN check -c "$config_file" > $test_log_file 2>&1; status=$?
}
if [ "${status}" = 0 ]; then if [ "${status}" = 0 ]; then
ln_run "$SINGBOX_BIN" "sing-box" "${log_file}" run -c "$config_file" ln_run "$SINGBOX_BIN" "sing-box" "${log_file}" run -c "$config_file"
else else
@@ -201,7 +205,7 @@ run_singbox() {
run_xray() { run_xray() {
local flag type node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password local flag type node redir_port tcp_proxy_way socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_query_strategy direct_dns_port direct_dns_udp_server direct_dns_tcp_server remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache dns_socks_address dns_socks_port local dns_listen_port direct_dns_query_strategy direct_dns_port direct_dns_udp_server direct_dns_tcp_server remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache dns_socks_address dns_socks_port
local loglevel log_file config_file server_host server_port no_run use_proxy_list use_gfw_list chn_list local loglevel log_file config_file server_host server_port no_run use_proxy_list use_gfw_list chn_list run_in_global
eval_set_val "$@" eval_set_val "$@"
[ -z "$type" ] && { [ -z "$type" ] && {
type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
@@ -278,13 +282,17 @@ run_xray() {
json_add_string "loglevel" "$loglevel" json_add_string "loglevel" "$loglevel"
[ -n "$no_run" ] && json_add_string "no_run" "1" [ -n "$no_run" ] && json_add_string "no_run" "1"
[ -n "$run_in_global" ] && json_add_string "run_in_global" "1"
local _json_arg="$(json_dump)" local _json_arg="$(json_dump)"
lua $UTIL_XRAY gen_config "${_json_arg}" > $config_file lua $UTIL_XRAY gen_config "${_json_arg}" > $config_file
[ -n "$no_run" ] && return [ -n "$no_run" ] && return
local test_log_file=$log_file local test_log_file=$log_file
local status=0
[ "$test_log_file" = "/dev/null" ] && test_log_file="${TMP_PATH}/${config_file##*/}_test.log" [ "$test_log_file" = "/dev/null" ] && test_log_file="${TMP_PATH}/${config_file##*/}_test.log"
$XRAY_BIN run -test -c "$config_file" > $test_log_file; local status=$? [ -n "$run_in_global" ] && {
$XRAY_BIN run -test -c "$config_file" > $test_log_file; status=$?
}
if [ "${status}" = 0 ]; then if [ "${status}" = 0 ]; then
ln_run "$XRAY_BIN" "xray" "${log_file}" run -c "$config_file" ln_run "$XRAY_BIN" "xray" "${log_file}" run -c "$config_file"
else else
@@ -489,8 +497,6 @@ run_socks() {
;; ;;
esac esac
set_cache_var "node_${node}_socks_port" "${socks_port}"
# http to socks # http to socks
[ -z "$http_flag" ] && [ "$http_port" != "0" ] && [ -n "$http_config_file" ] && [ "$type" != "sing-box" ] && [ "$type" != "xray" ] && [ "$type" != "socks" ] && { [ -z "$http_flag" ] && [ "$http_port" != "0" ] && [ -n "$http_config_file" ] && [ "$type" != "sing-box" ] && [ "$type" != "xray" ] && [ "$type" != "socks" ] && {
json_init json_init
@@ -601,7 +607,7 @@ start_global() {
;; ;;
sing-box) sing-box)
local _flag="global" local _flag="global"
local _args="" local _args="run_in_global=1"
[ "$on_node_socks" = "1" ] && { [ "$on_node_socks" = "1" ] && {
node_socks_flag=1 node_socks_flag=1
_args="${_args} socks_address=${node_socks_bind} socks_port=${GLOBAL_SOCKS_port}" _args="${_args} socks_address=${node_socks_bind} socks_port=${GLOBAL_SOCKS_port}"
@@ -679,7 +685,7 @@ start_global() {
;; ;;
xray) xray)
local _flag="global" local _flag="global"
local _args="" local _args="run_in_global=1"
[ "$on_node_socks" = "1" ] && { [ "$on_node_socks" = "1" ] && {
node_socks_flag=1 node_socks_flag=1
_args="${_args} socks_address=${node_socks_bind} socks_port=${GLOBAL_SOCKS_port}" _args="${_args} socks_address=${node_socks_bind} socks_port=${GLOBAL_SOCKS_port}"
@@ -829,7 +835,6 @@ start_global() {
set_cache_var "GLOBAL_SOCKS_server" "${GLOBAL_SOCKS_server}" set_cache_var "GLOBAL_SOCKS_server" "${GLOBAL_SOCKS_server}"
} }
[ "$type" != "sing-box" ] && [ "$type" != "xray" ] && echo "${NODE}" >> $TMP_PATH/direct_node_list [ "$type" != "sing-box" ] && [ "$type" != "xray" ] && echo "${NODE}" >> $TMP_PATH/direct_node_list
set_cache_var "node_${NODE}_redir_port" "$REDIR_PORT"
set_cache_var "ACL_GLOBAL_node" "$NODE" set_cache_var "ACL_GLOBAL_node" "$NODE"
set_cache_var "ACL_GLOBAL_redir_port" "$REDIR_PORT" set_cache_var "ACL_GLOBAL_redir_port" "$REDIR_PORT"
} }
@@ -1570,9 +1575,9 @@ acl_app() {
#dhcp.leases to hosts #dhcp.leases to hosts
$APP_PATH/lease2hosts.sh > /dev/null 2>&1 & $APP_PATH/lease2hosts.sh > /dev/null 2>&1 &
} }
local _redir_port=$(get_cache_var "node_${node}_redir_port") local _redir_port=$(get_cache_var "acl_node_${node}_redir_port")
local _socks_port=$(get_cache_var "node_${node}_socks_port") local _socks_port=$(get_cache_var "acl_node_${node}_socks_port")
local _enable_log=$(get_cache_var "node_${node}_enable_log") local _enable_log=$(get_cache_var "acl_node_${node}_enable_log")
local _dns_port local _dns_port
if [ -n "${_socks_port}" ] && [ -n "${_redir_port}" ] && [ "${_enable_log}" != "1" ] && [ "${log}" != "1" ]; then if [ -n "${_socks_port}" ] && [ -n "${_redir_port}" ] && [ "${_enable_log}" != "1" ] && [ "${log}" != "1" ]; then
socks_port=${_socks_port} socks_port=${_socks_port}
@@ -1581,14 +1586,14 @@ acl_app() {
run_dns ${_dns_port} run_dns ${_dns_port}
else else
socks_port=$(get_new_port $(expr $socks_port + 1)) socks_port=$(get_new_port $(expr $socks_port + 1))
set_cache_var "node_${node}_socks_port" "${socks_port}" set_cache_var "acl_node_${node}_socks_port" "${socks_port}"
redir_port=$(get_new_port $(expr $redir_port + 1)) redir_port=$(get_new_port $(expr $redir_port + 1))
set_cache_var "node_${node}_redir_port" "${redir_port}" set_cache_var "acl_node_${node}_redir_port" "${redir_port}"
node_port=$redir_port node_port=$redir_port
local log_file="/dev/null" local log_file="/dev/null"
[ "${log}" = "1" ] && { [ "${log}" = "1" ] && {
log_file="${TMP_ACL_PATH}/${sid}/node.log" log_file="${TMP_ACL_PATH}/${sid}/node.log"
set_cache_var "node_${node}_enable_log" "1" set_cache_var "acl_node_${node}_enable_log" "1"
} }
if [ "${type}" = "sing-box" ] || [ "${type}" = "xray" ]; then if [ "${type}" = "sing-box" ] || [ "${type}" = "xray" ]; then
@@ -109,8 +109,12 @@ api.uci_foreach_c("haproxy_config", function(t)
t.origin_port = server_port t.origin_port = server_port
if health_check_type == "script_logic" then if health_check_type == "script_logic" then
if server_node.type ~= "Socks" then if server_node.type ~= "Socks" then
local relay_port = server_node.port local new_port
local new_port = api.get_new_port() local cache = api.get_socks_port_by_cache(server_node[".name"])
if cache then
new_port = cache
else
new_port = api.get_new_port()
local config_file = string.format("%s_%s.json", t[".name"], new_port) local config_file = string.format("%s_%s.json", t[".name"], new_port)
sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null', sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null',
appname, appname,
@@ -123,6 +127,8 @@ api.uci_foreach_c("haproxy_config", function(t)
) )
) )
) )
api.set_socks_port_to_cache(server_node[".name"], new_port)
end
server_address = "127.0.0.1" server_address = "127.0.0.1"
server_port = new_port server_port = new_port
end end
@@ -469,16 +469,28 @@ load_acl() {
else else
[ -n "${DIRECT_DNSMASQ_PORT}" ] && dns_redirect=${DIRECT_DNSMASQ_PORT} [ -n "${DIRECT_DNSMASQ_PORT}" ] && dns_redirect=${DIRECT_DNSMASQ_PORT}
fi fi
if [ -n "${dns_redirect}" ]; then
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" if ([ -n "$tcp_port" ] || [ -n "$udp_port" ]) && [ -n "$dns_redirect" ]; then
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" if [ "$PROXY_IPV6" = "1" ]; then
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 accept"
[ "$_ipv4" != "1" ] && 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_MANGLE_V6 meta l4proto 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 meta l4proto 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\"" nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :${dns_redirect} comment \"$remarks\"" else
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :${dns_redirect} comment \"$remarks\"" 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}]。" [ -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
fi fi
[ -n "$tcp_port" ] || [ -n "$udp_port" ] && { [ -n "$tcp_port" ] || [ -n "$udp_port" ] && {
@@ -657,15 +669,26 @@ load_acl() {
[ -n "${DIRECT_DNSMASQ_PORT}" ] && DNS_REDIRECT=${DIRECT_DNSMASQ_PORT} [ -n "${DIRECT_DNSMASQ_PORT}" ] && DNS_REDIRECT=${DIRECT_DNSMASQ_PORT}
fi fi
if [ -n "${DNS_REDIRECT}" ]; then if ([ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ]) && [ -n "$DNS_REDIRECT" ]; then
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp udp dport 53 counter return comment \"默认\"" if [ "$PROXY_IPV6" = "1" ]; then
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 udp udp dport 53 counter accept"
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 tcp tcp dport 53 counter accept"
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 ip protocol 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 \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp tcp dport 53 counter redirect to :${DNS_REDIRECT} comment \"默认\"" else
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_MANGLE ip protocol udp udp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter redirect to :${DNS_REDIRECT} comment \"默认\"" 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
fi fi
[ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ] && { [ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ] && {
@@ -1310,10 +1333,15 @@ add_firewall_rule() {
if [ -n "$NODE" ] && ([ -n "${LOCALHOST_TCP_PROXY_MODE}" ] || [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then if [ -n "$NODE" ] && ([ -n "${LOCALHOST_TCP_PROXY_MODE}" ] || [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then
[ -n "$DNS_REDIRECT_PORT" ] && { [ -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 \"PSW_DNS\"" if [ "$PROXY_IPV6" == "1" ]; then
nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\"" #nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
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 PSW_OUTPUT_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\"" 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
} }
fi fi
@@ -183,8 +183,6 @@ test_auto_switch() {
start() { start() {
id=$1 id=$1
LOCK_FILE=${LOCK_PATH}/${CONFIG}_socks_auto_switch_${id}.lock LOCK_FILE=${LOCK_PATH}/${CONFIG}_socks_auto_switch_${id}.lock
LOG_EVENT_FILTER=$(uci -q get "${CONFIG}.global[0].log_event_filter" 2>/dev/null)
LOG_EVENT_CMD=$(uci -q get "${CONFIG}.global[0].log_event_cmd" 2>/dev/null)
main_node=$(config_n_get $id node) main_node=$(config_n_get $id node)
socks_port=$(config_n_get $id port 0) socks_port=$(config_n_get $id port 0)
delay=$(config_n_get $id autoswitch_testing_time 30) delay=$(config_n_get $id autoswitch_testing_time 30)
@@ -60,6 +60,63 @@ config_t_get() {
echo "${ret:=${3}}" echo "${ret:=${3}}"
} }
eval_set_val() {
for i in $@; do
for j in $i; do
eval $j
done
done
}
eval_unset_val() {
for i in $@; do
for j in $i; do
eval unset $j
done
done
}
lua_api() {
local func=${1}
[ -z "${func}" ] && {
echo "nil"
return
}
echo $(lua -e "local api = require 'luci.passwall.api' print(api.${func})")
}
eval_cache_var() {
[ -s "$TMP_PATH/var" ] && eval $(cat "$TMP_PATH/var")
}
del_cache_var() {
local key="${1}"
[ -n "${key}" ] && [ -f "${TMP_PATH}/var" ] && {
sed -i "/${key}=/d" $TMP_PATH/var >/dev/null 2>&1
}
}
set_cache_var() {
local key="${1}"
shift 1
[ -n "${key}" ] && {
del_cache_var ${key}
local val="$@"
[ -n "${val}" ] && {
[ ! -d $TMP_PATH ] && mkdir -p $TMP_PATH
echo "${key}=\"${val}\"" >> $TMP_PATH/var
eval ${key}=\"${val}\"
}
}
}
get_cache_var() {
local key="${1}"
[ -n "${key}" ] && [ -s "$TMP_PATH/var" ] && {
echo $(cat $TMP_PATH/var | grep "^${key}=" | awk -F '=' '{print $2}' | tail -n 1 | awk -F'"' '{print $2}')
}
}
first_type() { first_type() {
[ "${1#/}" != "$1" ] && [ -x "$1" ] && echo "$1" && return [ "${1#/}" != "$1" ] && [ -x "$1" ] && echo "$1" && return
for p in "/bin/$1" "/usr/bin/$1" "${TMP_BIN_PATH:-/tmp}/$1"; do for p in "/bin/$1" "/usr/bin/$1" "${TMP_BIN_PATH:-/tmp}/$1"; do
@@ -283,53 +340,42 @@ get_new_port() {
local default_start_port=2001 local default_start_port=2001
local min_port=1025 local min_port=1025
local max_port=49151 local max_port=49151
local port="$1" local port="$1" # Required parameter; please pass "auto" if you want it to be automatic.
local protocol=$(echo "$2" | tr 'A-Z' 'a-z') local protocol=$(echo "$2" | tr 'A-Z' 'a-z')
local LOCK_FILE="${LOCK_PATH}/${CONFIG}_get_prot.lock" local is_auto
while ! mkdir "$LOCK_FILE" 2>/dev/null; do
sleep 0.05
done
if [ "$port" = "auto" ]; then if [ "$port" = "auto" ]; then
local now last_time diff last_port is_auto=1
now=$(date +%s 2>/dev/null) local last_get_new_port_auto=$(get_cache_var "last_get_new_port_auto")
last_time=$(get_cache_var "last_get_new_port_time") if [ -n "$last_get_new_port_auto" ]; then
if [ -n "$now" ] && [ -n "$last_time" ]; then port=$(expr "$last_get_new_port_auto" + 1)
diff=$(expr "$now" - "$last_time")
[ "$diff" -lt 0 ] && diff=$(expr 0 - "$diff")
else
diff=999
fi
if [ "$diff" -gt 10 ]; then
port=$default_start_port
else
last_port=$(get_cache_var "last_get_new_port_auto")
if [ -n "$last_port" ]; then
port=$(expr "$last_port" + 1)
else else
port=$default_start_port port=$default_start_port
fi fi
fi fi
fi ([ "$port" -lt "$min_port" ] || [ "$port" -gt "$max_port" ]) && port=$default_start_port
[ "$port" -lt $min_port ] || [ "$port" -gt $max_port ] && port=$default_start_port
local start_port="$port"
while :; do while :; do
if [ "$(check_port_exists "$port" "$protocol")" = 0 ]; then local result=$(check_port_exists "$port" "$protocol")
break if [ "$is_auto" = "1" ] && [ -n "$(get_cache_var "get_port_${port}")" ]; then
# The port has already been allocated, continue to the next port.
result=1
fi fi
[ "$result" = "0" ] && break
if [ "$port" -lt "$max_port" ]; then
# If the port is smaller than the maximum port, increment by 1 and continue.
port=$(expr "$port" + 1) port=$(expr "$port" + 1)
if [ "$port" -gt $max_port ]; then elif [ "$port" -gt "$min_port" ]; then
port=$min_port # If the port is greater than the minimum port, decrement by 1 and continue.
port=$(expr "$port" - 1)
else
# Otherwise, reassign the default starting port.
port=$default_start_port
fi fi
[ "$port" = "$start_port" ] && {
rmdir "$LOCK_FILE" 2>/dev/null
return 1
}
done done
if [ "$1" = "auto" ]; then if [ "$is_auto" = "1" ]; then
# Set cache to prevent the port from being allocated again.
set_cache_var "get_port_${port}" "1"
set_cache_var "last_get_new_port_auto" "$port" set_cache_var "last_get_new_port_auto" "$port"
[ -n "$now" ] && set_cache_var "last_get_new_port_time" "$now"
fi fi
rmdir "$LOCK_FILE" 2>/dev/null
echo "$port" echo "$port"
} }
@@ -359,54 +405,6 @@ check_ver() {
echo 255 echo 255
} }
eval_set_val() {
for i in $@; do
for j in $i; do
eval $j
done
done
}
eval_unset_val() {
for i in $@; do
for j in $i; do
eval unset $j
done
done
}
lua_api() {
local func=${1}
[ -z "${func}" ] && {
echo "nil"
return
}
echo $(lua -e "local api = require 'luci.passwall.api' print(api.${func})")
}
set_cache_var() {
local key="${1}"
shift 1
local val="$@"
[ -n "${key}" ] && [ -n "${val}" ] && {
[ ! -d $TMP_PATH ] && mkdir -p $TMP_PATH
sed -i "/${key}=/d" $TMP_PATH/var >/dev/null 2>&1
echo "${key}=\"${val}\"" >> $TMP_PATH/var
eval ${key}=\"${val}\"
}
}
get_cache_var() {
local key="${1}"
[ -n "${key}" ] && [ -s "$TMP_PATH/var" ] && {
echo $(cat $TMP_PATH/var | grep "^${key}=" | awk -F '=' '{print $2}' | tail -n 1 | awk -F'"' '{print $2}')
}
}
eval_cache_var() {
[ -s "$TMP_PATH/var" ] && eval $(cat "$TMP_PATH/var")
}
has_1_65535() { has_1_65535() {
local val="$1" local val="$1"
val=${val//:/-} val=${val//:/-}
@@ -470,25 +468,9 @@ ln_run() {
echolog " - 找不到 ${ln_name},无法启动..." echolog " - 找不到 ${ln_name},无法启动..."
return 1 return 1
} }
[ "${output}" != "/dev/null" ] && [ -n "$(echo "${output}" | grep -E "default|socks_")" ] && [ "${ln_name}" != "chinadns-ng" ] && {
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 & ${file_func:-echolog " - ${ln_name}"} "$@" >${output} 2>&1 &
else
if [ -n "${persist_log_path}" ]; then
mkdir -p ${persist_log_path}
local log_file=${persist_log_path}/passwall_global_${ln_name}_$(date '+%F').log
echolog "记录到持久性日志文件:${log_file}"
${file_func:-echolog " - ${ln_name}"} "$@" >> ${log_file} 2>&1 &
sys_log=0
fi
if [ "${sys_log}" = "1" ]; then
echolog "记录 ${ln_name}_global 到系统日志"
${file_func:-echolog " - ${ln_name}"} "$@" 2>&1 | logger -t PASSWALL_global_${ln_name} &
fi
fi
[ "$NO_REC_PROCESS" = "1" ] && return [ "$NO_REC_PROCESS" = "1" ] && return
process_count=$(ls $TMP_SCRIPT_FUNC_PATH | wc -l) process_count=$(ls $TMP_SCRIPT_FUNC_PATH | wc -l)
process_count=$((process_count + 1)) process_count=$((process_count + 1))
@@ -238,7 +238,7 @@ end
function get_now_use_node() function get_now_use_node()
local e = {} local e = {}
local node = api.get_cache_var("ACL_GLOBAL_node") local node = api.get_cache_var(("ACL_${flag}_node"):gsub("${flag}", "acl_default"))
if node then if node then
e["global"] = node e["global"] = node
end end
+4 -1
View File
@@ -292,13 +292,16 @@ end
function curl_proxy(url, file, args) function curl_proxy(url, file, args)
-- Use the proxy -- Use the proxy
local socks_server = get_cache_var("GLOBAL_SOCKS_server") local socks_port = get_cache_var(("ACL_${flag}_node_socks_port"):gsub("${flag}", "acl_default"))
if socks_port then
local socks_server = "127.0.0.1:%s" % socks_port
if socks_server and socks_server ~= "" then if socks_server and socks_server ~= "" then
if not args then args = {} end if not args then args = {} end
local tmp_args = clone(args) local tmp_args = clone(args)
tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server
return curl_base(url, file, tmp_args) return curl_base(url, file, tmp_args)
end end
end
return nil, nil return nil, nil
end end
@@ -111,20 +111,21 @@ function gen_outbound(flag, node, tag, proxy_table)
end end
local remarks = node.remarks local remarks = node.remarks
local proxy_tag = nil local proxy_tag, fragment, record_fragment
local fragment = nil
local record_fragment = nil
local run_socks_instance = true
if proxy_table ~= nil and type(proxy_table) == "table" then if proxy_table ~= nil and type(proxy_table) == "table" then
proxy_tag = proxy_table.tag or nil proxy_tag = proxy_table.tag or nil
fragment = (proxy_table.fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil fragment = (proxy_table.fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil
record_fragment = (proxy_table.record_fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil record_fragment = (proxy_table.record_fragment and node.protocol ~= "naive" and not node.hysteria2_realms) and true or nil
run_socks_instance = proxy_table.run_socks_instance
end end
if node.type ~= "sing-box" then if node.type ~= "sing-box" then
local new_port local new_port
if run_socks_instance then local run_socks_instance = true
if NO_RUN then
TMP_PORT = TMP_PORT and TMP_PORT + 1 or 3001
new_port = TMP_PORT
run_socks_instance = nil
else
local relay_port = (proxy_tag and node.port) and tostring(node.port) or "" local relay_port = (proxy_tag and node.port) and tostring(node.port) or ""
if relay_port == "" then if relay_port == "" then
local cache = api.get_socks_port_by_cache(node_id) local cache = api.get_socks_port_by_cache(node_id)
@@ -1181,8 +1182,7 @@ function gen_config(var)
local remote_dns_client_ip = var["remote_dns_client_ip"] local remote_dns_client_ip = var["remote_dns_client_ip"]
local remote_rewrite_ttl = var["remote_rewrite_ttl"] or "30" local remote_rewrite_ttl = var["remote_rewrite_ttl"] or "30"
local dns_cache = var["dns_cache"] local dns_cache = var["dns_cache"]
local tags = var["tags"] NO_RUN = var["no_run"]
local no_run = var["no_run"]
local dns_domain_rules = {} local dns_domain_rules = {}
local dns = {} local dns = {}
@@ -1405,7 +1405,7 @@ function gen_config(var)
end end
end end
if is_new_ut_node then if is_new_ut_node then
local outboundTag = gen_outbound_get_tag(flag, ut_node_id, ut_node_tag, { fragment = singbox_settings.fragment == "1" or nil, record_fragment = singbox_settings.record_fragment == "1" or nil, run_socks_instance = not no_run }) local outboundTag = gen_outbound_get_tag(flag, ut_node_id, ut_node_tag, { fragment = singbox_settings.fragment == "1" or nil, record_fragment = singbox_settings.record_fragment == "1" or nil })
if outboundTag then if outboundTag then
valid_nodes[#valid_nodes + 1] = outboundTag valid_nodes[#valid_nodes + 1] = outboundTag
end end
@@ -1508,7 +1508,6 @@ function gen_config(var)
to_node.port = new_port to_node.port = new_port
to_outbound = gen_outbound(node[".name"], to_node, tag, { to_outbound = gen_outbound(node[".name"], to_node, tag, {
tag = tag, tag = tag,
run_socks_instance = not no_run
}) })
else else
to_outbound = gen_outbound(node[".name"], to_node) to_outbound = gen_outbound(node[".name"], to_node)
@@ -1607,7 +1606,6 @@ function gen_config(var)
local proxy_table = { local proxy_table = {
fragment = singbox_settings.fragment == "1", fragment = singbox_settings.fragment == "1",
record_fragment = singbox_settings.record_fragment == "1", record_fragment = singbox_settings.record_fragment == "1",
run_socks_instance = not no_run,
} }
local preproxy_node_id = node[rule_name .. "_proxy_tag"] local preproxy_node_id = node[rule_name .. "_proxy_tag"]
if preproxy_node_id == _node_id then preproxy_node_id = nil end if preproxy_node_id == _node_id then preproxy_node_id = nil end
@@ -2284,7 +2282,7 @@ function gen_config(var)
routing_mark = 255, routing_mark = 255,
}) })
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
if not value["_flag_proxy_tag"] and not value.detour and value["_id"] and value.server and value.server_port and not no_run then if not value["_flag_proxy_tag"] and not value.detour and value["_id"] and value.server and value.server_port and not NO_RUN then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list")) sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end end
if not value.detour and not value.bind_interface and value.server then if not value.detour and not value.bind_interface and value.server then
@@ -2427,7 +2425,7 @@ if arg[1] then
var = jsonc.parse(arg[2]) var = jsonc.parse(arg[2])
end end
print(func(var)) print(func(var))
if (next(GEO_VAR.SITE_TAGS) or next(GEO_VAR.IP_TAGS)) and not no_run then if (next(GEO_VAR.SITE_TAGS) or next(GEO_VAR.IP_TAGS)) and not NO_RUN then
convert_geofile() convert_geofile()
end end
end end
@@ -12,7 +12,7 @@ local GLOBAL = {
local xray_version = api.get_app_version("xray") local xray_version = api.get_app_version("xray")
local xray_min_version = "26.3.27" local xray_min_version = "26.7.11"
local function get_domain_excluded() local function get_domain_excluded()
local path = "/usr/share/passwall2/domains_excluded" local path = "/usr/share/passwall2/domains_excluded"
@@ -58,21 +58,21 @@ function gen_outbound(flag, node, tag, proxy_table)
end end
local remarks = node.remarks local remarks = node.remarks
local proxy_tag = nil local proxy_tag, dialer_proxy_tag, fragment, noise
local dialer_proxy_tag = nil
local fragment = nil
local noise = nil
local run_socks_instance = true
if proxy_table ~= nil and type(proxy_table) == "table" then if proxy_table ~= nil and type(proxy_table) == "table" then
proxy_tag = proxy_table.tag or nil proxy_tag = proxy_table.tag or nil
fragment = (proxy_table.fragment and not node.hysteria2_realms) and true or nil fragment = (proxy_table.fragment and not node.hysteria2_realms) and true or nil
noise = (proxy_table.noise and not node.hysteria2_realms) and true or nil noise = (proxy_table.noise and not node.hysteria2_realms) and true or nil
run_socks_instance = proxy_table.run_socks_instance
end end
if node.type ~= "Xray" then if node.type ~= "Xray" then
local new_port local new_port
if run_socks_instance then local run_socks_instance = true
if NO_RUN then
TMP_PORT = TMP_PORT and TMP_PORT + 1 or 3001
new_port = TMP_PORT
run_socks_instance = nil
else
local relay_port = (proxy_tag and node.port) and tostring(node.port) or "" local relay_port = (proxy_tag and node.port) and tostring(node.port) or ""
if relay_port == "" then if relay_port == "" then
local cache = api.get_socks_port_by_cache(node_id) local cache = api.get_socks_port_by_cache(node_id)
@@ -106,7 +106,7 @@ function gen_outbound(flag, node, tag, proxy_table)
if new_port then if new_port then
node = {} node = {}
node.protocol = "socks" node.protocol = "socks"
node.transport = "tcp" node.transport = "raw"
node.address = "127.0.0.1" node.address = "127.0.0.1"
node.port = new_port node.port = new_port
node.stream_security = "none" node.stream_security = "none"
@@ -181,7 +181,7 @@ function gen_outbound(flag, node, tag, proxy_table)
} or nil, } or nil,
dialerProxy = dialer_proxy_tag, dialerProxy = dialer_proxy_tag,
}, },
[(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network" method = node.transport,
security = node.stream_security, security = node.stream_security,
tlsSettings = (node.stream_security == "tls") and { tlsSettings = (node.stream_security == "tls") and {
serverName = node.tls_serverName, serverName = node.tls_serverName,
@@ -665,7 +665,7 @@ function gen_config_server(node)
outbound_node_t = { outbound_node_t = {
type = node.type, type = node.type,
protocol = node.outbound_node:gsub("_", ""), protocol = node.outbound_node:gsub("_", ""),
transport = "tcp", transport = "raw",
address = node.outbound_node_address, address = node.outbound_node_address,
port = node.outbound_node_port, port = node.outbound_node_port,
username = (node.outbound_node_username and node.outbound_node_username ~= "") and node.outbound_node_username or nil, username = (node.outbound_node_username and node.outbound_node_username ~= "") and node.outbound_node_username or nil,
@@ -696,7 +696,7 @@ function gen_config_server(node)
protocol = node.protocol, protocol = node.protocol,
settings = settings, settings = settings,
streamSettings = { streamSettings = {
[(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network" method = node.transport,
security = "none", security = "none",
tlsSettings = ("1" == node.tls) and { tlsSettings = ("1" == node.tls) and {
disableSystemRoot = false, disableSystemRoot = false,
@@ -877,9 +877,6 @@ function gen_config_server(node)
config.outbounds[index][k] = nil config.outbounds[index][k] = nil
end end
end end
if value.protocol == "freedom" and api.compare_versions(xray_version, "<", "26.5.3") then -- Todo is to remove it
value.settings = nil
end
end end
return config return config
@@ -921,7 +918,7 @@ function gen_config(var)
local remote_dns_query_strategy = var["remote_dns_query_strategy"] local remote_dns_query_strategy = var["remote_dns_query_strategy"]
local remote_dns_detour = var["remote_dns_detour"] local remote_dns_detour = var["remote_dns_detour"]
local dns_cache = var["dns_cache"] local dns_cache = var["dns_cache"]
local no_run = var["no_run"] NO_RUN = var["no_run"]
local dns_domain_rules = {} local dns_domain_rules = {}
local dns = {} local dns = {}
@@ -1046,7 +1043,7 @@ function gen_config(var)
protocol = "socks", protocol = "socks",
address = "127.0.0.1", address = "127.0.0.1",
port = section.port, port = section.port,
transport = "tcp", transport = "raw",
stream_security = "none" stream_security = "none"
} }
end end
@@ -1104,7 +1101,7 @@ function gen_config(var)
end end
end end
if is_new_blc_node then if is_new_blc_node then
local outboundTag = gen_outbound_get_tag(flag, blc_node_id, blc_node_tag, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.noise == "1" or nil, run_socks_instance = not no_run }) local outboundTag = gen_outbound_get_tag(flag, blc_node_id, blc_node_tag, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.noise == "1" or nil })
if outboundTag then if outboundTag then
valid_nodes[#valid_nodes + 1] = outboundTag valid_nodes[#valid_nodes + 1] = outboundTag
end end
@@ -1133,7 +1130,7 @@ function gen_config(var)
local fallback_node = get_node_by_id(fallback_node_id) local fallback_node = get_node_by_id(fallback_node_id)
if fallback_node then if fallback_node then
if fallback_node.protocol ~= "_balancing" then if fallback_node.protocol ~= "_balancing" then
local outboundTag = gen_outbound_get_tag(flag, fallback_node, fallback_node_id, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.noise == "1" or nil, run_socks_instance = not no_run }) local outboundTag = gen_outbound_get_tag(flag, fallback_node, fallback_node_id, { fragment = xray_settings.fragment == "1" or nil, noise = xray_settings.noise == "1" or nil })
if outboundTag then if outboundTag then
fallback_node_tag = outboundTag fallback_node_tag = outboundTag
end end
@@ -1265,7 +1262,6 @@ function gen_config(var)
}) })
to_outbound = gen_outbound(node[".name"], to_node, to_node[".name"], { to_outbound = gen_outbound(node[".name"], to_node, to_node[".name"], {
tag = to_node[".name"], tag = to_node[".name"],
run_socks_instance = not no_run
}) })
else else
to_outbound = gen_outbound(node[".name"], to_node) to_outbound = gen_outbound(node[".name"], to_node)
@@ -1336,9 +1332,9 @@ function gen_config(var)
interface = node.iface interface = node.iface
} }
}, },
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check settings = {
finalRules = {{ action = "allow" }} finalRules = {{ action = "allow" }}
} or nil }
} }
sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface)) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.iface))
end end
@@ -1398,7 +1394,6 @@ function gen_config(var)
local proxy_table = { local proxy_table = {
fragment = xray_settings.fragment == "1", fragment = xray_settings.fragment == "1",
noise = xray_settings.noise == "1", noise = xray_settings.noise == "1",
run_socks_instance = not no_run,
} }
local preproxy_node_id = node[rule_name .. "_proxy_tag"] local preproxy_node_id = node[rule_name .. "_proxy_tag"]
if preproxy_node_id == _node_id then preproxy_node_id = nil end if preproxy_node_id == _node_id then preproxy_node_id = nil end
@@ -1750,12 +1745,10 @@ function gen_config(var)
}) })
local direct_type_dns = { local direct_type_dns = {
settings = { settings = {
address = direct_dns_udp_server, rewriteAddress = direct_dns_udp_server,
port = tonumber(direct_dns_udp_port) or 53, rewritePort = tonumber(direct_dns_udp_port) or 53,
network = "udp", rewriteNetwork = "udp",
nonIPQuery = (api.compare_versions(xray_version, "<", "26.4.25")) and "skip" or nil, -- Todo is to remove it rules = {
blockTypes = (api.compare_versions(xray_version, "<", "26.4.25")) and { 65 } or nil, -- Todo is to remove it
rules = (api.compare_versions(xray_version, ">", "26.4.17")) and {
{ {
qType = "1,28", qType = "1,28",
action = "hijack" action = "hijack"
@@ -1776,11 +1769,10 @@ function gen_config(var)
} }
local remote_type_dns = { local remote_type_dns = {
settings = { settings = {
address = remote_dns_udp_server, rewriteAddress = remote_dns_udp_server,
port = tonumber(remote_dns_udp_port) or 53, rewritePort = tonumber(remote_dns_udp_port) or 53,
network = _remote_dns_proto or "tcp", rewriteNetwork = _remote_dns_proto or "tcp",
nonIPQuery = (api.compare_versions(xray_version, "<", "26.4.25")) and "reject" or nil, -- Todo is to remove it rules = {
rules = (api.compare_versions(xray_version, ">", "26.4.17")) and {
{ {
qType = "1,28", qType = "1,28",
action = "hijack" action = "hijack"
@@ -2058,7 +2050,7 @@ function gen_config(var)
local direct_outbound = { local direct_outbound = {
protocol = "freedom", protocol = "freedom",
tag = "direct", tag = "direct",
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check settings = {
finalRules = {{ action = "allow" }} finalRules = {{ action = "allow" }}
} or nil, } or nil,
streamSettings = { streamSettings = {
@@ -2086,7 +2078,7 @@ function gen_config(var)
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
local s = value.settings local s = value.settings
if not value["_flag_proxy_tag"] and value["_id"] and s and not no_run and if not value["_flag_proxy_tag"] and value["_id"] and s and not NO_RUN and
((s.vnext and s.vnext[1] and s.vnext[1].address and s.vnext[1].port) or ((s.vnext and s.vnext[1] and s.vnext[1].address and s.vnext[1].port) or
(s.servers and s.servers[1] and s.servers[1].address and s.servers[1].port) or (s.servers and s.servers[1] and s.servers[1].address and s.servers[1].port) or
(s.peers and s.peers[1] and s.peers[1].endpoint) or (s.peers and s.peers[1] and s.peers[1].endpoint) or
@@ -2168,7 +2160,7 @@ function gen_proto_config(var)
local outbound = { local outbound = {
protocol = server_proto, protocol = server_proto,
streamSettings = { streamSettings = {
network = "tcp", method = "raw",
security = "none" security = "none"
}, },
settings = { settings = {
@@ -2192,10 +2184,12 @@ function gen_proto_config(var)
table.insert(outbounds, { table.insert(outbounds, {
protocol = "freedom", protocol = "freedom",
tag = "direct", tag = "direct",
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check settings = {
finalRules = {{ action = "allow" }} finalRules = {{ action = "allow" }}
} or nil, } or nil,
streamSettings = {
sockopt = {mark = 255} sockopt = {mark = 255}
}
}) })
local config = { local config = {
@@ -2204,7 +2198,10 @@ function gen_proto_config(var)
}, },
inbounds = inbounds, inbounds = inbounds,
outbounds = outbounds, outbounds = outbounds,
routing = routing routing = routing,
version = {
min = xray_min_version
}
} }
return jsonc.stringify(config, 1) return jsonc.stringify(config, 1)
end end
@@ -1,17 +1,12 @@
#!/bin/sh #!/bin/sh
# Devices without a hardware RTC boot with a wrong system clock: sysfixtime can [ "$ACTION" = "step" ] || exit 0
# only restore the mtime of the newest file under /etc, so the clock is usually
# hours behind after a cold boot. passwall2 is then started by
# /etc/hotplug.d/iface/98-passwall2 on ifup, which typically happens before NTP
# has corrected the time, and time-sensitive handshakes (VMess AEAD, TLS) fail.
#
# Nothing restarts passwall2 once the clock is corrected, so it stays broken
# until the user restarts it manually. Restart once when ntpd reports that the
# time is valid -- the same approach dnsmasq uses for DNSSEC in
# /etc/hotplug.d/ntp/25-dnsmasqsec.
[ "$ACTION" = "stratum" ] || exit 0 offset=${offset#-}
offset=${offset%.*}
# Skip service restart if the time adjustment is less than 120 seconds.
[ "$offset" -lt 120 ] && exit 0
. /usr/share/passwall2/utils.sh . /usr/share/passwall2/utils.sh
@@ -23,5 +18,5 @@ NTP_LOCK_FILE="${LOCK_PATH}/${CONFIG}_ntp.lock"
echo $$ > ${NTP_LOCK_FILE} echo $$ > ${NTP_LOCK_FILE}
/etc/init.d/${CONFIG} restart >/dev/null 2>&1 & /etc/init.d/${CONFIG} restart >/dev/null 2>&1 &
logger -p notice -t network -s "${CONFIG}: restart after NTP time became valid" logger -p notice -t network -s "${CONFIG}: restart after NTP time step (${offset}s)"
} }
@@ -856,8 +856,8 @@ acl_node() {
local DNSMASQ_LOCAL_DNS="${LOCAL_DNS:-${AUTO_DNS}}" local DNSMASQ_LOCAL_DNS="${LOCAL_DNS:-${AUTO_DNS}}"
[ -n "${DIRECT_DNS_DNSMASQ_SERVER}" ] && DNSMASQ_LOCAL_DNS="${DIRECT_DNS_DNSMASQ_SERVER}" [ -n "${DIRECT_DNS_DNSMASQ_SERVER}" ] && DNSMASQ_LOCAL_DNS="${DIRECT_DNS_DNSMASQ_SERVER}"
if [ "${flag}" = "acl_default" ]; then if [ "${flag}" = "acl_default" ]; then
set_cache_var "GLOBAL_SOCKS_server" "127.0.0.1:$socks_port" set_cache_var "ACL_${flag}_node" "$node"
set_cache_var "ACL_GLOBAL_node" "$node" set_cache_var "ACL_${flag}_node_socks_port" "$socks_port"
run_new_dnsmasq=$(config_n_get @global[0] dns_redirect 1) run_new_dnsmasq=$(config_n_get @global[0] dns_redirect 1)
if [ "${run_new_dnsmasq}" != "1" ]; then if [ "${run_new_dnsmasq}" != "1" ]; then
#Rewrite the default DNS service configuration #Rewrite the default DNS service configuration
@@ -865,15 +865,15 @@ acl_node() {
lua $APP_PATH/helper_dnsmasq.lua stretch lua $APP_PATH/helper_dnsmasq.lua stretch
json_init json_init
json_add_string "FLAG" "${flag}" json_add_string "FLAG" "${flag}"
json_add_string "TMP_DNSMASQ_PATH" "${GLOBAL_DNSMASQ_CONF_PATH}" json_add_string "TMP_DNSMASQ_PATH" "${DEFAULT_DNSMASQ_CONF_PATH}"
json_add_string "DNSMASQ_CONF_FILE" "${GLOBAL_DNSMASQ_CONF}" json_add_string "DNSMASQ_CONF_FILE" "${DEFAULT_DNSMASQ_CONF}"
json_add_string "DEFAULT_DNS" "${DNSMASQ_DEFAULT_DNS}" json_add_string "DEFAULT_DNS" "${DNSMASQ_DEFAULT_DNS}"
json_add_string "LOCAL_DNS" "${DNSMASQ_LOCAL_DNS}" json_add_string "LOCAL_DNS" "${DNSMASQ_LOCAL_DNS}"
json_add_string "TUN_DNS" "${DNSMASQ_TUN_DNS}" json_add_string "TUN_DNS" "${DNSMASQ_TUN_DNS}"
json_add_string "NFTFLAG" "${nftflag:-0}" json_add_string "NFTFLAG" "${nftflag:-0}"
json_add_string "NO_LOGIC_LOG" "${NO_LOGIC_LOG:-0}" json_add_string "NO_LOGIC_LOG" "${NO_LOGIC_LOG:-0}"
lua $APP_PATH/helper_dnsmasq.lua add_rule "$(json_dump)" lua $APP_PATH/helper_dnsmasq.lua add_rule "$(json_dump)"
uci -q add_list dhcp.@dnsmasq[0].addnmount=${GLOBAL_DNSMASQ_CONF_PATH} uci -q add_list dhcp.@dnsmasq[0].addnmount=${DEFAULT_DNSMASQ_CONF_PATH}
uci -q commit dhcp uci -q commit dhcp
lua $APP_PATH/helper_dnsmasq.lua logic_restart lua $APP_PATH/helper_dnsmasq.lua logic_restart
@@ -973,8 +973,8 @@ stop() {
unset XRAY_LOCATION_ASSET unset XRAY_LOCATION_ASSET
unset SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN unset SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN
stop_crontab stop_crontab
rm -rf $GLOBAL_DNSMASQ_CONF rm -rf $DEFAULT_DNSMASQ_CONF
rm -rf $GLOBAL_DNSMASQ_CONF_PATH rm -rf $DEFAULT_DNSMASQ_CONF_PATH
[ "1" = "1" ] && { [ "1" = "1" ] && {
#restore logic #restore logic
bak_dnsmasq_dns_redirect=$(config_n_get @global[0] dnsmasq_dns_redirect) bak_dnsmasq_dns_redirect=$(config_n_get @global[0] dnsmasq_dns_redirect)
@@ -985,7 +985,7 @@ stop() {
uci -q commit ${CONFIG} uci -q commit ${CONFIG}
} }
if [ -z "${ACL_default_dns_port}" ] || [ -n "${bak_dnsmasq_dns_redirect}" ]; then if [ -z "${ACL_default_dns_port}" ] || [ -n "${bak_dnsmasq_dns_redirect}" ]; then
uci -q del_list dhcp.@dnsmasq[0].addnmount="${GLOBAL_DNSMASQ_CONF_PATH}" uci -q del_list dhcp.@dnsmasq[0].addnmount="${DEFAULT_DNSMASQ_CONF_PATH}"
uci -q commit dhcp uci -q commit dhcp
json_init json_init
@@ -1061,8 +1061,8 @@ get_config() {
DNSMASQ_CONF_DIR=${DEFAULT_DNSMASQ_CONF_DIR} DNSMASQ_CONF_DIR=${DEFAULT_DNSMASQ_CONF_DIR}
fi fi
fi fi
set_cache_var GLOBAL_DNSMASQ_CONF ${DNSMASQ_CONF_DIR}/dnsmasq-${CONFIG}.conf set_cache_var DEFAULT_DNSMASQ_CONF ${DNSMASQ_CONF_DIR}/dnsmasq-${CONFIG}.conf
set_cache_var GLOBAL_DNSMASQ_CONF_PATH ${TMP_ACL_PATH}/acl_default_dnsmasq.d set_cache_var DEFAULT_DNSMASQ_CONF_PATH ${TMP_ACL_PATH}/acl_default_dnsmasq.d
QUEUE_RUN=1 QUEUE_RUN=1
} }
@@ -230,7 +230,7 @@ gen_shunt_list() {
} }
[ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\" [ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\"
[ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\" [ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\"
set_cache_var "gen_shunt_list_${node}" "1" set_cache_var "node_${node}_gen_shunt_list" "1"
} }
add_shunt_t_rule() { add_shunt_t_rule() {
@@ -261,7 +261,7 @@ load_acl() {
for sid in $(jsonfilter -s "${ACL_JSON}" -e '$.acl[*].flag'); do for sid in $(jsonfilter -s "${ACL_JSON}" -e '$.acl[*].flag'); do
eval local $(cat "${TMP_ACL_PATH}/${sid}/var") eval local $(cat "${TMP_ACL_PATH}/${sid}/var")
[ -z "$(get_cache_var "gen_shunt_list_${node}")" ] && [ -n "${node}" ] && gen_shunt_list "${node}" shunt_list4 shunt_list6 [ -z "$(get_cache_var "node_${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 "${use}" ] && local dns_redirect_port=$(get_cache_var "ACL_${use}_dns_port")
local ipt_tmp=$ipt_n local ipt_tmp=$ipt_n
@@ -271,7 +271,7 @@ gen_shunt_list() {
} }
[ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\" [ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\"
[ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\" [ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\"
set_cache_var "gen_shunt_list_${node}" "1" set_cache_var "node_${node}_gen_shunt_list" "1"
} }
add_shunt_t_rule() { add_shunt_t_rule() {
@@ -299,7 +299,7 @@ load_acl() {
for sid in $(jsonfilter -s "${ACL_JSON}" -e '$.acl[*].flag'); do for sid in $(jsonfilter -s "${ACL_JSON}" -e '$.acl[*].flag'); do
eval $(cat "${TMP_ACL_PATH}/${sid}/var") eval $(cat "${TMP_ACL_PATH}/${sid}/var")
[ -z "$(get_cache_var "gen_shunt_list_${node}")" ] && [ -n "${node}" ] && gen_shunt_list "${node}" shunt_list4 shunt_list6 [ -z "$(get_cache_var "node_${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 "${use}" ] && local dns_redirect_port=$(get_cache_var "ACL_${use}_dns_port")
[ "${local_proxy}" = "1" ] && { [ "${local_proxy}" = "1" ] && {
@@ -650,14 +650,14 @@ prepare_clash_runtime_config() {
enable: false enable: false
EOF EOF
# 根据 dns_mode 添加不同的 dns 配置
if [ "$dns_mode" = "7" ]; then
# 根据 enable_fake_ip 决定 enhanced-mode # 根据 enable_fake_ip 决定 enhanced-mode
if [ "$enable_fake_ip" = "1" ]; then if [ "$enable_fake_ip" = "1" ]; then
ENHANCED_MODE="fake-ip" ENHANCED_MODE="fake-ip"
else else
ENHANCED_MODE="redir-host" ENHANCED_MODE="redir-host"
fi fi
# 根据 dns_mode 添加不同的 dns 配置
if [ "$dns_mode" = "7" ]; then
cat >> "$overlay_file" <<-EOF cat >> "$overlay_file" <<-EOF
dns: dns:
enable: true enable: true
@@ -668,7 +668,9 @@ prepare_clash_runtime_config() {
else else
cat >> "$overlay_file" <<-EOF cat >> "$overlay_file" <<-EOF
dns: dns:
enable: false enable: true
enhanced-mode: $ENHANCED_MODE
ipv6: $( [ "$dns_ipv4_only" = "1" ] && echo "false" || echo "true" )
EOF EOF
fi fi
@@ -681,7 +683,7 @@ prepare_clash_runtime_config() {
if [ "$socks5_auth" = "password" ]; then if [ "$socks5_auth" = "password" ]; then
if [ -z "$socks5_user" ] || [ -z "$socks5_pass" ]; then if [ -z "$socks5_user" ] || [ -z "$socks5_pass" ]; then
echolog "警告:SOCKS5 代理未完整配置用户名或密码,已自动降级为无认证模式 (noauth)" echolog "警告:SOCKS5 代理未完整配置用户名或密码,已自动降级为无认证模式 (noauth)"
socks5_auth="noauth" socks5_auth="noauth"
fi fi
fi fi
@@ -653,17 +653,14 @@ local function build_dns_upstreams()
} }
end end
local function build_dns_section(dns_mode, user_dns, is_external_dns) local function build_dns_section(dns_mode, user_dns)
local result local result
local has_user_dns = type(user_dns) == "table" and next(user_dns) local has_user_dns = type(user_dns) == "table" and next(user_dns)
dns_mode = tostring(dns_mode or "0")
if not has_user_dns then if not has_user_dns then
if is_external_dns then
return { enable = false }
end
result = { result = {
enable = true, enable = true
listen = "127.0.0.1:5335"
} }
else else
result = clone_table(user_dns) result = clone_table(user_dns)
@@ -749,7 +746,7 @@ local function build_dns_section(dns_mode, user_dns, is_external_dns)
for k, v in pairs(upstreams) do for k, v in pairs(upstreams) do
if k == "proxy-server-nameserver" then if k == "proxy-server-nameserver" then
result[k] = v result[k] = v
elseif result[k] == nil then elseif result[k] == nil and not (k == "respect-rules" and enable_fake_ip ~= "1") then
result[k] = v result[k] = v
end end
end end
@@ -862,7 +859,8 @@ local function apply_sniffer_config(doc, enable_fake_ip)
["override-destination"] = true, ["override-destination"] = true,
sniff = { sniff = {
HTTP = { HTTP = {
ports = { 80, 2052, 2082, 2086, 2095, "8080-8880" } ports = { 80, 2052, 2082, 2086, 2095, "8080-8880" },
["override-destination"] = true
}, },
TLS = { TLS = {
ports = { 443, 2053, 2083, 2087, 2096, 8443 } ports = { 443, 2053, 2083, 2087, 2096, 8443 }
@@ -1603,8 +1601,6 @@ end
local function build_single_proxy_runtime_doc(proxy, local_port, socks_port, mode) local function build_single_proxy_runtime_doc(proxy, local_port, socks_port, mode)
local listen_port = tonumber(local_port) local listen_port = tonumber(local_port)
local socks_listen = tonumber(socks_port) local socks_listen = tonumber(socks_port)
local mode_str = tostring(dns_mode or "")
local is_ext_dns = (mode_str ~= "7")
local doc = { local doc = {
["allow-lan"] = true, ["allow-lan"] = true,
@@ -1629,8 +1625,9 @@ local function build_single_proxy_runtime_doc(proxy, local_port, socks_port, mod
["store-selected"] = true, ["store-selected"] = true,
["store-fake-ip"] = true ["store-fake-ip"] = true
}, },
dns = build_dns_section(dns_mode, nil, is_ext_dns) dns = build_dns_section(dns_mode, nil)
} }
apply_sniffer_config(doc, enable_fake_ip)
if mode == "socks" then if mode == "socks" then
doc["socks-port"] = listen_port doc["socks-port"] = listen_port
@@ -1641,6 +1638,23 @@ local function build_single_proxy_runtime_doc(proxy, local_port, socks_port, mod
doc["socks-port"] = socks_listen doc["socks-port"] = socks_listen
end end
end end
if doc["socks-port"] and doc["socks-port"] > 0 then
local socks5_auth = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_auth", "noauth")
if socks5_auth == "password" then
local socks5_user = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_user", "")
local socks5_pass = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_pass", "")
if socks5_user == "" or socks5_pass == "" then
io.stderr:write("警告:SOCKS5 代理未完整配置用户名或密码,已自动降级为无认证模式 (noauth)!\n")
else
doc["authentication"] = {
string.format("%s:%s", socks5_user, socks5_pass)
}
end
end
end
return doc return doc
end end
@@ -1650,8 +1664,6 @@ local function build_tuic_runtime_doc(sid, local_port, socks_port, mode)
local tuic_ip = get_server_field(sid, "tuic_ip", "") local tuic_ip = get_server_field(sid, "tuic_ip", "")
local tls_host = get_server_field(sid, "tls_host", "") local tls_host = get_server_field(sid, "tls_host", "")
local ipstack_prefer = get_server_field(sid, "ipstack_prefer", "") local ipstack_prefer = get_server_field(sid, "ipstack_prefer", "")
local mode_str = tostring(dns_mode or "")
local is_ext_dns = (mode_str ~= "7")
local proxy = { local proxy = {
name = sid, name = sid,
@@ -1724,8 +1736,9 @@ local function build_tuic_runtime_doc(sid, local_port, socks_port, mode)
["store-selected"] = true, ["store-selected"] = true,
["store-fake-ip"] = true ["store-fake-ip"] = true
}, },
dns = build_dns_section(dns_mode, nil, is_ext_dns) dns = build_dns_section(dns_mode, nil)
} }
apply_sniffer_config(doc, enable_fake_ip)
if mode == "socks" then if mode == "socks" then
doc["socks-port"] = listen_port doc["socks-port"] = listen_port
@@ -1737,6 +1750,22 @@ local function build_tuic_runtime_doc(sid, local_port, socks_port, mode)
end end
end end
if doc["socks-port"] and doc["socks-port"] > 0 then
local socks5_auth = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_auth", "noauth")
if socks5_auth == "password" then
local socks5_user = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_user", "")
local socks5_pass = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_pass", "")
if socks5_user == "" or socks5_pass == "" then
io.stderr:write("警告:SOCKS5 代理未完整配置用户名或密码,已自动降级为无认证模式 (noauth)!\n")
else
doc["authentication"] = {
string.format("%s:%s", socks5_user, socks5_pass)
}
end
end
end
return doc return doc
end end
@@ -1745,8 +1774,7 @@ local function build_shadowsocks_runtime_doc(sid, local_port, socks_port, mode)
local server_port = tonumber(get_server_field(sid, "server_port", "0")) or 0 local server_port = tonumber(get_server_field(sid, "server_port", "0")) or 0
local method = get_server_field(sid, "encrypt_method_ss", "none") local method = get_server_field(sid, "encrypt_method_ss", "none")
local password = get_server_field(sid, "password", "") local password = get_server_field(sid, "password", "")
local mode_str = tostring(dns_mode or "")
local is_ext_dns = (mode_str ~= "7")
local proxy = { local proxy = {
name = sid, name = sid,
type = "ss", type = "ss",
@@ -1788,8 +1816,9 @@ local function build_shadowsocks_runtime_doc(sid, local_port, socks_port, mode)
["store-selected"] = true, ["store-selected"] = true,
["store-fake-ip"] = true ["store-fake-ip"] = true
}, },
dns = build_dns_section(dns_mode, nil, is_ext_dns) dns = build_dns_section(dns_mode, nil)
} }
apply_sniffer_config(doc, enable_fake_ip)
local listen_port = tonumber(local_port) local listen_port = tonumber(local_port)
local socks_listen = tonumber(socks_port) local socks_listen = tonumber(socks_port)
@@ -1803,6 +1832,22 @@ local function build_shadowsocks_runtime_doc(sid, local_port, socks_port, mode)
end end
end end
if doc["socks-port"] and doc["socks-port"] > 0 then
local socks5_auth = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_auth", "noauth")
if socks5_auth == "password" then
local socks5_user = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_user", "")
local socks5_pass = uci:get_first("shadowsocksr", "socks5_proxy", "socks5_pass", "")
if socks5_user == "" or socks5_pass == "" then
io.stderr:write("警告:SOCKS5 代理未完整配置用户名或密码,已自动降级为无认证模式 (noauth)!\n")
else
doc["authentication"] = {
string.format("%s:%s", socks5_user, socks5_pass)
}
end
end
end
return doc return doc
end end
@@ -1988,10 +2033,7 @@ local function prepare(input_path, output_path)
local filled_groups = fill_empty_proxy_groups(doc) local filled_groups = fill_empty_proxy_groups(doc)
local stripped_rules = strip_incompatible_script_rules(doc) local stripped_rules = strip_incompatible_script_rules(doc)
local dns_config = build_dns_section(dns_mode, user_dns, false) doc.dns = build_dns_section(dns_mode, user_dns)
if dns_config and next(dns_config) then
doc.dns = dns_config
end
doc.rules = merge_rules_with_direct(doc.rules) doc.rules = merge_rules_with_direct(doc.rules)
apply_sniffer_config(doc, enable_fake_ip) apply_sniffer_config(doc, enable_fake_ip)
@@ -2002,6 +2044,7 @@ local function prepare(input_path, output_path)
if doc["tcp-concurrent"] == nil then if doc["tcp-concurrent"] == nil then
doc["tcp-concurrent"] = true doc["tcp-concurrent"] = true
end end
if doc["find-process-mode"] == nil then if doc["find-process-mode"] == nil then
doc["find-process-mode"] = "off" doc["find-process-mode"] = "off"
end end
@@ -2035,21 +2078,13 @@ local function merge(raw_path, overlay_path, output_path)
strip_runtime_conflicts(raw_doc) strip_runtime_conflicts(raw_doc)
local filled_groups = fill_empty_proxy_groups(raw_doc) local filled_groups = fill_empty_proxy_groups(raw_doc)
local stripped_rules = strip_incompatible_script_rules(raw_doc) local stripped_rules = strip_incompatible_script_rules(raw_doc)
if user_dns then
if dns_mode ~= "7" then
overlay_doc.dns = nil
end
end
local merged = deep_merge(raw_doc, overlay_doc) local merged = deep_merge(raw_doc, overlay_doc)
if user_dns then
merged.dns = build_dns_section(dns_mode, user_dns, false) local target_dns = user_dns
elseif type(merged.dns) == "table" and next(merged.dns) then if not target_dns and type(merged.dns) == "table" and next(merged.dns) then
merged.dns = build_dns_section(dns_mode, merged.dns, false) target_dns = merged.dns
else
merged.dns = build_dns_section(dns_mode, nil, false)
end end
merged.dns = build_dns_section(dns_mode, target_dns)
merged.rules = merge_rules_with_direct(merged.rules) merged.rules = merge_rules_with_direct(merged.rules)
apply_sniffer_config(merged, enable_fake_ip) apply_sniffer_config(merged, enable_fake_ip)
@@ -2060,6 +2095,7 @@ local function merge(raw_path, overlay_path, output_path)
if merged["tcp-concurrent"] == nil then if merged["tcp-concurrent"] == nil then
merged["tcp-concurrent"] = true merged["tcp-concurrent"] = true
end end
if merged["find-process-mode"] == nil then if merged["find-process-mode"] == nil then
merged["find-process-mode"] = "off" merged["find-process-mode"] = "off"
end end
@@ -1714,7 +1714,7 @@ local function processData(szType, content, cfgid)
result.quic_security = params.quicSecurity or "none" result.quic_security = params.quicSecurity or "none"
result.quic_key = params.key result.quic_key = params.key
elseif result.transport == "grpc" then elseif result.transport == "grpc" then
result.serviceName = params.serviceName result.serviceName = params.servicename
result.grpc_mode = params.mode or "gun" result.grpc_mode = params.mode or "gun"
elseif result.transport == "tcp" or result.transport == "raw" then elseif result.transport == "tcp" or result.transport == "raw" then
result.tcp_guise = params.headerType and params.headerType ~= "" and params.headerType or "none" result.tcp_guise = params.headerType and params.headerType ~= "" and params.headerType or "none"
+6 -20
View File
@@ -1,10 +1,9 @@
# SPDX-License-Identifier: GPL-3.0-only # SPDX-License-Identifier: GPL-3.0-only
# #
# Copyright (C) 2021-2025 sirpdboy <herboy2008@gmail.com> # Copyright (C) 2021-2022 sirpdboy <herboy2008@gmail.com>
# #
# This is free software, licensed under the Apache License, Version 2.0 . # This is free software, licensed under the Apache License, Version 2.0 .
# #
#
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
@@ -26,12 +25,8 @@ ifeq ($(ARCH),x86_64)
LUCKY_ARCH:=x86_64 LUCKY_ARCH:=x86_64
endif endif
ifeq ($(ARCH),arm) ifeq ($(ARCH),arm)
ifeq ($(BOARD),bcm53xx)
LUCKY_ARCH:=armv6
else
LUCKY_ARCH:=armv7 LUCKY_ARCH:=armv7
endif endif
endif
ifeq ($(BOARD),bcm53xx) ifeq ($(BOARD),bcm53xx)
LUCKY_ARCH:=armv6 LUCKY_ARCH:=armv6
ifeq ($(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE)))),) ifeq ($(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE)))),)
@@ -50,42 +45,33 @@ PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=GDY666 <gdy666@foxmail.com> PKG_MAINTAINER:=GDY666 <gdy666@foxmail.com>
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=skip PKG_HASH:=0216c9a833724875f4a004aa5fc5e6e1a2d9f92f99e933905f76ebf7876b413c
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME) define Package/$(PKG_NAME)
SECTION:=net SECTION:=net
CATEGORY:=Network CATEGORY:=Network
TITLE:=Lucky gdy TITLE:=Lucky dynamic domain name ddns-go service, socat,frp
DEPENDS:=@(i386||x86_64||arm||aarch64||mipsel||mips) DEPENDS:=@(i386||x86_64||arm||aarch64||mipsel||mips)
URL:=https://github.com/gdy666/lucky URL:=https://github.com/gdy666/lucky
endef endef
define Package/$(PKG_NAME)/description define Package/$(PKG_NAME)/description
Main functions of Lucky: ipv4/ipv6 portforward,ddns,IOT wake on lan ,reverse proxy and more... Main functions of Lucky: dynamic domain name ddns-go service, socat,reverse proxy ,wake on lan
endef endef
define Build/Prepare define Build/Prepare
[ ! -f $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz ] && wget https://github.com/gdy666/lucky/releases/download/v$(PKG_VERSION)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -O $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz [ ! -f $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz ] && wget https://github.com/gdy666/lucky/releases/download/v$(PKG_VERSION)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -O $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz
tar -xzvf $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -C $(PKG_BUILD_DIR) || exit 1 tar -xzvf $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -C $(PKG_BUILD_DIR)
endef endef
define Package/$(PKG_NAME)/conffiles
/etc/config/lucky
/etc/lucky/*
endef
define Build/Compile define Build/Compile
endef endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin/ $(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_DIR) $(1)/etc/init.d/
$(INSTALL_DIR) $(1)/etc/config/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lucky $(1)/usr/bin/lucky $(INSTALL_BIN) $(PKG_BUILD_DIR)/lucky $(1)/usr/bin/lucky
$(INSTALL_BIN) $(CURDIR)/files/luckyarch.bin $(1)/usr/bin/luckyarch
$(INSTALL_BIN) ./files/lucky.init $(1)/etc/init.d/lucky
$(INSTALL_CONF) $(CURDIR)/files/lucky.config $(1)/etc/config/lucky
endef endef
$(eval $(call BuildPackage,$(PKG_NAME))) $(eval $(call BuildPackage,$(PKG_NAME)))
-5
View File
@@ -1,5 +0,0 @@
config lucky 'lucky'
option logger '1'
option port '16601'
option configdir '/etc/lucky'
option enabled '0'
-81
View File
@@ -1,81 +0,0 @@
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2021-2025 sirpdboy <herboy2008@gmail.com> https://github.com/sirpdboy/luci-app-lucky
# This file is part of lucky .
#
# This is free software, licensed under the Apache License, Version 2.0 .
START=99
STOP=15
USE_PROCD=1
CONF=lucky
PROG=/usr/bin/lucky
CONFDIR=/etc/lucky
get_config() {
config_get_bool enabled $1 enabled 0
config_get_bool logger $1 logger 1
config_get port $1 port 16601
config_get SafeURL $1 safe
config_get delay $1 delay 0
}
init_config(){
config_load "$CONF"
config_foreach get_config "$CONF"
}
init_confdir(){
[ -d $CONFDIR ] || mkdir -p $CONFDIR 2>/dev/null
}
LOG(){
echo "$1"
logger -t lucky -p warn "$1"
}
start_instance() {
enabled=$(uci -q get $CONF.$CONF.enabled ) || enabled="0"
logger=$(uci -q get $CONF.$CONF.logger ) || logger="1"
port=$(uci -q get $CONF.$CONF.port ) || port="16601"
SafeURL=$(uci -q get $CONF.$CONF.safe ) || SafeURL=" "
delay=$(uci -q get $CONF.$CONF.delay ) || delay="5"
SafeURL="${SafeURL##*( )}"
SafeURL="${SafeURL%%*( )}"
init_confdir
[ x$enabled = x1 ] || return 1
[ $(awk -F. '{print $1}' /proc/uptime) -lt "120" ] && sleep $delay
$(which lucky) -setconf -key AdminWebListenPort -value $port -cd $CONFDIR
if [ -z "$SafeURL" ] ; then
$(which lucky) -rCancelSafeURL
else
$(which lucky) -setconf -key SafeURL -value "$SafeURL" -cd $CONFDIR
fi
procd_open_instance
procd_set_param command $PROG
procd_append_param command -cd $CONFDIR
procd_set_param respawn
procd_set_param stderr 1
procd_close_instance
LOG "lucky is start."
}
start_service() {
pgrep -f $PROG | xargs kill -9 >/dev/null 2>&1
start_instance
}
stop_service() {
pgrep -f $PROG | xargs kill -9 >/dev/null 2>&1
LOG "lucky is stop."
}
service_triggers() {
procd_add_reload_trigger lucky
}
-14
View File
@@ -1,14 +0,0 @@
#!/bin/sh
cputype=$(uname -ms | tr ' ' '_' | tr '[A-Z]' '[a-z]')
[ -n "$(echo $cputype | grep -E "linux.*armv.*")" ] && cpucore="armv5"
[ -n "$(echo $cputype | grep -E "linux.*armv7.*")" ] && [ -n "$(cat /proc/cpuinfo | grep vfp)" ] && [ ! -d /jffs/clash ] && cpucore="armv7"
[ -n "$(echo $cputype | grep -E "linux.*aarch64.*|linux.*armv8.*")" ] && cpucore="arm64"
[ -n "$(echo $cputype | grep -E "linux.*86.*")" ] && cpucore="i386"
[ -n "$(echo $cputype | grep -E "linux.*86_64.*")" ] && cpucore="x86_64"
if [ -n "$(echo $cputype | grep -E "linux.*mips.*")" ];then
mipstype=$(echo -n I | hexdump -o 2>/dev/null | awk '{ print substr($2,6,1); exit}') #通过判断大小端判断mips或mipsle
[ "$mipstype" = "0" ] && cpucore="mips_softfloat" || cpucore="mipsle_softfloat"
fi
echo $cpucore
+1 -1
View File
@@ -80,7 +80,7 @@ export function load_profile() {
let result = {}; let result = {};
const process = popen('yq -M -p yaml -o json /etc/nikki/run/config.yaml'); const process = popen('yq -M -p yaml -o json /etc/nikki/run/config.yaml');
if (process) { if (process) {
result = json(process); result = json(process.read('all'));
process.close(); process.close();
} }
return result; return result;
+2 -2
View File
@@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=sing-box PKG_NAME:=sing-box
PKG_VERSION:=1.14.0 PKG_VERSION:=1.14.1
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)? PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=87baf6852e37941cbe40bdd94bec81c957c88a56751cecd6bbf0e6108bc69398 PKG_HASH:=1ea41f7d06b0017fe3d3ba7ee30959048aa0ddde31cb0165dab9257edf673321
PKG_LICENSE:=GPL-3.0-or-later PKG_LICENSE:=GPL-3.0-or-later
PKG_LICENSE_FILES:=LICENSE PKG_LICENSE_FILES:=LICENSE
+3 -3
View File
@@ -21,16 +21,16 @@ define Download/geoip
HASH:=1cba1f0982cf62502fa079c66047c3d0c608196da5b3305671e68f60e917a482 HASH:=1cba1f0982cf62502fa079c66047c3d0c608196da5b3305671e68f60e917a482
endef endef
GEOSITE_VER:=20260908094002 GEOSITE_VER:=20260914091725
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER) GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
define Download/geosite define Download/geosite
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/ URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
URL_FILE:=dlc.dat URL_FILE:=dlc.dat
FILE:=$(GEOSITE_FILE) FILE:=$(GEOSITE_FILE)
HASH:=35ed26a24cafa1256bd7261414224b7bcef5c944cea7760e172b030a8b266450 HASH:=4f4df95fee39f8824449f271d773b28eb1f4471aa733d01750209df0dc373091
endef endef
GEOSITE_IRAN_VER:=202609070121 GEOSITE_IRAN_VER:=202609140147
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER) GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
define Download/geosite-ir define Download/geosite-ir
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/ URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/