Find own ipv6 address and loop updates

This commit is contained in:
Michael Mandl 2020-05-24 19:18:39 +02:00
parent 67a5b82d9b
commit 4d78196461
4 changed files with 61 additions and 25 deletions

View file

@ -3,5 +3,9 @@ RUN pip install --no-cache-dir --upgrade pip
WORKDIR /app WORKDIR /app
COPY src/ ./ COPY src/ ./
RUN pip install --no-cache-dir --requirement requirements.txt
ARG APK_BUILD_DEPS=".build-deps gcc musl-dev linux-headers"
RUN apk add --no-cache --virtual $APK_BUILD_DEPS\
&& pip install --no-cache-dir --requirement requirements.txt \
&& apk del $APK_BUILD_DEPS
CMD [ "python", "ddns_update.py" ] CMD [ "python", "ddns_update.py" ]

View file

@ -5,4 +5,8 @@ services:
container_name: strato-ddns container_name: strato-ddns
build: build:
context: . context: .
network_mode: host
restart: always restart: always
environment:
- DDNS_HOST=my.host.name
- DDNS_KEY=secret

View file

@ -5,15 +5,54 @@ import requests
from requests.exceptions import RequestException from requests.exceptions import RequestException
import click import click
from os import environ from os import environ
from netifaces import interfaces, ifaddresses, AF_INET6
from ipaddress import ip_address
from time import sleep
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger("ddns updater") log = logging.getLogger("ddns updater")
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)
def response_successful(response_text): def response_successful(response_text):
return response_text.startswith("good") or response_text.startswith("nochg") return response_text.startswith("good") or response_text.startswith("nochg")
def ddns_update(host, key, ip):
url = f"https://dyndns.strato.com/nic/update?hostname={host}&myip={ip}"
try:
response = requests.get(url, auth=(host, key), timeout=3)
response.raise_for_status()
if not response_successful(response.text):
raise RequestException("update failed")
except RequestException as error:
log.debug(response.text.strip())
log.error(error)
return False
log.debug(response.text.strip())
log.info("update successful")
return True
@click.command() @click.command()
@click.option( @click.option(
"--host", "--host",
@ -27,30 +66,17 @@ def response_successful(response_text):
default=lambda: environ.get("DDNS_KEY", None), default=lambda: environ.get("DDNS_KEY", None),
help="The ddns authorization key", help="The ddns authorization key",
) )
@click.option( def loop_ddns_update(host, key):
"--ip", last_ip = None
required=True, while True:
default=lambda: environ.get("DDNS_IP", None), current_ip = get_global_ipv6()
help="The hosts new ip address in ipv4 or ipv6 format", if current_ip != last_ip:
) if ddns_update(host, key, current_ip):
def ddns_update(host, key, ip): last_ip = current_ip
url = f"https://dyndns.strato.com/nic/update?hostname={host}&myip={ip}" else:
log.debug("skipped update, ip address unchanged")
try: sleep(5)
response = requests.get(url, auth=(host, key), timeout=3)
response.raise_for_status()
if not response_successful(response.text):
raise RequestException("update failed")
except RequestException as error:
log.debug(response.text.strip())
log.error(error)
return
log.debug(response.text.strip())
log.info("update successful")
if __name__ == "__main__": if __name__ == "__main__":
ddns_update() loop_ddns_update()

View file

@ -1,2 +1,4 @@
Click==7.0 Click==7.0
requests==2.23.0 requests==2.23.0
netifaces==0.10.9
ipaddress==1.0.23