[enh] Use a common method to retrieve public IP address

This commit is contained in:
Jérôme Lebleu 2016-03-08 11:08:57 +01:00
parent 5f08eb06ae
commit 8aa64a0641
4 changed files with 48 additions and 46 deletions

View file

@ -1169,7 +1169,7 @@ dyndns:
full: --key full: --key
help: Public DNS key help: Public DNS key
-i: -i:
full: --ip full: --ipv4
help: IP address to send help: IP address to send
-6: -6:
full: --ipv6 full: --ipv6

View file

@ -82,10 +82,7 @@ def domain_add(auth, domain, dyndns=False):
from yunohost.hook import hook_callback from yunohost.hook import hook_callback
attr_dict = { 'objectClass' : ['mailDomain', 'top'] } attr_dict = { 'objectClass' : ['mailDomain', 'top'] }
try:
ip = str(urlopen('https://ip.yunohost.org').read())
except IOError:
ip = "127.0.0.1"
now = datetime.datetime.now() now = datetime.datetime.now()
timestamp = str(now.year) + str(now.month) + str(now.day) timestamp = str(now.year) + str(now.month) + str(now.day)
@ -232,20 +229,16 @@ def domain_dns_conf(domain, ttl=None):
ip4 = ip6 = None ip4 = ip6 = None
# A/AAAA records # A/AAAA records
try: ip4 = get_public_ip()
ip4 = urlopen("https://ip.yunohost.org").read().strip()
except IOError:
raise MoulinetteError(errno.ENETUNREACH,
m18n.n('no_internet_connection'))
result = ( result = (
"@ {ttl} IN A {ip4}\n" "@ {ttl} IN A {ip4}\n"
"* {ttl} IN A {ip4}\n" "* {ttl} IN A {ip4}\n"
).format(ttl=ttl, ip4=ip4) ).format(ttl=ttl, ip4=ip4)
try: try:
ip6 = urlopen("http://ip6.yunohost.org").read().strip() ip6 = get_public_ip(6)
except IOError: except:
logger.debug('cannot retrieve IPv6', exc_info=1) pass
else: else:
result += ( result += (
"@ {ttl} IN AAAA {ip6}\n" "@ {ttl} IN AAAA {ip6}\n"
@ -295,3 +288,17 @@ def domain_dns_conf(domain, ttl=None):
) )
return result return result
def get_public_ip(protocol=4):
"""Retrieve the public IP address from ip.yunohost.org"""
if protocol not in [4, 6]:
raise ValueError("invalid protocol version")
try:
return urlopen("https://ip{protocol}.yunohost.org".format(
protocol=('' if protocol == 4 else 'v6')
)).read().strip()
except IOError:
logger.debug('cannot retrieve public IPv%d' % protocol, exc_info=1)
raise MoulinetteError(errno.ENETUNREACH,
m18n.n('no_internet_connection'))

View file

