diff --git a/.github/diy/patches/tailscale.patch b/.github/diy/patches/tailscale.patch index bac203694..4741f84f9 100644 --- a/.github/diy/patches/tailscale.patch +++ b/.github/diy/patches/tailscale.patch @@ -1,41 +1,129 @@ --- a/luci-app-tailscale/Makefile +++ b/luci-app-tailscale/Makefile -@@ -42,7 +39,8 @@ disable_legacy_hotplug() { - - disable_legacy_hotplug || exit 1 +@@ -7,107 +7,40 @@ include $(TOPDIR)/rules.mk + LUCI_TITLE:=LuCI for Tailscale + LUCI_DEPENDS:=+tailscale +jshn +curl +jq +flock + LUCI_PKGARCH:=all +- + PKG_VERSION:=1.2.17 +-# Keep UCI configs as ordinary package data. The pre-install hook snapshots an +-# existing configuration before extraction; the UCI-defaults script restores it +-# afterwards. Declaring the same files as opkg conffiles conflicts with this +-# lifecycle and creates inactive *-opkg files during upgrades. +-define Package/luci-app-tailscale/preinst +-#!/bin/sh +-state_dir=/etc/.luci-app-tailscale-upgrade +-state_pending="$${state_dir}.pending" +-legacy_hotplug=/etc/hotplug.d/iface/40-tailscale +-legacy_backup_dir=/etc/tailscale/luci-app-tailscale-legacy +- +-[ -n "$${IPKG_INSTROOT}" ] && exit 0 +- +-disable_legacy_hotplug() { +- local backup_file +- +- [ -e "$${legacy_hotplug}" ] || [ -L "$${legacy_hotplug}" ] || return 0 +- backup_file="$${legacy_backup_dir}/40-tailscale.disabled.$$(date +%Y%m%d%H%M%S).$$$$" +- if mkdir -p "$${legacy_backup_dir}" 2>/dev/null && cp -p "$${legacy_hotplug}" "$${backup_file}"; then +- : +- else +- rm -f "$${backup_file}" 2>/dev/null || true +- fi +- +- # Disabling the duplicate starter is mandatory even when its backup fails. +- # chmod is a last-resort guard for a transient remove failure; package +- # extraction will subsequently remove the obsolete package-owned path. +- rm -f "$${legacy_hotplug}" || chmod 000 "$${legacy_hotplug}" || return 1 +-} +- +-disable_legacy_hotplug || exit 1 +- -[ -f /etc/config/tailscale ] || exit 0 -+# 若系统内无任何相关配置文件,说明是全新安装,直接退出让包管理器正常解压释放默认配置 -+[ -f /etc/config/tailscale ] || [ -f /etc/config/tailscale_openclash ] || [ -f /etc/config/tailscale_policy_routing ] || exit 0 - [ -f "$${state_dir}/.complete" ] && exit 0 - - clear_state_dir() { -@@ -54,20 +52,26 @@ clear_state_dir() { - - clear_state_dir "$${state_dir}" || exit 1 - clear_state_dir "$${state_pending}" || exit 1 -+ - umask 077 - mkdir "$${state_pending}" || exit 1 - chmod 700 "$${state_pending}" || exit 1 +-[ -f "$${state_dir}/.complete" ] && exit 0 +- +-clear_state_dir() { +- rm -f "$${1}/tailscale" "$${1}/tailscale_openclash" \ +- "$${1}/tailscale_openclash.absent" "$${1}/tailscale_policy_routing" \ +- "$${1}/.complete" +- rmdir "$${1}" 2>/dev/null || [ ! -e "$${1}" ] +-} +- +-clear_state_dir "$${state_dir}" || exit 1 +-clear_state_dir "$${state_pending}" || exit 1 +-umask 077 +-mkdir "$${state_pending}" || exit 1 +-chmod 700 "$${state_pending}" || exit 1 -cp /etc/config/tailscale "$${state_pending}/tailscale" || exit 1 -+ -+if [ -f /etc/config/tailscale ]; then -+ cp /etc/config/tailscale "$${state_pending}/tailscale" || exit 1 -+fi -+ - if [ -f /etc/config/tailscale_openclash ]; then - cp /etc/config/tailscale_openclash "$${state_pending}/tailscale_openclash" || exit 1 +-if [ -f /etc/config/tailscale_openclash ]; then +- cp /etc/config/tailscale_openclash "$${state_pending}/tailscale_openclash" || exit 1 -else - : >"$${state_pending}/tailscale_openclash.absent" || exit 1 +-fi +-if [ -f /etc/config/tailscale_policy_routing ]; then +- cp /etc/config/tailscale_policy_routing "$${state_pending}/tailscale_policy_routing" || exit 1 +-fi +-: >"$${state_pending}/.complete" || exit 1 +-mv "$${state_pending}" "$${state_dir}" || exit 1 +-exit 0 ++define Package/luci-app-tailscale/conffiles ++/etc/config/tailscale ++/etc/config/tailscale_openclash ++/etc/config/tailscale_policy_routing + endef + + define Package/luci-app-tailscale/prerm + #!/bin/sh +-state_dir=/etc/.luci-app-tailscale-upgrade +- +-case "$${2:-}" in +- remove|[0-9]*) ;; +- *) +- # default_prerm sources this script for opkg, while OpenWrt 24.10 +- # apk runs pre-deinstall directly with the old package version in $1. +- case "$${1:-}" in +- [0-9]*) ;; +- *) exit 0 ;; +- esac +- ;; +-esac ++[ -n "$${IPKG_INSTROOT}" ] && exit 0 + +-if [ -z "$${IPKG_INSTROOT}" ] && [ -x /usr/sbin/tailscale_policy_routing ]; then +- /usr/sbin/tailscale_policy_routing cleanup >/dev/null 2>&1 || exit 1 ++if [ -x /usr/sbin/tailscale_policy_routing ]; then ++ /usr/sbin/tailscale_policy_routing cleanup >/dev/null 2>&1 || true fi +-if [ -z "$${IPKG_INSTROOT}" ] && [ -x /etc/init.d/tailscale-policy-routing ]; then +- /etc/init.d/tailscale-policy-routing disable >/dev/null 2>&1 || exit 1 + - if [ -f /etc/config/tailscale_policy_routing ]; then - cp /etc/config/tailscale_policy_routing "$${state_pending}/tailscale_policy_routing" || exit 1 ++if [ -x /etc/init.d/tailscale-policy-routing ]; then ++ /etc/init.d/tailscale-policy-routing stop >/dev/null 2>&1 || true ++ /etc/init.d/tailscale-policy-routing disable >/dev/null 2>&1 || true fi +-if [ -z "$${IPKG_INSTROOT}" ] && [ -x /usr/sbin/tailscale_openclash_bypass ]; then + - : >"$${state_pending}/.complete" || exit 1 - mv "$${state_pending}" "$${state_dir}" || exit 1 ++if [ -x /usr/sbin/tailscale_openclash_bypass ]; then + /usr/sbin/tailscale_openclash_bypass cleanup >/dev/null 2>&1 || true + fi +-if [ -z "$${IPKG_INSTROOT}" ] && [ -x /etc/init.d/tailscale-openclash-bypass ]; then ++ ++if [ -x /etc/init.d/tailscale-openclash-bypass ]; then ++ /etc/init.d/tailscale-openclash-bypass stop >/dev/null 2>&1 || true + /etc/init.d/tailscale-openclash-bypass disable >/dev/null 2>&1 || true + fi +-if [ -z "$${IPKG_INSTROOT}" ] && [ -x /etc/init.d/tailscale ]; then +- /etc/init.d/tailscale stop >/dev/null 2>&1 || exit 1 ++ ++if [ -x /etc/init.d/tailscale ]; then ++ /etc/init.d/tailscale stop >/dev/null 2>&1 || true + fi +-for cleanup_dir in "$${state_dir}" "$${state_dir}.pending"; do +- rm -f "$${cleanup_dir}/tailscale" "$${cleanup_dir}/tailscale_openclash" \ +- "$${cleanup_dir}/tailscale_openclash.absent" "$${cleanup_dir}/tailscale_policy_routing" \ +- "$${cleanup_dir}/.complete" +- rmdir "$${cleanup_dir}" 2>/dev/null || true +-done + exit 0 endef @@ -43,36 +131,97 @@ --- a/luci-app-tailscale/root/etc/uci-defaults/40_luci-tailscale +++ b/luci-app-tailscale/root/etc/uci-defaults/40_luci-tailscale -@@ -12,7 +12,7 @@ LUCI_INDEX_CACHE="${LUCI_INDEX_CACHE:-/tmp/luci-indexcache}" +@@ -1,86 +1,30 @@ + #!/bin/sh - cleanup_upgrade_state() { - rm -f "$UPGRADE_STATE_DIR/tailscale" "$UPGRADE_STATE_DIR/tailscale_openclash" \ +-UPGRADE_STATE_DIR="${UPGRADE_STATE_DIR:-/etc/.luci-app-tailscale-upgrade}" + TAILSCALE_SECRETS_BIN="${TAILSCALE_SECRETS_BIN:-/usr/sbin/tailscale_secrets}" + UCI_BIN="${UCI_BIN:-uci}" + OPENCLASH_BYPASS_INIT="${OPENCLASH_BYPASS_INIT:-/etc/init.d/tailscale-openclash-bypass}" + POLICY_ROUTING_INIT="${POLICY_ROUTING_INIT:-/etc/init.d/tailscale-policy-routing}" +-LEGACY_ADGUARD_DNS_INIT="${LEGACY_ADGUARD_DNS_INIT:-/etc/init.d/tailscale-adguard-dns}" +-LEGACY_ADGUARD_DNS_RC_DIR="${LEGACY_ADGUARD_DNS_RC_DIR:-/etc/rc.d}" +-LEGACY_ADGUARD_DNS_BACKUP_DIR="${LEGACY_ADGUARD_DNS_BACKUP_DIR:-/etc/tailscale/luci-app-tailscale-legacy}" + LUCI_INDEX_CACHE="${LUCI_INDEX_CACHE:-/tmp/luci-indexcache}" + +-cleanup_upgrade_state() { +- rm -f "$UPGRADE_STATE_DIR/tailscale" "$UPGRADE_STATE_DIR/tailscale_openclash" \ - "$UPGRADE_STATE_DIR/tailscale_openclash.absent" "$UPGRADE_STATE_DIR/tailscale_policy_routing" \ -+ "$UPGRADE_STATE_DIR/tailscale_policy_routing" \ - "$UPGRADE_STATE_DIR/.complete" - rmdir "$UPGRADE_STATE_DIR" 2>/dev/null || true - } -@@ -47,20 +48,18 @@ cleanup_legacy_adguard_dns_service() { - fi - - cp -p "$LEGACY_ADGUARD_DNS_INIT" "$backup_dir/init" || return 1 -+ - for link in "$LEGACY_ADGUARD_DNS_RC_DIR"/*tailscale-adguard-dns; do - [ -e "$link" ] || [ -L "$link" ] || continue - rm -f "$link" || return 1 - done -+ - mv "$LEGACY_ADGUARD_DNS_INIT" "$backup_dir/tailscale-adguard-dns.disabled" || return 1 - } - - if [ -f "$UPGRADE_STATE_DIR/.complete" ]; then - restore_upgrade_config "$UPGRADE_STATE_DIR/tailscale" /etc/config/tailscale || exit 1 +- "$UPGRADE_STATE_DIR/.complete" +- rmdir "$UPGRADE_STATE_DIR" 2>/dev/null || true +-} +- +-restore_upgrade_config() { +- local source_file="$1" target_file="$2" temporary_file +- +- [ -f "$source_file" ] || return 0 +- temporary_file="$target_file.luci-app-tailscale-upgrade.$$" +- cp "$source_file" "$temporary_file" || return 1 +- mv "$temporary_file" "$target_file" || { +- rm -f "$temporary_file" +- return 1 +- } +-} +- +-cleanup_legacy_adguard_dns_service() { +- local backup_dir link +- +- [ -e "$LEGACY_ADGUARD_DNS_INIT" ] || return 0 +- backup_dir="$LEGACY_ADGUARD_DNS_BACKUP_DIR/tailscale-adguard-dns.$(date +%Y%m%d%H%M%S).$$" +- mkdir -p "$backup_dir" || return 1 +- +- for link in "$LEGACY_ADGUARD_DNS_RC_DIR"/*tailscale-adguard-dns; do +- [ -e "$link" ] || [ -L "$link" ] || continue +- printf '%s\t%s\n' "${link##*/}" "$(readlink "$link" 2>/dev/null || true)" >>"$backup_dir/rc-links" +- done +- +- if [ -x "$LEGACY_ADGUARD_DNS_INIT" ]; then +- "$LEGACY_ADGUARD_DNS_INIT" stop || return 1 +- "$LEGACY_ADGUARD_DNS_INIT" disable || true +- fi +- +- cp -p "$LEGACY_ADGUARD_DNS_INIT" "$backup_dir/init" || return 1 +- for link in "$LEGACY_ADGUARD_DNS_RC_DIR"/*tailscale-adguard-dns; do +- [ -e "$link" ] || [ -L "$link" ] || continue +- rm -f "$link" || return 1 +- done +- mv "$LEGACY_ADGUARD_DNS_INIT" "$backup_dir/tailscale-adguard-dns.disabled" || return 1 +-} +- +-if [ -f "$UPGRADE_STATE_DIR/.complete" ]; then +- restore_upgrade_config "$UPGRADE_STATE_DIR/tailscale" /etc/config/tailscale || exit 1 - if [ -f "$UPGRADE_STATE_DIR/tailscale_openclash.absent" ]; then - rm -f /etc/config/tailscale_openclash - else - restore_upgrade_config "$UPGRADE_STATE_DIR/tailscale_openclash" /etc/config/tailscale_openclash || exit 1 - fi -+ restore_upgrade_config "$UPGRADE_STATE_DIR/tailscale_openclash" /etc/config/tailscale_openclash || exit 1 - restore_upgrade_config "$UPGRADE_STATE_DIR/tailscale_policy_routing" /etc/config/tailscale_policy_routing || exit 1 - cleanup_upgrade_state - elif [ -d "$UPGRADE_STATE_DIR" ]; then +- restore_upgrade_config "$UPGRADE_STATE_DIR/tailscale_policy_routing" /etc/config/tailscale_policy_routing || exit 1 +- cleanup_upgrade_state +-elif [ -d "$UPGRADE_STATE_DIR" ]; then +- cleanup_upgrade_state ++# 初始化密钥存储 ++if [ -x "$TAILSCALE_SECRETS_BIN" ]; then ++ "$TAILSCALE_SECRETS_BIN" migrate || exit 1 + fi + +-cleanup_legacy_adguard_dns_service || exit 1 +- +-"$TAILSCALE_SECRETS_BIN" migrate || exit 1 +- ++# 根据配置启用 OpenClash 旁路分流服务 + openclash_bypass_enabled="$("$UCI_BIN" -q get tailscale_openclash.settings.enabled 2>/dev/null || true)" + if [ "$openclash_bypass_enabled" = '1' ] && [ -x "$OPENCLASH_BYPASS_INIT" ]; then + "$OPENCLASH_BYPASS_INIT" enable + "$OPENCLASH_BYPASS_INIT" start + fi + ++# 启用策略路由服务 + if [ -x "$POLICY_ROUTING_INIT" ]; then + "$POLICY_ROUTING_INIT" enable + "$POLICY_ROUTING_INIT" start + fi + ++# 刷新 LuCI 缓存使菜单立即生效 + rm -f "$LUCI_INDEX_CACHE" ++ + exit 0