#! /usr/bin/env python3 # Most internet box support DynDNS... but not my Livebox ! # Well it's more complicated than that: only a (very) limited # number of DynDNS services are supported, and OVH is not among # them... After all, why would the biggest French internet provider # support the biggest French hosting service ? (╬ ಠ益ಠ) # # Anyway, this script poll the Livebox to retrieve it current IP address, # then (if it has changed) update the OVH DynDNS service accordingly. import urllib.request from pathlib import Path import re import json from base64 import b64encode BASEDIR = Path(__file__).parent # The last know IP is stored in this file, to avoid updating OVH DynDNS if the IP didn't change CURRENT_IP_FILE = BASEDIR / "current_ip.txt" TARGET_HOSTNAME = "" # Fill me ! OVH_DYNDNS_AUTH_USER = "" # Fill me ! OVH_DYNDNS_AUTH_PASSWORD = "" # Fill me ! LIVEBOX_API_ENDPOINT = "http://192.168.1.1/ws" current_ip = CURRENT_IP_FILE.read_text().strip() assert re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", current_ip) # 1) Retreive current IP from the Livebox req = urllib.request.Request( url=LIVEBOX_API_ENDPOINT, method="POST", headers={ "Content-Type": "application/x-sah-ws-1-call+json", }, data=b'{"service":"NMC","method":"getWANStatus","parameters":{}}' ) rep = urllib.request.urlopen(req) assert rep.status == 200 new_ip = json.loads(rep.read().decode("utf8"))['result']['data']['IPAddress'].strip() assert re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", new_ip) if new_ip == current_ip: print("IP didn't change, nothing to update") raise SystemExit(0) print(f"IP has changed: {current_ip} -> {new_ip}") # 2) Update OVH DynDNS with the new IP req = urllib.request.Request( url=f"https://www.ovh.com/nic/update?system=dyndns&hostname={TARGET_HOSTNAME}&myip={new_ip}", method="GET", headers={ "Authorization": "Basic {}".format(b64encode(f"{OVH_DYNDNS_AUTH_USER}:{OVH_DYNDNS_AUTH_PASSWORD}".encode("utf8")).decode()), }, ) rep = urllib.request.urlopen(req) assert rep.status == 200 rep_status = rep.read().decode("utf8") if rep_status.startswith("nochg"): print("OVH DynDNS updated, but already using this IP !") elif rep_status.startswith("good"): print("OVH DynDNS updated !") else: raise SystemExit("OVH DynDNS rejected the IP update: {}".format(rep_status)) # 3) Finally update the current IP file CURRENT_IP_FILE.write_text(new_ip)