@ -35,6 +35,8 @@ import subprocess
from moulinette.core import MoulinetteError from moulinette.core import MoulinetteError
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
from yunohost.domain import get_public_ip
logger = getActionLogger('yunohost.dyndns') logger = getActionLogger('yunohost.dyndns')
@ -112,7 +114,8 @@ def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None
dyndns_installcron() dyndns_installcron()
def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=None, ipv6=None): def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None,
ipv4=None, ipv6=None):
""" """
Update IP on DynDNS platform Update IP on DynDNS platform
@ -120,7 +123,7 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non
domain -- Full domain to subscribe with domain -- Full domain to subscribe with
dyn_host -- Dynette DNS server to inform dyn_host -- Dynette DNS server to inform
key -- Public DNS key key -- Public DNS key
ip -- IP address to send ipv4 -- IP address to send
ipv6 -- IPv6 address to send ipv6 -- IPv6 address to send
""" """
@ -129,13 +132,8 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non
domain = f.readline().rstrip() domain = f.readline().rstrip()
# IPv4 # IPv4
if ip is None: if ipv4 is None:
try: ipv4 = get_public_ip()
new_ip = requests.get('https://ip.yunohost.org').text
except requests.ConnectionError:
raise MoulinetteError(errno.ENETUNREACH, m18n.n('no_internet_connection'))
else:
new_ip = ip
try: try:
with open('/etc/yunohost/dyndns/old_ip', 'r') as f: with open('/etc/yunohost/dyndns/old_ip', 'r') as f:
@ -145,7 +143,6 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non
# IPv6 # IPv6
if ipv6 is None: if ipv6 is None:
new_ipv6 = None
try: try:
ip_route_out = subprocess.check_output( ip_route_out = subprocess.check_output(
['ip', 'route', 'get', '2000::']).split('\n') ['ip', 'route', 'get', '2000::']).split('\n')
@ -153,7 +150,7 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non
if len(ip_route_out) > 0: if len(ip_route_out) > 0:
route = IPRouteLine(ip_route_out[0]) route = IPRouteLine(ip_route_out[0])
if not route.unreachable: if not route.unreachable:
new_ipv6 = route.src_addr ipv6 = route.src_addr
except (OSError, ValueError) as e: except (OSError, ValueError) as e:
# Unlikely case "ip route" does not return status 0 # Unlikely case "ip route" does not return status 0
@ -161,11 +158,8 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non
raise MoulinetteError(errno.EBADMSG, raise MoulinetteError(errno.EBADMSG,
"ip route cmd error : {}".format(e)) "ip route cmd error : {}".format(e))
if new_ipv6 is None: if ipv6 is None:
logger.warning(m18n.n('no_ipv6_connectivity')) logger.info(m18n.n('no_ipv6_connectivity'))
else:
new_ipv6 = ipv6
try: try:
with open('/etc/yunohost/dyndns/old_ipv6', 'r') as f: with open('/etc/yunohost/dyndns/old_ipv6', 'r') as f:
@ -173,7 +167,7 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non
except IOError: except IOError:
old_ipv6 = '0000:0000:0000:0000:0000:0000:0000:0000' old_ipv6 = '0000:0000:0000:0000:0000:0000:0000:0000'
if old_ip != new_ip or old_ipv6 != new_ipv6: if old_ip != ipv4 or old_ipv6 != ipv6:
host = domain.split('.')[1:] host = domain.split('.')[1:]
host = '.'.join(host) host = '.'.join(host)
lines = [ lines = [
@ -191,21 +185,21 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non
'update delete vjud.%s. AAAA' % domain, 'update delete vjud.%s. AAAA' % domain,
'update delete _xmpp-client._tcp.%s. SRV' % domain, 'update delete _xmpp-client._tcp.%s. SRV' % domain,
'update delete _xmpp-server._tcp.%s. SRV' % domain, 'update delete _xmpp-server._tcp.%s. SRV' % domain,
'update add %s. 1800 A %s' % (domain, new_ip), 'update add %s. 1800 A %s' % (domain, ipv4),
'update add %s. 14400 MX 5 %s.' % (domain, domain), 'update add %s. 14400 MX 5 %s.' % (domain, domain),
'update add %s. 14400 TXT "v=spf1 a mx -all"' % domain, 'update add %s. 14400 TXT "v=spf1 a mx -all"' % domain,
'update add pubsub.%s. 1800 A %s' % (domain, new_ip), 'update add pubsub.%s. 1800 A %s' % (domain, ipv4),
'update add muc.%s. 1800 A %s' % (domain, new_ip), 'update add muc.%s. 1800 A %s' % (domain, ipv4),
'update add vjud.%s. 1800 A %s' % (domain, new_ip), 'update add vjud.%s. 1800 A %s' % (domain, ipv4),
'update add _xmpp-client._tcp.%s. 14400 SRV 0 5 5222 %s.' % (domain, domain), 'update add _xmpp-client._tcp.%s. 14400 SRV 0 5 5222 %s.' % (domain, domain),
'update add _xmpp-server._tcp.%s. 14400 SRV 0 5 5269 %s.' % (domain, domain) 'update add _xmpp-server._tcp.%s. 14400 SRV 0 5 5269 %s.' % (domain, domain)
] ]
if new_ipv6 is not None: if ipv6 is not None:
lines += [ lines += [
'update add %s. 1800 AAAA %s' % (domain, new_ipv6), 'update add %s. 1800 AAAA %s' % (domain, ipv6),
'update add pubsub.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add pubsub.%s. 1800 AAAA %s' % (domain, ipv6),
'update add muc.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add muc.%s. 1800 AAAA %s' % (domain, ipv6),
'update add vjud.%s. 1800 AAAA %s' % (domain, new_ipv6), 'update add vjud.%s. 1800 AAAA %s' % (domain, ipv6),
] ]
lines += [ lines += [
'show', 'show',
@ -222,10 +216,10 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non
if os.system('/usr/bin/nsupdate -k %s /etc/yunohost/dyndns/zone' % private_key_file) == 0: if os.system('/usr/bin/nsupdate -k %s /etc/yunohost/dyndns/zone' % private_key_file) == 0:
logger.success(m18n.n('dyndns_ip_updated')) logger.success(m18n.n('dyndns_ip_updated'))
with open('/etc/yunohost/dyndns/old_ip', 'w') as f: with open('/etc/yunohost/dyndns/old_ip', 'w') as f:
f.write(new_ip) f.write(ipv4)
if new_ipv6 is not None: if ipv6 is not None:
with open('/etc/yunohost/dyndns/old_ipv6', 'w') as f: with open('/etc/yunohost/dyndns/old_ipv6', 'w') as f:
f.write(new_ipv6) f.write(ipv6)
else: else:
os.system('rm -f /etc/yunohost/dyndns/old_ip') os.system('rm -f /etc/yunohost/dyndns/old_ip')
os.system('rm -f /etc/yunohost/dyndns/old_ipv6') os.system('rm -f /etc/yunohost/dyndns/old_ipv6')

View file

@ -35,12 +35,13 @@ import errno
import os import os
import dns.resolver import dns.resolver
import cPickle as pickle import cPickle as pickle
from urllib import urlopen
from datetime import datetime, timedelta from datetime import datetime, timedelta
from moulinette.core import MoulinetteError from moulinette.core import MoulinetteError
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
from yunohost.domain import get_public_ip
logger = getActionLogger('yunohost.monitor') logger = getActionLogger('yunohost.monitor')
glances_uri = 'http://127.0.0.1:61209' glances_uri = 'http://127.0.0.1:61209'
@ -210,9 +211,9 @@ def monitor_network(units=None, human_readable=False):
logger.debug('interface name %s was not found', iname) logger.debug('interface name %s was not found', iname)
elif u == 'infos': elif u == 'infos':
try: try:
p_ip = str(urlopen('https://ip.yunohost.org').read()) p_ipv4 = get_public_ip()
except: except:
p_ip = 'unknown' p_ipv4 = 'unknown'
l_ip = 'unknown' l_ip = 'unknown'
for name, addrs in devices.items(): for name, addrs in devices.items():
@ -231,7 +232,7 @@ def monitor_network(units=None, human_readable=False):
proto, gateway = addr.popitem() proto, gateway = addr.popitem()
result[u] = { result[u] = {
'public_ip': p_ip, 'public_ip': p_ipv4,
'local_ip': l_ip, 'local_ip': l_ip,
'gateway': gateway, 'gateway': gateway,
} }