okay. so the config's cleaned up, and we now create a sparse example config file.

This commit is contained in:
brent s. 2020-05-16 03:48:02 -04:00
parent a0d5071a8d
commit 5f2883a698
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
3 changed files with 128 additions and 55 deletions

View File

@ -1,53 +1,71 @@
import collections
import copy
import ipaddress
import os
import re
##
import netaddr
import requests
import requests.auth
from lxml import etree
from pyroute2 import IPRoute
##
from . import tunnel


def create_default_cfg():
# Create a stripped sample config.
nsmap = {None: 'https://tunnelbroker.net/',
'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
attr_qname = etree.QName('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')
schema_url = 'http://schema.xml.r00t2.io/projects/he_ipv6.xsd'
schema_loc = '{0} {1}'.format(nsmap[None], schema_url)
xml = etree.Element('heIPv6',
{attr_qname: schema_loc},
nsmap = nsmap)
xml.append(etree.Comment(('See example.tunnelbroker.xml for an extensively commented sample config.')))
creds = etree.SubElement(xml, 'creds')
creds.append(etree.Comment(('Your tunnelbroker.net *login*. You can specify multiple credentials via multiple '
'"cred" items. The "id" attribute is up to you but it must be unique.')))
cred = etree.SubElement(creds, 'cred')
cred.attrib['id'] = ''
user = etree.SubElement(cred, 'user')
user.text = ''
password = etree.SubElement(cred, 'password')
password.text = ''
tunnels = etree.SubElement(xml, 'tunnels')
tunnels.append(etree.Comment(('You can have define multiple tunnels via multiple "tunnel" items. You should most '
'likely only run one at a time.')))
tunnel = etree.SubElement(tunnels, 'tunnel')
tunnel.append(etree.Comment(('The "id" attribute should match the id number of a tunnel on your tunnelbroker.net '
'account. The "creds" attribute references a cred item id attribute.')))
tunnel.attrib['id'] = ''
tunnel.attrib['creds'] = ''
ukey = etree.SubElement(tunnel, '')
return (etree.tostring(xml,
encoding = 'UTF-8',
xml_declaration = True,
pretty_print = True,
with_tail = True,
with_comments = True))
ws_re = re.compile(r'^\s*$')
cur_dir = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
xtbxml = os.path.join(cur_dir, 'example.tunnelbroker.xml')
with open(xtbxml, 'rb') as fh:
xml = etree.fromstring(fh.read())
# Create a stripped sample config.
# First we strip comments (and fix the ensuing whitespace).
# etree has a .canonicalize(), but it chokes on a default namespace.
# https://bugs.launchpad.net/lxml/+bug/1869455
# So everything we do is kind of a hack.
# for c in xml.xpath("//comment()"):
# parent = c.getparent()
# parent.remove(c)
xmlstr = etree.tostring(xml, with_comments = False, method = 'c14n', pretty_print = True).decode('utf-8')
newstr = []
for line in xmlstr.splitlines():
r = ws_re.search(line)
if not r:
newstr.append(line.strip())
xml = etree.fromstring(''.join(newstr).encode('utf-8'))
# Remove text and attr text.
xpathq = "descendant-or-self::*[namespace-uri()!='']"
for e in xml.xpath(xpathq):
if e.tag == '{{{0}}}heIPv6'.format(xml.nsmap[None]):
continue
if e.text is not None and e.text.strip() != '':
e.text = ''
for k, v in e.attrib.items():
if v is not None:
e.attrib[k] = ''
# Remove multiple children of same type to simplify.
for e in xml.xpath(xpathq):
if e.tag == '{{{0}}}heIPv6'.format(xml.nsmap[None]):
continue
parent = e.getparent()
try:
for idx, child in enumerate(parent.findall(e.tag)):
if idx == 0:
continue
parent.remove(child)
except AttributeError:
pass
# And add a comment pointing them to the fully commented config.
xml.insert(0, etree.Comment(('\n Please reference the fully commented example.tunnelbroker.xml found either '
'at:\n '
' * {0}\n * https://git.square-r00t.net/RouterBox/tree/utils/he_ipv6/'
'example.tunnelbroker.xml\n and then configure this according to those '
'instructions.\n ').format(xtbxml)))
return(etree.tostring(xml,
pretty_print = True,
with_comments = True,
with_tail = True,
encoding = 'UTF-8',
xml_declaration = True))


class Credential(object):
@ -189,7 +207,10 @@ class Config(BaseConfig):
def __init__(self, xml_path, *args, **kwargs):
self.xml_path = os.path.abspath(os.path.expanduser(xml_path))
if not os.path.isfile(self.xml_path):
raise ValueError('xml_path does not exist')
with open(self.xml_path, 'wb') as fh:
fh.write(create_default_cfg())
raise ValueError('xml_path does not exist; '
'a sample configuration has been generated (be sure to configure it)')
else:
with open(xml_path, 'rb') as fh:
raw_xml = fh.read()

View File

@ -8,7 +8,8 @@
https://www.tunnelbroker.net/tunnel_detail.php?tid=584532
I highly recommend their (free) certification as well if you're brand-new to IPv6:
https://ipv6.he.net/certification/
**It is VERY highly encouraged to only use one tunnel at a time on a machine.**
**It is VERY highly encouraged to only use one tunnel at a time on a machine. Completely unpredictable results will
incur if this is not heeded.**
-->
<creds>
<!--
@ -39,10 +40,14 @@
-->
<updateKey>xXxXxXxXxXxXxXXX</updateKey>
<!--
Where to assign your allocations. The default allocation prefix is a /64 (prefix="64"), since that's what SLAAC
recommends.
It has one optional attribute, "raProvider", which can be "dnsmasq" or "radvd". Further system configuration may
be required. If not specified, the default is to not send router advertisements.
Where to assign your allocations. The default allocation prefix is a /64 (prefix="64"), since that's what
SLAAC (RFC 2462) recommends.
It has one optional attribute, "raProvider", which can be "dnsmasq" or "radvd". Its configuration file will be
regenerated and the service restarted after the addresses are allocated to interfaces. Further system
configuration may be required. If not specified, the default is to not send router advertisements (RFC 4861). See
the "ra" child element under <assign> for further details.
If you are using dnsmasq, you will want to edit dnsmasq.conf to *include* the generated file, most likely, as it
only generates configuration for IPv6 options.
-->
<assignments raProvider="dnsmasq">
<!--
@ -60,24 +65,52 @@
-->
<assign prefix="64" alloc="64" iface="eth0">
<!--
Each assignment can have an "ra" child. The default is to not implement RA for this interface if not
present.
Each assignment CAN have an "ra" child. The default is to not implement RA for this interface if an ra element
is not present.
It takes one optional attribute, which is only used for raProvider="dnsmasq", "tag", which is the tag name for
the interface (this should be set in an earlier included conf/the main dnsmasq.conf).
-->
<ra>
<dns>true</dns>
<dhcpv6>true</dhcpv6>
<ra tag="main">
<!--
Specify RDNSS (RFC 8106). If specified, this allocation's "router IP" (<PREFIX>::1) will be passed as a
resolver via RDNSS.
It takes one (optional) attribute, "domains", which is a space-separated list of search domains, referred
to in IPv6 as DNSSL (RFC 6106).
Note that Windows does not support DNSSL, and as such you must use dhcpv6's "domains" attribute if you wish
to do that.
If "domains" is specified but the element is false, the configuration will only advertise DNSSL and not
RDNSS.
-->
<dns domains="foo.com bar.com">true</dns>
<!--
Enable DHCPv6 for this assignment. Only used for dnsmasq, has no effect for radvd. As mentioned above, you
can also specify the "domains" attribute here as well, which will pass them via a regular DHCPv6 option.
If "domains" is specified but the element is false, only the domains will be passed.
Again, this only pertains to dnsmasq since radvd offers no DHCPv6 capabilities whatsoever.
-->
<dhcpv6 domains="foo.com bar.com">true</dhcpv6>
</ra>
</assign>
<!-- Disable RA for this set (no "ra" chiled specified). -->
<assign prefix="64" alloc="48" iface="eth0"/>
<assign prefix="64" alloc="48" iface="eth1">

<ra tag="vmlan">
<!-- This will use strictly SLAAC (if using dnsmasq, obviously - radvd only does SLAAC). -->
<dhcpv6>false</dhcpv6>
<!-- And let clients choose their own resolver. -->
<dns>false</dns>
</ra>
</assign>
<assign prefix="64" alloc="48" iface="eth2">
<ra tag="wlan">
<!-- Only pass RDNSS resolvers. -->
<dns>true</dns>
<dhcpv6>false</dhcpv6>
</ra>
</assign>
<assign prefix="64" alloc="48" iface="eth2"/>
</assignments>
</tunnel>
<!--
And you can, of course, specify multiple tunnels.
-->
<!-- And you can, of course, specify multiple tunnels. -->
<tunnel id="54321" creds="anotheruser">
<updateKey>0000000000000000</updateKey>
<assignments>

View File

@ -1,4 +1,4 @@
## General Info/Networking Configuration
## General Info/Networking Configuration ##
# https://wiki.archlinux.org/index.php/IPv6_tunnel_broker_setup
# https://gist.github.com/pklaus/960672
# https://genneko.github.io/playing-with-bsd/networking/freebsd-tunnelv6-he
@ -8,8 +8,27 @@
# https://shorewall.org/6to4.htm#idm143
# https://shorewall.org/6to4.htm#SixInFour
# https://wiki.ubuntu.com/IPv6#Configure_your_Ubuntu_box_as_a_IPv6_router
# http://koo.fi/blog/2013/03/20/linux-ipv6-router-radvd-dhcpv6/

## Tunnelbroker API
## Tunnelbroker API ##
# https://forums.he.net/index.php?topic=3153.0 ("The following scripts conform to the Dyn DNS Update API (as documented at http://dyn.com/support/developers/api/).")
# https://help.dyn.com/remote-access-api/return-codes/
#

## DNSMASQ ##
# https://hveem.no/using-dnsmasq-for-dhcpv6

## RFCs ##
# DNSSL #
# https://tools.ietf.org/html/rfc6106
# https://tools.ietf.org/html/rfc8106
# RDNSS #
# https://tools.ietf.org/html/rfc5006 (see also 6106, 8106)
# SLAAC
# https://tools.ietf.org/html/rfc2462
# https://tools.ietf.org/html/rfc4862
# https://tools.ietf.org/html/rfc8064
# Router Advertisements
# https://tools.ietf.org/html/rfc4861
# https://tools.ietf.org/html/rfc5175
# https://tools.ietf.org/html/rfc6104
# https://tools.ietf.org/html/rfc7772