Files
tsparams/tsparams.py
2026-03-08 11:36:22 +01:00

90 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (C) 2026 Bryan Joshua Pedini - gpl-3-or-later
import subprocess
import json
import sys
def get_tailscale_prefs():
"""
Executes 'tailscale debug prefs' and returns the parsed JSON output.
"""
try:
# Run the command and capture stdout
result = subprocess.run(
["tailscale", "debug", "prefs"],
capture_output=True,
text=True,
check=True
)
return json.loads(result.stdout)
except FileNotFoundError:
print("Error: 'tailscale' command not found. Please ensure Tailscale is installed.", file=sys.stderr)
sys.exit(1)
except subprocess.CalledProcessError as e:
print(f"Error running 'tailscale debug prefs': {e.stderr}", file=sys.stderr)
sys.exit(1)
except json.JSONDecodeError as e:
print(f"Error parsing JSON output: {e}", file=sys.stderr)
sys.exit(1)
def process_advertise_routes(routes_array, append_func):
"""
Processes the AdvertiseRoutes array according to the specific logic:
- Separates exit node routes (0.0.0.0/0, ::/0) from standard routes.
- Appends '--advertise-exit-node' if exit node routes are found.
- Appends '--advertise-routes=' with a comma-separated list of standard routes.
"""
exit_node_routes = {"0.0.0.0/0", "::/0"}
has_exit_node = False
standard_routes = []
if routes_array:
for route in routes_array:
if route in exit_node_routes:
has_exit_node = True
else:
standard_routes.append(route)
# If exit node routes are present, append the specific flag
if has_exit_node:
append_func("--advertise-exit-node")
# If standard routes are present, append them as a comma-separated list
if standard_routes:
routes_str = ",".join(standard_routes)
append_func(f"--advertise-routes={routes_str}")
def main():
# 1. Get the JSON data from the command
prefs = get_tailscale_prefs()
# Initialize the main string list
cmd_parts = ["tailscale up"]
# Helper function to append to the main string list
def append_to_cmd(string_part):
cmd_parts.append(string_part)
# 2. Process RouteAll
# Default is false, so we only append if it is true
if prefs.get("RouteAll", False):
append_to_cmd("--accept-routes")
# 3. Process CorpDNS
# Default is true, so we only append if it is false (to set --accept-dns=false)
if not prefs.get("CorpDNS", True):
append_to_cmd("--accept-dns=false")
# 4. Process AdvertiseRoutes
# We use the dedicated function for the array logic
routes = prefs.get("AdvertiseRoutes")
if routes:
process_advertise_routes(routes, append_to_cmd)
# Output the resulting string
print(" ".join(cmd_parts))
if __name__ == "__main__":
main()