strato-ddns/src/ddns_update.py

88 lines
2.2 KiB
Python
Raw Normal View History

2020-05-22 14:28:09 +00:00
#!/usr/bin/python3
import logging
2020-05-24 11:35:27 +00:00
import requests
from requests.exceptions import RequestException
import click
from os import environ
2020-05-24 17:18:39 +00:00
from netifaces import interfaces, ifaddresses, AF_INET6
from ipaddress import ip_address
from time import sleep
2020-05-22 14:28:09 +00:00
2020-06-11 08:44:36 +00:00
logging.basicConfig(level=logging.INFO, format="%(asctime)-15s - %(name)s %(levelname)-8s: %(message)s")
2020-05-22 14:28:09 +00:00
log = logging.getLogger("ddns updater")
2020-05-24 11:35:27 +00:00
2020-05-24 17:18:39 +00:00
def get_global_address(address_family):
for interface in interfaces():
if_addresses = ifaddresses(interface)
if address_family in if_addresses:
for address in if_addresses[address_family]:
addr = ip_address(address["addr"].split("%")[0])
if addr.is_global:
return addr
return None
def get_global_ipv6():
return get_global_address(AF_INET6)
2020-05-24 11:35:27 +00:00
def response_successful(response_text):
return response_text.startswith("good") or response_text.startswith("nochg")
def ddns_update(host, key, ip):
2020-06-11 10:46:30 +00:00
url = f"https://dyndns.strato.com/nic/update?hostname={host}&myip={ip}"
2020-05-24 11:35:27 +00:00
try:
response = requests.get(url, auth=(host, key), timeout=3)
except RequestException as error:
log.error(error)
return False
try:
2020-05-24 11:35:27 +00:00
response.raise_for_status()
if not response_successful(response.text):
raise RequestException("update failed")
except RequestException as error:
2020-05-24 17:55:15 +00:00
log.error(response.text.strip())
2020-05-24 11:35:27 +00:00
log.error(error)
2020-05-24 17:18:39 +00:00
return False
2020-05-24 11:35:27 +00:00
log.debug(response.text.strip())
log.info("update successful")
2020-05-24 17:18:39 +00:00
return True
@click.command()
@click.option(
"--host",
required=True,
default=lambda: environ.get("DDNS_HOST", None),
help="The dns name to update",
)
@click.option(
"--key",
required=True,
default=lambda: environ.get("DDNS_KEY", None),
help="The ddns authorization key",
)
def loop_ddns_update(host, key):
last_ip = None
while True:
current_ip = get_global_ipv6()
if current_ip != last_ip:
if ddns_update(host, key, current_ip):
last_ip = current_ip
else:
log.debug("skipped update, ip address unchanged")
2020-05-24 17:32:01 +00:00
sleep(30)
2020-05-24 17:18:39 +00:00
2020-05-24 11:35:27 +00:00
2020-05-22 14:28:09 +00:00
if __name__ == "__main__":
2020-05-24 17:18:39 +00:00
loop_ddns_update()