255 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			255 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/sh /etc/rc.common
 | |
| 
 | |
| START=90
 | |
| 
 | |
| USE_PROCD=1
 | |
| 
 | |
| PROG=/usr/sbin/tailscale
 | |
| PROGD=/usr/sbin/tailscaled
 | |
| CONFIG_PATH=/var/lib/tailscale
 | |
| 
 | |
| service_triggers() {
 | |
| 	procd_add_reload_trigger "tailscale"
 | |
| 	procd_add_interface_trigger "interface.*.up" wan /etc/init.d/tailscale reload
 | |
| }
 | |
| 
 | |
| section_enabled() {
 | |
| 	config_get_bool enabled "$1" 'enabled' 0
 | |
| 	[ $enabled -gt 0 ]
 | |
| }
 | |
| 
 | |
| custom_instance() {
 | |
| 	local cfg="$1"
 | |
| 	local acceptRoutes hostname acceptDNS advertiseExitNode exitNode advertiseRoutes s2s subnetRoutes flags loginServer authkey std_out std_err
 | |
| 	local ARGS=" up --reset"
 | |
| 
 | |
| 	if ! section_enabled "$cfg"; then
 | |
| 		echo "disabled in config"
 | |
| 		return 1
 | |
| 	fi
 | |
| 
 | |
| 	config_get_bool acceptRoutes $cfg 'acceptRoutes'
 | |
| 	config_get hostname $cfg 'hostname'
 | |
| 	config_get_bool acceptDNS $cfg 'acceptDNS'
 | |
| 	config_get_bool advertiseExitNode $cfg 'advertiseExitNode'
 | |
| 	config_get exitNode $cfg 'exitNode'
 | |
| 	config_get advertiseRoutes $cfg 'advertiseRoutes'
 | |
| 	config_get_bool s2s $cfg 's2s'
 | |
| 	config_get flags $cfg 'flags'
 | |
| 	config_get loginServer $cfg 'loginServer'
 | |
| 	config_get authkey $cfg 'authkey'
 | |
| 	config_get_bool std_out $cfg 'log_stdout'
 | |
| 	config_get_bool std_err $cfg 'log_stderr'
 | |
| 
 | |
| 	[ "$acceptRoutes" = "1" ] && ARGS="$ARGS --accept-routes=true"
 | |
| 	[ -n "$hostname" ] && ARGS="$ARGS --hostname=$hostname"
 | |
| 	[ "$acceptDNS" = "0" ] && ARGS="$ARGS --accept-dns=false"
 | |
| 	[ "$advertiseExitNode" = "1" ] && ARGS="$ARGS --advertise-exit-node"
 | |
| 	[ -n "$exitNode" ] && ARGS="$ARGS --exit-node=$exitNode --exit-node-allow-lan-access=true"
 | |
| 	[ -n "$advertiseRoutes" ] && ARGS="$ARGS --advertise-routes=$(echo $advertiseRoutes | tr ' ' ',')"
 | |
| 	[ "$s2s" = "1" ] && ARGS="$ARGS --snat-subnet-routes=false"
 | |
| 	[ -n "$flags" ] && ARGS="$ARGS $flags"
 | |
| 	[ -n "$loginServer" ] && ARGS="$ARGS --login-server=$loginServer"
 | |
| 	[ -n "$authkey" ] && ARGS="$ARGS --authkey=$authkey"
 | |
| 
 | |
| 	procd_open_instance
 | |
| 	procd_set_param command $PROG $ARGS
 | |
| 	procd_set_param stdout "$std_out"
 | |
| 	procd_set_param stderr "$std_err"
 | |
| 	procd_close_instance
 | |
| 	(
 | |
| 		[ -f "/var/run/tailscale.wait.pid" ] && return
 | |
| 		touch /var/run/tailscale.wait.pid
 | |
| 		count=0
 | |
| 		while [ -z "$(ifconfig | grep 'tailscale' | awk '{print $1}')" ] || [ -z "$(tailscale ip -4)" ]
 | |
| 		do
 | |
| 			sleep 2
 | |
| 			let count++
 | |
| 			[ "${count}" -ge 5 ] && { rm /var/run/tailscale.wait.pid; exit 19; }
 | |
| 		done
 | |
| 
 | |
| 		if [ "$acceptDNS" = "1" ]; then
 | |
| 			MagicDNSSuffix=$(tailscale status --json | awk -F'"' '/"MagicDNSSuffix"/ {last=$(NF-1)} END {print last}')
 | |
| 			sed -i '/100.100.100.100/d' /etc/dnsmasq.conf
 | |
| 			echo "server=/$MagicDNSSuffix/100.100.100.100" >> /etc/dnsmasq.conf
 | |
| 			/etc/init.d/dnsmasq reload
 | |
| 		fi
 | |
| 
 | |
| 		ts0=$(ifconfig | grep 'tailscale' | awk '{print $1}')
 | |
| 		if [ -z "$(uci -q get network.tailscale)" ];  then				
 | |
| 			uci set network.tailscale='interface'
 | |
| 			if [ "$ts0" = *$'\n'* ]; then
 | |
| 				uci set network.ts_lan='device'
 | |
| 				uci set network.ts_lan.type='bridge'
 | |
| 				uci set network.ts_lan.name='ts-lan'
 | |
| 				for port in "${ts0}"; do
 | |
| 					uci add_list network.ts_lan.ports=$port
 | |
| 				done
 | |
| 				uci set network.tailscale.proto='none'
 | |
| 				uci set network.tailscale.device='ts-lan'
 | |
| 			else
 | |
| 				ts_ip=$(tailscale ip -4)
 | |
| 				uci set network.tailscale.proto='static'
 | |
| 				uci set network.tailscale.ipaddr=$ts_ip
 | |
| 				uci set network.tailscale.netmask='255.0.0.0'
 | |
| 				uci set network.tailscale.device=$ts0
 | |
| 			fi
 | |
| 		fi
 | |
| 
 | |
| 		lan2wan=$(uci show firewall | grep "firewall.@forwarding\[[0-9]\+\]\.src='lan'" -B 1 -A 1 | grep "firewall.@forwarding\[[0-9]\+\]\.dest='wan'" | grep -o '[0-9]\+')
 | |
| 		if [ -n "$exitNode" ];  then
 | |
| 			uci set firewall.@defaults[0].forward='REJECT'
 | |
| 			[ -n $lan2wan ] && uci set firewall.@forwarding[$lan2wan].enabled='0'
 | |
| 		else
 | |
| 			uci -q delete firewall.@forwarding[$lan2wan].enabled
 | |
| 		fi
 | |
| 
 | |
| 		config_get subnetRoutes $cfg 'subnetRoutes'
 | |
| 		if [ -n "$subnetRoutes" ];  then
 | |
| 			i=1
 | |
| 			ts_ip=$(tailscale ip -4)
 | |
| 			for route in $subnetRoutes; do
 | |
| 				uci set network.ts_subnet$i='route'
 | |
| 				uci set network.ts_subnet$i.interface='tailscale'
 | |
| 				uci set network.ts_subnet$i.target=$route
 | |
| 				uci set network.ts_subnet$i.gateway=$ts_ip
 | |
| 				let i++
 | |
| 			done
 | |
| 		else
 | |
| 			for route in $(uci show network | grep 'network.ts_subnet[0-9]\+=route' | grep -o 'network.ts_subnet[0-9]\+'); do
 | |
| 				uci -q delete $route
 | |
| 			done
 | |
| 		fi
 | |
| 
 | |
| 		config_get access $cfg 'access'
 | |
| 		if [ -n "$access" ];  then
 | |
| 			if [ -z "$(uci -q get firewall.tszone)" ];  then
 | |
| 				uci set firewall.tszone='zone'
 | |
| 				uci set firewall.tszone.input='ACCEPT'
 | |
| 				uci set firewall.tszone.output='ACCEPT'
 | |
| 				uci set firewall.tszone.forward='ACCEPT'
 | |
| 				uci set firewall.tszone.masq='1'
 | |
| 				uci set firewall.tszone.mtu_fix='1'
 | |
| 				uci set firewall.tszone.name='tailscale'
 | |
| 				uci set firewall.tszone.network='tailscale'
 | |
| 			fi
 | |
| 		else
 | |
| 			uci -q delete firewall.tszone
 | |
| 		fi
 | |
| 		if [ "${access//tsfwlan/}" != "$access" ]; then
 | |
| 			uci set firewall.tsfwlan=forwarding
 | |
| 			uci set firewall.tsfwlan.dest='lan'
 | |
| 			uci set firewall.tsfwlan.src='tailscale'
 | |
| 		else
 | |
| 			uci -q delete firewall.tsfwlan
 | |
| 		fi
 | |
| 		if [ "${access//tsfwwan/}" != "$access" ]; then
 | |
| 			uci set firewall.tsfwwan=forwarding
 | |
| 			uci set firewall.tsfwwan.dest='wan'
 | |
| 			uci set firewall.tsfwwan.src='tailscale'
 | |
| 		else
 | |
| 			uci -q delete firewall.tsfwwan
 | |
| 		fi
 | |
| 		if [ "${access//lanfwts/}" != "$access" ]; then
 | |
| 			uci set firewall.lanfwts=forwarding
 | |
| 			uci set firewall.lanfwts.dest='tailscale'
 | |
| 			uci set firewall.lanfwts.src='lan'
 | |
| 		else
 | |
| 			uci -q delete firewall.lanfwts
 | |
| 		fi
 | |
| 		if [ "${access//wanfwts/}" != "$access" ]; then
 | |
| 			uci set firewall.wanfwts=forwarding
 | |
| 			uci set firewall.wanfwts.dest='tailscale'
 | |
| 			uci set firewall.wanfwts.src='wan'
 | |
| 		else
 | |
| 			uci -q delete firewall.wanfwts
 | |
| 		fi
 | |
| 
 | |
| 		[ -n "$(uci changes network)" ] && uci commit network && /etc/init.d/network reload
 | |
| 		[ -n "$(uci changes firewall)" ] && uci commit firewall && /etc/init.d/firewall reload
 | |
| 		rm /var/run/tailscale.wait.pid
 | |
| 	) &
 | |
| }
 | |
