1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
"""
ddupdate plugin to retrieve address as seen from internet.
See: ddupdate(8)
"""
import urllib.request
import re
from ddupdate.ddplugin import AddressPlugin, AddressError, IpAddr
_URLS = [
'http://checkip.dyndns.org/',
'https://api.ipify.org?format=json',
'https://ifconfig.co'
]
class DefaultWebPlugin(AddressPlugin):
"""
Get the external address as seen from the web.
Relies on urls defined in _URLS, trying each in turn when running
into trouble.
Options used: none
"""
_name = 'default-web-ip'
_oneliner = 'Obtain external address as seen from the net'
def get_ip(self, log, options):
"""Implement AddressPlugin.get_ip()."""
def check_url(url):
"""Get reply from host and decode."""
log.debug('trying ' + url)
try:
with urllib.request.urlopen(url) as response:
html = response.read().decode('utf-8')
except (urllib.error.HTTPError, urllib.error.URLError):
log.debug("Bad response at %s (ignored)" % url)
return None
log.debug("Got response: %s", html)
pat = re.compile(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")
match = pat.search(html)
if match:
return html[match.start(): match.end()]
log.debug("Cannot parse address reply")
return None
for ix, url in enumerate(_URLS):
ip = check_url(url)
if ip:
return IpAddr(ip)
if ix + 1 < len(_URLS):
log.info("Falling back to %s", _URLS[ix + 1])
raise AddressError(
"Cannot obtain ip address (%s, %s and %s tried)" % tuple(_URLS))
|