Compare commits

..
5 Commits
Author SHA1 Message Date
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
37 changed files with 725 additions and 471 deletions
+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:=dc66a8a
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:=dc66a8a180c0fa1c2b91cf5413426e68dbca320e
PKG_HASH:=593e53b3aeb52bbd3f49ddf4ae7773ce340bf2e984a9d5634a6385fa3041b5a2 PKG_HASH:=e7003359dc55a62a6f31b45f9123fc14a0a58f66c8cc4a3514ab15e94f08008b
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
} }
+118 -16
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
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
} }
trap cleanup_child TERM INT
/usr/bin/daed "$@" & exit_with_signal() {
child_pid=$! local sig="$1"
wait "$child_pid" trap - TERM INT HUP QUIT
status=$? kill -"$sig" "$$" 2>/dev/null
child_pid= exit 1
trap - TERM INT }
if ! daed_cleanup_runtime; then child_is_running() {
echo "daed: runtime cleanup after exit failed" >&2 local state
status=1 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 "$@" &
child_pid=$!
if [ -n "$pending_signal" ]; then
sig="$pending_signal"
pending_signal=
forward_signal "$sig"
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 fi
exit "$status"
# 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"
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"
}
@@ -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
@@ -105,13 +105,26 @@ function gen_outbound(flag, node, tag, proxy_table)
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
if run_socks_instance then
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 +132,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
+42 -33
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)
@@ -58,15 +58,24 @@ function gen_outbound(flag, node, tag, proxy_table)
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() if run_socks_instance then
local config_file = string.format("%s_%s_%s.json", flag, tag, new_port) local relay_port = (proxy_tag and node.port) and tostring(node.port) or ""
if tag and node_id and not tag:find(node_id) then if relay_port == "" then
config_file = string.format("%s_%s_%s_%s.json", flag, tag, node_id, new_port) 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,
@@ -483,7 +499,7 @@ function gen_config_server(node)
local settings = nil local settings = nil
local routing = nil local routing = nil
local outbounds = { local outbounds = {
{ protocol = "freedom", tag = "direct", settings = { finalRules = {{ action = "allow" }}}}, { protocol = "blackhole", tag = "blocked" } { protocol = "freedom", tag = "direct", finalRules = {{ action = "allow" }}}, { protocol = "blackhole", tag = "blocked" }
} }
local users = node.users or {} local users = node.users or {}
@@ -631,10 +647,8 @@ function gen_config_server(node)
interface = node.outbound_node_iface interface = node.outbound_node_iface
} }
}, },
settings = {
finalRules = {{ action = "allow" }} finalRules = {{ action = "allow" }}
} }
}
sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface)) sys.call(string.format("mkdir -p %s && touch %s/%s", api.TMP_IFACE_PATH, api.TMP_IFACE_PATH, node.outbound_node_iface))
else else
local outbound_node_t = api.uci_get_c(node.outbound_node) local outbound_node_t = api.uci_get_c(node.outbound_node)
@@ -675,7 +689,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 +871,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
@@ -1316,9 +1327,7 @@ function gen_config(var)
interface = node.iface interface = node.iface
} }
}, },
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check
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
@@ -1802,11 +1811,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 +2038,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 finalRules = {{ action = "allow" }},
finalRules = {{ action = "allow" }}
} or nil,
streamSettings = { streamSettings = {
sockopt = { sockopt = {
mark = 255, mark = 255,
@@ -2136,7 +2142,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 +2167,10 @@ 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 finalRules = {{ action = "allow" }},
finalRules = {{ action = "allow" }} streamSettings = {
} or nil,
sockopt = {mark = 255} sockopt = {mark = 255}
}
}) })
local config = { local config = {
@@ -2176,7 +2182,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
-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)"
} }
@@ -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)
@@ -384,16 +384,26 @@ lua_api() {
echo $(lua -e "local api = require 'luci.passwall.api' print(api.${func})") echo $(lua -e "local api = require 'luci.passwall.api' print(api.${func})")
} }
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() { set_cache_var() {
local key="${1}" local key="${1}"
shift 1 shift 1
[ -n "${key}" ] && {
del_cache_var ${key}
local val="$@" local val="$@"
[ -n "${key}" ] && [ -n "${val}" ] && { [ -n "${val}" ] && {
[ ! -d $TMP_PATH ] && mkdir -p $TMP_PATH [ ! -d $TMP_PATH ] && mkdir -p $TMP_PATH
sed -i "/${key}=/d" $TMP_PATH/var >/dev/null 2>&1
echo "${key}=\"${val}\"" >> $TMP_PATH/var echo "${key}=\"${val}\"" >> $TMP_PATH/var
eval ${key}=\"${val}\" eval ${key}=\"${val}\"
} }
}
} }
get_cache_var() { get_cache_var() {
@@ -470,25 +480,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))
@@ -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;
+1 -1
View File
@@ -30,7 +30,7 @@ define Download/geosite
HASH:=35ed26a24cafa1256bd7261414224b7bcef5c944cea7760e172b030a8b266450 HASH:=35ed26a24cafa1256bd7261414224b7bcef5c944cea7760e172b030a8b266450
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)/