| 
 | |
| start_instance() {
 | |
| 	local cfg="$1"
 | |
| 	local port config_path fw_mode std_out std_err state_file
 | |
| 	local ARGS=""
 | |
| 
 | |
| 	if ! section_enabled "$cfg"; then
 | |
| 		echo "disabled in config"
 | |
| 		return 1
 | |
| 	fi
 | |
| 
 | |
| 	config_get port $cfg 'port'
 | |
| 	config_get config_path $cfg 'config_path'
 | |
| 	config_get fw_mode $cfg 'fw_mode'
 | |
| 	config_get_bool std_out $cfg 'log_stdout'
 | |
| 	config_get_bool std_err $cfg 'log_stderr'
 | |
| 
 | |
| 	[ -d $config_path ] || mkdir -p $config_path
 | |
| 	[ -d $CONFIG_PATH ] || mkdir -p $CONFIG_PATH
 | |
| 	state_file=$config_path/tailscaled.state
 | |
| 	
 | |
| 	/usr/sbin/tailscaled --cleanup
 | |
| 
 | |
| 	[ -n "$port" ] && ARGS="$ARGS --port $port"
 | |
| 	[ -n "$state_file" ] && ARGS="$ARGS --state $state_file"
 | |
| 
 | |
| 	procd_open_instance
 | |
| 	procd_set_param command $PROGD $ARGS
 | |
| 
 | |
| 	procd_set_param env TS_DEBUG_FIREWALL_MODE="$fw_mode"
 | |
|  	
 | |
| 	procd_set_param respawn
 | |
| 	procd_set_param stdout "$std_out"
 | |
| 	procd_set_param stderr "$std_err"
 | |
| 	procd_close_instance
 | |
| }
 | |
