-
-
Save andybarilla/b0dd93e71ff18303c059 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
"""hover.py: Provides dynamic DNS functionality for Hover.com using their unofficial API. | |
This script is based off one by Dan Krause: https://gist.github.com/dankrause/5585907""" | |
__author__ = "Andrew Barilla" | |
__credits__ = ["Andrew Barilla", "Dan Krause"] | |
__license__ = "GPL" | |
__version__ = "1.0" | |
__maintainer__ = "Andrew Barilla" | |
__email__ = "[email protected]" | |
__status__ = "Production" | |
import requests | |
import json | |
# Your hover.com username and password | |
username = "username" | |
password = "password" | |
# Sign into hover.com and then go to: https://www.hover.com/api/domains/YOURDOMAIN.COM/dns | |
# Look for the subdomain record that you want to update and put its id here. | |
dns_id = "dns0000000" | |
class HoverException(Exception): | |
pass | |
class HoverAPI(object): | |
def __init__(self, username, password): | |
params = {"username": username, "password": password} | |
r = requests.post("https://www.hover.com/api/login", params=params) | |
if not r.ok or "hoverauth" not in r.cookies: | |
raise HoverException(r) | |
self.cookies = {"hoverauth": r.cookies["hoverauth"]} | |
def call(self, method, resource, data=None): | |
url = "https://www.hover.com/api/{0}".format(resource) | |
r = requests.request(method, url, data=data, cookies=self.cookies) | |
if not r.ok: | |
raise HoverException(r) | |
if r.content: | |
body = r.json() | |
if "succeeded" not in body or body["succeeded"] is not True: | |
raise HoverException(body) | |
return body | |
ip = requests.post("http://bot.whatismyipaddress.com") | |
if ip.ok: | |
# connect to the API using your account | |
client = HoverAPI(username, password) | |
current_ip = ip.content | |
same_ip = False | |
current = client.call("get", "dns") | |
try: | |
for domain in current.get("domains"): | |
for entry in domain["entries"]: | |
if entry["id"] == dns_id and entry["content"] == current_ip: | |
same_ip = True | |
except: | |
pass | |
if not same_ip: | |
client.call("put", "dns/" + dns_id, {"content": current_ip}) |
Thanks for this!
I have incorporated the functionality of your script into a script that does what yours does, but can also run continuously polling every so often for a change. I also added and simple install script and systemd .service file to allow using it as a service on Linux (at least on Ubuntu)
This stopped working recently, I had to update line 38 to post as (application/json)
r = requests.post("https://www.hover.com/api/login", json=params)
I can't seem to update records with PUT to api/dns/{id}
. I continually get an error: "Can not update attributes: dn"
Has anyone else seen this issue?
@MasterRex yes - but I am unable to fix it. Did you find a way?
As the API is entirely un-documented and un-supported, it appears they've made some changes recently :) @MasterRex and @bkanuka , this might help?
@heypete - thanks for the OpenDNS trick :)
The API URL for a DNS update now appears to be
https://www.hover.com/api/control_panel/dns
and the minimum JSON required to perform an update is
{"domain":{"id":"domain-YOURDOMAIN.COM","dns_records":[{"id":"dns12345678"}]},"fields":{"content":"127.0.0.1"}}
For anyone interested I've pulled this together into a powershell script which will update a single record.
The script demonstrates the bare essentials, nothing clever - but it does what I need it to for now :)
#Update which Hover record?
$dnsID = "dns12345678"
$dnsdomain = "YOURDOMAIN.com"
$username = "Username"
$password = "Password"
#Get current public IP (pretty cool little trick, don't adjust this line)
$myIP = Resolve-DnsName -Name myip.opendns.com -Server resolver1.opendns.com
#Connect to HoverAPI
$Headers = @{ "accept"="application/json";
"content-type"="application/json"}
$params = @{ "username"=$username;
"password"=$password}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$loginResult = Invoke-WebRequest -Uri "https://www.hover.com/api/login" -Method POST -Body ($params|ConvertTo-Json) -Headers $Headers -SessionVariable WebSession
#Check the login was successful
if($loginResult.Headers.'Set-Cookie' -notmatch "hoverauth" -or $loginResult.StatusDescription -ne "OK")
{
Write-Host "There has been a problem"
}
else
{
#update the record
$jsonRequest = '{"domain":{"id":"domain-' + $dnsdomain + '","dns_records":[{"id":"'+$dnsID+'"}]},"fields":{"content":"' + $myIP.IPAddress + '"}}'
$updateResult = Invoke-WebRequest -Uri "https://www.hover.com/api/control_panel/dns" -Method put -Body $jsonRequest -WebSession $WebSession
}
Cheers!
Nat
@bkanuka Lexicon would seem to do the job nicely :) Wish I'd noticed it sooner! but then I wouldn't have had the fun of figuring this out. Thanks for the heads up! I'll be sure to point others in that direction in the future :) - and thanks for replying ^.^
Instead of making a relatively heavy TCP+HTTP call to http://bot.whatismyipaddress.com to determine your IP address, considering making a lightweight UDP+DNS call instead.
If you perform a DNS query for the A record of myip.opendns.com using resolver{1,2}.opendns.com, the result will be your IP address. Note: you need to directly query that server, rather than using your ISP's (or other) resolving nameservers.
The equivalent query using dig would be: "dig +short myip.opendns.com @resolver1.opendns.com". I'm not sure how that'd translate to Python, but I'd imagine it's fairly straightforward.