From 031a5f5881e6f956b44fe4ae7d77af0d991b7b20 Mon Sep 17 00:00:00 2001 From: jrroca Date: Fri, 19 Jul 2024 17:23:34 +0200 Subject: [PATCH 1/2] Reorder to aovid compilation on every change --- app/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Dockerfile b/app/Dockerfile index 77b0776..f77d975 100644 --- a/app/Dockerfile +++ b/app/Dockerfile @@ -1,6 +1,7 @@ FROM python:3.8 WORKDIR /app -ADD . /app +ADD requirements.txt /app RUN pip install --upgrade pip RUN pip install -r requirements.txt +ADD . /app CMD ["python", "app.py"] \ No newline at end of file From 601695380a3410c0aa4166895889319db69f1afe Mon Sep 17 00:00:00 2001 From: jrroca Date: Fri, 19 Jul 2024 17:46:48 +0200 Subject: [PATCH 2/2] Allow wildcard DNS entryies and allow not registering IpV6 address. --- app/app.py | 4 ++-- app/cloudflare.py | 2 +- app/config.py | 2 +- app/headscale.py | 13 +++++++++---- app/tailscale.py | 7 ++++++- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/app/app.py b/app/app.py index 80dcde1..d4caa57 100644 --- a/app/app.py +++ b/app/app.py @@ -17,10 +17,10 @@ def main(): # Get records depeneding on mode if config['mode'] == "tailscale": - ts_records = getTailscaleDevice(config['ts-key'], config['ts-client-id'], config['ts-client-secret'], config['ts-tailnet']) + ts_records = getTailscaleDevice(config['ts-key'], config['ts-client-id'], config['ts-client-secret'], config['ts-tailnet'], config['ignore-ipv6'], config['wildcardhost']) if config['mode'] == "headscale": from headscale import getHeadscaleDevice - ts_records = getHeadscaleDevice(config['hs-apikey'], config['hs-baseurl']) + ts_records = getHeadscaleDevice(config['hs-apikey'], config['hs-baseurl'], config['ignore-ipv6'], config['wildcardhost']) records_typemap = { 4: 'A', diff --git a/app/cloudflare.py b/app/cloudflare.py index 7b6e6fd..b4fa20a 100644 --- a/app/cloudflare.py +++ b/app/cloudflare.py @@ -87,7 +87,7 @@ def deleteDNSRecord(token, domain, id, zoneId=False): print("--> [CLOUDFLARE] [{code}] {msg}".format(code=response.status_code, msg=colored('record deleted', "green"))) def isValidDNSRecord(name): - regex = "^([a-zA-Z]|\d|-|\.)*$" + regex = "^(\*\.)?([a-zA-Z]|\d|-|\.)*$" return re.match(regex, name) diff --git a/app/config.py b/app/config.py index 26b01a8..da7338f 100644 --- a/app/config.py +++ b/app/config.py @@ -4,7 +4,7 @@ from termcolor import cprint keysToImport = ['cf-key', 'cf-domain', 'ts-tailnet'] -keysOptional = ['cf-sub', 'prefix', 'postfix', 'ts-key', 'ts-client-id', 'ts-client-secret', "mode", "hs-baseurl", "hs-apikey"] +keysOptional = ['cf-sub', 'prefix', 'postfix', 'ts-key', 'ts-client-id', 'ts-client-secret', "mode", "hs-baseurl", "hs-apikey", 'ignore-ipv6', 'wildcardhost'] def importkey(name, optional=False): key = name diff --git a/app/headscale.py b/app/headscale.py index ac057e9..080b0b4 100644 --- a/app/headscale.py +++ b/app/headscale.py @@ -1,9 +1,9 @@ -import requests, json +import requests, json, ipaddress from termcolor import colored from tailscale import alterHostname -def getHeadscaleDevice(apikey, baseurl): - url = "{baseurl}/api/v1/machine".format(baseurl=baseurl) +def getHeadscaleDevice(apikey, baseurl, ignoreipv6=False, wildcardhost=False): + url = "{baseurl}/api/v1/node".format(baseurl=baseurl) payload={} headers = { "Authorization": "Bearer {apikey}".format(apikey=apikey) @@ -15,10 +15,15 @@ def getHeadscaleDevice(apikey, baseurl): data = json.loads(response.text) if (response.status_code == 200): output = [] - for device in data['machines']: + for device in data['nodes']: for address in device['ipAddresses']: if not device['givenName'].lower().startswith('localhost'): + ip = ipaddress.ip_address(address) + if ip.version == 6 and ignoreipv6: + continue output.append({'hostname': alterHostname(device['givenName'].split('.')[0].lower()), 'address': address}) + if wildcardhost: + output.append({'hostname': "*.{host}".format(host=alterHostname(device['givenName'].split('.')[0].lower())), 'address': address}) return output else: exit(colored("getTailscaleDevice() - {status}, {error}".format(status=str(response.status_code), error=data['message']), "red")) diff --git a/app/tailscale.py b/app/tailscale.py index f34030f..ab11968 100644 --- a/app/tailscale.py +++ b/app/tailscale.py @@ -6,7 +6,7 @@ from termcolor import colored ### Get Data -def getTailscaleDevice(apikey, clientid, clientsecret, tailnet): +def getTailscaleDevice(apikey, clientid, clientsecret, tailnet, ignoreipv6=False, wildcardhost=False): if clientid and clientsecret: token = OAuth2Session(client=BackendApplicationClient(client_id=clientid)).fetch_token(token_url='https://api.tailscale.com/api/v2/oauth/token', client_id=clientid, client_secret=clientsecret) apikey = token["access_token"] @@ -28,7 +28,12 @@ def getTailscaleDevice(apikey, clientid, clientsecret, tailnet): for address in device['addresses']: output.append({'hostname': alterHostname(device['hostname']), 'address': address}) if device['name'].split('.')[0].lower() != device['hostname'].lower(): + ip = ipaddress.ip_address(address) + if ip.version == 6 and ignoreipv6: + continue output.append({'hostname': alterHostname(device['name'].split('.')[0].lower()), 'address': address}) + if wildcardhost: + output.append({'hostname': "*.{host}".format(host=alterHostname(device['name'].split('.')[0].lower())), 'address': address}) return output else: exit(colored("getTailscaleDevice() - {status}, {error}".format(status=str(response.status_code), error=data['message']), "red"))