checking in

This commit is contained in:
brent s. 2020-05-12 03:26:44 -04:00
parent c596a4d341
commit 7170f61160
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
7 changed files with 169 additions and 1 deletions

View File

@ -0,0 +1,5 @@
from . import args
from . import config
from . import logger
from . import tunnelbroker
from . import main

32
utils/he_ipv6/args.py Normal file
View File

@ -0,0 +1,32 @@
import argparse


def parseArgs():
args = argparse.ArgumentParser(description = ('Dynamically update and enable/disable '
'Hurricane Electric Tunnelbroker'))
args.add_argument('-i', '--no-wan-ip',
dest = 'wan_ip',
action = 'store_false',
help = ('If specified, use the RFC1918 IP address assigned to this machine instead of the WAN '
'IP (necessary if this machine is behind NAT)'))
args.add_argument('-c', '--config',
dest = 'conf',
default = '~/.config/he_tunnelbroker.ini',
help = ('The path to the config. '
'Default: ~/.config/he_tunnelbroker.ini'))
args.add_argument('-t', '--tunnel-id',
dest = 'tun_id',
help = ('The tunnel profile ID/name to use in -c/--config. '
'Default is to use the first one found.'))
args.add_argument('-u', '--no-update',
dest = 'update',
action = 'store_false',
help = ('If specified, do not perform the automatic update for start operations. Has no effect '
'for other operations'))
args.add_argument('oper',
metavar = 'OPERATION',
choices = ('update', 'start', 'stop'),
help = ('The operation to perform ("start", "stop", or "update"). "update" is performed '
'automatically by "start", but otherwise will just update the IPv4 address on record '
'at tunnelbroker'))
return(args)

View File

@ -1,3 +1,4 @@
import collections
import copy import copy
import ipaddress import ipaddress
import os import os
@ -6,6 +7,7 @@ import re
import netaddr import netaddr
import requests import requests
from lxml import etree from lxml import etree
from pyroute2 import IPRoute




class IP(object): class IP(object):
@ -56,11 +58,15 @@ class Allocation(object):
self.prefix = None self.prefix = None
self.ip = None self.ip = None
self.iface = None self.iface = None
self.iface_idx = None
self.parse() self.parse()


def _iface(self): def _iface(self):
_iface_txt = self.xml.attrib['iface'] _iface_txt = self.xml.attrib['iface']
self.iface = _iface_txt.strip() self.iface = _iface_txt.strip()
ipr = IPRoute()
self.iface_idx = ipr.link_lookup(ifname = self.iface)[0]
ipr.close()
return(None) return(None)


def _ip(self): def _ip(self):
@ -173,7 +179,7 @@ class Config(object):
self.xsd = None self.xsd = None
self.defaults_parser = None self.defaults_parser = None
self.obj = None self.obj = None
self.tunnels = {} self.tunnels = collections.OrderedDict()
self.creds = {} self.creds = {}
self.parse() self.parse()



49
utils/he_ipv6/logger.py Normal file
View File

@ -0,0 +1,49 @@
import logging
import logging.handlers
import os
try:
# https://www.freedesktop.org/software/systemd/python-systemd/journal.html#journalhandler-class
from systemd import journal
_has_journald = True
except ImportError:
_has_journald = False


logfile = '/var/log/tunnelbroker_manager.log'
# Prep the log file.
logfile = os.path.abspath(os.path.expanduser(logfile))
os.makedirs(os.path.dirname(logfile), exist_ok = True, mode = 0o0700)
if not os.path.isfile(logfile):
with open(logfile, 'w') as fh:
fh.write('')
os.chmod(logfile, 0o0600)

# And set up logging.
_cfg_args = {'handlers': [],
'level': logging.DEBUG}
if _has_journald:
# There were some weird changes somewhere along the line.
try:
# But it's *probably* this one.
h = journal.JournalHandler()
except AttributeError:
h = journal.JournaldLogHandler()
# Systemd includes times, so we don't need to.
h.setFormatter(logging.Formatter(style = '{',
fmt = ('{name}:{levelname}:{name}:{filename}:'
'{funcName}:{lineno}: {message}')))
_cfg_args['handlers'].append(h)
h = logging.handlers.RotatingFileHandler(logfile,
encoding = 'utf8',
# Disable rotating for now.
# maxBytes = 50000000000,
# backupCount = 30
)
h.setFormatter(logging.Formatter(style = '{',
fmt = ('{asctime}:'
'{levelname}:{name}:{filename}:'
'{funcName}:{lineno}: {message}')))
_cfg_args['handlers'].append(h)
logging.basicConfig(**_cfg_args)
logger = logging.getLogger('HE Tunnelbroker Manager')
logger.info('Logging initialized.')

24
utils/he_ipv6/main.py Executable file
View File

@ -0,0 +1,24 @@
import logging
##
from . import args
from . import tunnelbroker


logger = logging.getLogger()


def main():
_args = args.parseArgs().parse_args()
logger.debug('Invoked with args: {0}'.format(vars(_args)))
tb = tunnelbroker.TunnelBroker(**vars(_args))
if _args.oper == 'start':
tb.start()
elif _args.oper == 'stop':
tb.stop()
elif _args.oper == 'update':
tb.update(oneshot = True)
return(None)


if __name__ == '__main__':
main()

4
utils/he_ipv6/ref Normal file
View File

@ -0,0 +1,4 @@
# https://wiki.archlinux.org/index.php/IPv6_tunnel_broker_setup
# https://forums.he.net/index.php?topic=3153.0
# https://gist.github.com/pklaus/960672
# https://shorewall.org/6to4.htm#idm143

View File

@ -0,0 +1,48 @@
import logging
import os
import socket
logger = logging.getLogger()
##
import requests
from pyroute2 import IPRoute
##
from . import config


class TunnelBroker(object):
url_ip = 'https://ipv4.clientinfo.square-r00t.net/'
params_ip = {'raw': '1'}
url_api = 'https://ipv4.tunnelbroker.net/nic/update'

def __init__(self, conf_xml, tun_id = None, wan_ip = True, update = True, *args, **kwargs):
self.conf_file = os.path.abspath(os.path.expanduser(conf_xml))
logger.debug('Using config path: {0}'.format(self.conf_file))
self._conf = config.Config(self.conf_file)
if tun_id:
self.cfg = self._conf.tunnels[int(tun_id)]
else:
tun_id = list(self._conf.tunnels.keys())[0]
self.cfg = self._conf.tunnels[tun_id]
self.wan = wan_ip
self.update = update
self.my_ip = None

def _get_my_ip(self):
if self.wan:
logger.debug('WAN IP tunneling enabled; fetching WAN IP.')
req = requests.get(self.url_ip, params = self.params_ip)
if not req.ok:
logger.error('Could not fetch self IP. Request returned {0}.'.format(req.status_code))
raise RuntimeError('Could not fetch self IP')
self.my_ip = config.IP4(req.json()['ip'], 32)
logger.debug('Set my_ip to {0}.'.format(self.my_ip.str))
else:
logger.debug('WAN IP tunneling disabled; fetching LAN IP.')
ipr = IPRoute()
_defrt = ipr.get_default_routes(family = socket.AF_INET)
if len(_defrt) != 1: # This (probably) WILL fail on multipath systems.
logger.error('Could not determine default route. Does this machine have a single default route?')
raise RuntimeError('Could not determine default IPv4 route')
self.my_ip = config.IP4(_defrt[0]['attrs']['RTA_PREFSRC'], 32)
logger.debug('Set my_ip to {0}.'.format(self.my_ip.str))
return(None)