mirror of
https://github.com/openwrt/luci.git
synced 2026-05-31 10:31:55 +08:00
b1a20c42bd
add switch DNSMode add fw now donot duplicate fw remove WAN-> TAILSCALE FORWARD CHAIN Signed-off-by: tokisaki galaxy <moebest@outlook.jp>
230 lines
6.2 KiB
Bash
Executable File
230 lines
6.2 KiB
Bash
Executable File
#!/bin/sh /etc/rc.common
|
|
|
|
USE_PROCD=1
|
|
START=99
|
|
STOP=10
|
|
|
|
NAME=tailscale-settings
|
|
|
|
# Compare version strings: return 0 (true) if $1 >= $2
|
|
version_gte() {
|
|
awk -v a="${1%%-*}" -v b="${2%%-*}" 'BEGIN {
|
|
split(a, av, ".")
|
|
split(b, bv, ".")
|
|
for (i=1; i<=3; i++) {
|
|
ai = int(av[i]+0); bi = int(bv[i]+0)
|
|
if (ai > bi) { exit 0 }
|
|
if (ai < bi) { exit 1 }
|
|
}
|
|
exit 0
|
|
}'
|
|
return $?
|
|
}
|
|
|
|
# Add/remove DNS forward entry in dnsmasq for MagicDNS via OpenWrt
|
|
setup_tailscale_dns_forward() {
|
|
if [ ! -x /usr/sbin/tailscale ] && [ ! -x /usr/bin/tailscale ]; then
|
|
return 0
|
|
fi
|
|
|
|
local entry="/.ts.net/100.100.100.100"
|
|
local found=0
|
|
|
|
# Check if entry already exists in dnsmasq
|
|
if uci -q show dhcp.@dnsmasq[0].server 2>/dev/null | grep -Fqx "dhcp.@dnsmasq[0].server='$entry'"; then
|
|
found=1
|
|
fi
|
|
|
|
if [ "$found" = "0" ]; then
|
|
uci add_list dhcp.@dnsmasq[0].server="$entry"
|
|
uci commit dhcp
|
|
/etc/init.d/dnsmasq reload 2>/dev/null || /etc/init.d/dnsmasq restart 2>/dev/null
|
|
logger -t "$NAME" "Added DNS forward: $entry"
|
|
fi
|
|
}
|
|
|
|
remove_tailscale_dns_forward() {
|
|
local entry="/.ts.net/100.100.100.100"
|
|
local idx=0
|
|
local removed=0
|
|
while true; do
|
|
local val
|
|
val=$(uci -q get dhcp.@dnsmasq[0].server."${idx}" 2>/dev/null)
|
|
[ -z "$val" ] && break
|
|
if [ "$val" = "$entry" ]; then
|
|
uci -q del_list dhcp.@dnsmasq[0].server="$entry"
|
|
removed=1
|
|
break
|
|
fi
|
|
idx=$((idx + 1))
|
|
done
|
|
|
|
if [ "$removed" = "1" ]; then
|
|
uci commit dhcp
|
|
/etc/init.d/dnsmasq reload 2>/dev/null || /etc/init.d/dnsmasq restart 2>/dev/null
|
|
logger -t "$NAME" "Removed Tailscale DNS forward entry: $entry"
|
|
fi
|
|
}
|
|
|
|
apply_settings() {
|
|
local ts_bin
|
|
if [ -x /usr/sbin/tailscale ]; then
|
|
ts_bin=/usr/sbin/tailscale
|
|
elif [ -x /usr/bin/tailscale ]; then
|
|
ts_bin=/usr/bin/tailscale
|
|
else
|
|
logger -t "$NAME" "tailscale binary not found, skipping settings apply"
|
|
return 0
|
|
fi
|
|
|
|
config_load tailscale
|
|
|
|
local accept_routes advertise_exit_node exit_node exit_node_allow_lan_access
|
|
local ssh shields_up runwebclient nosnat hostname
|
|
local enable_relay relay_server_port
|
|
|
|
config_get accept_routes settings accept_routes '0'
|
|
config_get advertise_exit_node settings advertise_exit_node '0'
|
|
config_get exit_node settings exit_node ''
|
|
config_get exit_node_allow_lan_access settings exit_node_allow_lan_access '0'
|
|
config_get ssh settings ssh '0'
|
|
config_get dns_mode settings dns_mode 'disabled'
|
|
config_get shields_up settings shields_up '0'
|
|
config_get runwebclient settings runwebclient '0'
|
|
config_get nosnat settings nosnat '0'
|
|
config_get hostname settings hostname ''
|
|
config_get enable_relay settings enable_relay '0'
|
|
config_get relay_server_port settings relay_server_port '40000'
|
|
|
|
# Collect advertise_routes UCI list into comma-separated string
|
|
local routes=""
|
|
append_route() {
|
|
if [ -z "$routes" ]; then
|
|
routes="$1"
|
|
else
|
|
routes="$routes,$1"
|
|
fi
|
|
}
|
|
config_list_foreach settings advertise_routes append_route
|
|
|
|
# Build argument list for 'tailscale set'
|
|
set -- set
|
|
|
|
# --accept-routes
|
|
[ "$accept_routes" = "1" ] \
|
|
&& set -- "$@" --accept-routes=true \
|
|
|| set -- "$@" --accept-routes=false
|
|
|
|
# --advertise-exit-node (only when no exit node is selected)
|
|
if [ "$advertise_exit_node" = "1" ] && [ -z "$exit_node" ]; then
|
|
set -- "$@" --advertise-exit-node=true
|
|
else
|
|
set -- "$@" --advertise-exit-node=false
|
|
fi
|
|
|
|
# --exit-node-allow-lan-access (only when no exit node is selected)
|
|
if [ -z "$exit_node" ]; then
|
|
[ "$exit_node_allow_lan_access" = "1" ] \
|
|
&& set -- "$@" --exit-node-allow-lan-access=true \
|
|
|| set -- "$@" --exit-node-allow-lan-access=false
|
|
fi
|
|
|
|
# --ssh
|
|
[ "$ssh" = "1" ] \
|
|
&& set -- "$@" --ssh=true \
|
|
|| set -- "$@" --ssh=false
|
|
|
|
# --accept-dns based on dns_mode
|
|
case "$dns_mode" in
|
|
magicdns)
|
|
set -- "$@" --accept-dns=true
|
|
remove_tailscale_dns_forward
|
|
;;
|
|
openwrt_forward)
|
|
set -- "$@" --accept-dns=false
|
|
setup_tailscale_dns_forward
|
|
;;
|
|
*)
|
|
# disabled (default)
|
|
set -- "$@" --accept-dns=false
|
|
remove_tailscale_dns_forward
|
|
;;
|
|
esac
|
|
|
|
# --shields-up
|
|
[ "$shields_up" = "1" ] \
|
|
&& set -- "$@" --shields-up=true \
|
|
|| set -- "$@" --shields-up=false
|
|
|
|
# --webclient
|
|
[ "$runwebclient" = "1" ] \
|
|
&& set -- "$@" --webclient=true \
|
|
|| set -- "$@" --webclient=false
|
|
|
|
# --snat-subnet-routes (inverse of nosnat)
|
|
[ "$nosnat" = "1" ] \
|
|
&& set -- "$@" --snat-subnet-routes=false \
|
|
|| set -- "$@" --snat-subnet-routes=true
|
|
|
|
# --advertise-routes (comma-separated, empty clears routes)
|
|
set -- "$@" "--advertise-routes=$routes"
|
|
|
|
# --exit-node (empty clears the exit node)
|
|
set -- "$@" "--exit-node=$exit_node"
|
|
|
|
# when an exit node is configured, always allow LAN access
|
|
[ -n "$exit_node" ] && set -- "$@" --exit-node-allow-lan-access=true
|
|
|
|
# --hostname (only set if non-empty)
|
|
[ -n "$hostname" ] && set -- "$@" "--hostname=$hostname"
|
|
|
|
# --relay-server-port (requires tailscale >= 1.90.5)
|
|
local ts_ver
|
|
ts_ver=$("$ts_bin" version 2>/dev/null | head -n1)
|
|
if version_gte "$ts_ver" "1.90.5"; then
|
|
if [ "$enable_relay" = "1" ]; then
|
|
set -- "$@" "--relay-server-port=${relay_server_port:-40000}"
|
|
else
|
|
set -- "$@" "--relay-server-port="
|
|
fi
|
|
fi
|
|
|
|
logger -t "$NAME" "Applying settings"
|
|
"$ts_bin" "$@"
|
|
local ret=$?
|
|
[ $ret -eq 0 ] \
|
|
&& logger -t "$NAME" "Settings applied successfully" \
|
|
|| logger -t "$NAME" "Failed to apply settings (exit code: $ret)"
|
|
return $ret
|
|
}
|
|
|
|
handle_service_state() {
|
|
config_load tailscale
|
|
local service_enabled
|
|
config_get service_enabled settings service_enabled '1'
|
|
|
|
if [ "$service_enabled" = "0" ]; then
|
|
logger -t "$NAME" "Service is disabled, stopping tailscale"
|
|
/etc/init.d/tailscale stop 2>/dev/null
|
|
/etc/init.d/tailscale disable 2>/dev/null
|
|
killall tailscaled 2>/dev/null
|
|
else
|
|
logger -t "$NAME" "Service is enabled, ensuring tailscale is running"
|
|
/etc/init.d/tailscale enable 2>/dev/null
|
|
/etc/init.d/tailscale start 2>/dev/null
|
|
apply_settings
|
|
fi
|
|
}
|
|
|
|
start_service() {
|
|
apply_settings
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_trigger "tailscale"
|
|
}
|
|
|
|
reload_service() {
|
|
handle_service_state
|
|
}
|