File: addr_default_web6.py

package info (click to toggle)
ddupdate 0.7.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 420 kB
  • sloc: python: 1,899; sh: 38; makefile: 35
file content (65 lines) | stat: -rw-r--r-- 2,014 bytes parent folder | download | duplicates (4)
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
60
61
62
63
64
65
"""
ddupdate plugin to retrieve ipv6 address as seen from internet.

See: ddupdate(8)
"""

import urllib.request
import urllib.error
import re

from ddupdate.ddplugin import AddressPlugin, AddressError, IpAddr

TIMEOUT = 20


class DefaultWeb6Plugin(AddressPlugin):
    """
    Get the external ipv6 address as seen from the web.

    Relies on now-dns.com, falling back to ipv6.whatismyip.akamai.com
    and ifcfg.me.

    Options used: none
    """

    _name = 'default-web-ip6'
    _oneliner = 'Obtain external ipv6 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, None, TIMEOUT) as response:
                    if response.getcode() != 200:
                        log.debug("Bad response at %s (ignored)" % url)
                        return None
                    html = response.read().decode()
            except urllib.error.URLError as err:
                log.debug("Got URLError: %s", err)
                return None
            log.debug("Got response: %s", html)
            pat = re.compile(r'[:0-9a-f]{12,}(\s|\Z)')
            match = pat.search(html)
            if match:
                return html[match.start(): match.end()]
            log.debug("Cannot parse ipv6 address reply")
            return None

        urls = [
            'https://now-dns.com/ip',
            'http://ipv6.whatismyip.akamai.com',
            'https://ifcfg.me/'
        ]
        for ix, url in enumerate(urls):
            log.info('Trying: %s', url)
            ip = check_url(url)
            if ip:
                return IpAddr(None, ip)
            if ix + 1 < len(urls):
                log.info("Falling back to %s", urls[ix + 1])
        raise AddressError(
            "Cannot obtain ip6 address (%s, %s and %s tried)"
            % tuple(urls))