| 
 | |
| start_service() {
 | |
| 	config_load 'tailscale'
 | |
| 	config_foreach start_instance 'tailscale'
 | |
| 	config_foreach custom_instance 'tailscale'
 | |
| }
 | |
| 
 | |
| stop_instance() {
 | |
| 	local cfg="$1"
 | |
| 	/usr/sbin/tailscaled --cleanup
 | |
| 
 | |
| 	# Remove dnsmasq settings
 | |
| 	sed -i '/100.100.100.100/d' /etc/dnsmasq.conf
 | |
| 	/etc/init.d/dnsmasq reload
 | |
| 	
 | |
| 	# Remove network settings
 | |
| 	uci -q delete network.tailscale
 | |
| 	uci -q delete network.ts_lan
 | |
| 	for route in $(uci show network | grep 'network.ts_subnet[0-9]\+=route' | grep -o 'network.ts_subnet[0-9]\+'); do
 | |
| 		uci -q delete $route
 | |
| 	done
 | |
| 	
 | |
| 	# Remove firewall settings
 | |
| 	lan2wan=$(uci show firewall | grep "firewall.@forwarding\[[0-9]\+\]\.src='lan'" -B 1 -A 1 | grep "firewall.@forwarding\[[0-9]\+\]\.dest='wan'" | grep -o '[0-9]\+')
 | |
| 	uci -q delete firewall.@forwarding[$lan2wan].enabled
 | |
| 	uci -q delete firewall.tszone
 | |
| 	uci -q delete firewall.tsfwlan
 | |
| 	uci -q delete firewall.tsfwwan
 | |
| 	uci -q delete firewall.lanfwts
 | |
| 	uci -q delete firewall.wanfwts
 | |
| 	[ -n "$(uci changes network)" ] && uci commit network && /etc/init.d/network reload
 | |
| 	[ -n "$(uci changes firewall)" ] && uci commit firewall && /etc/init.d/firewall reload
 | |
| 
 | |
| 	# Remove existing link or folder
 | |
| 	rm -rf $CONFIG_PATH
 | |
| }
 | |
| 
 | |
| stop_service() {
 | |
| 	config_load 'tailscale'
 | |
| 	config_foreach stop_instance 'tailscale'
 | |
| }
 | |
| 
 | |
| reload_service() {
 | |
| 	stop
 | |
| 	start
 | |
| }
 | 
