update... work pending

This commit is contained in:
brent saner
2025-02-04 12:14:08 -05:00
parent 3b4d712722
commit 3c984a0636
39 changed files with 2122 additions and 597 deletions

View File

@@ -0,0 +1,70 @@
{
"default_username": "default_user",
"freq": "5m",
"1tun": true,
"tunnels": [
{
"tun_id": 123,
"addr": "203.0.113.1",
"mtu": 1450,
"username": "specific_user",
"update_key": "abcdef",
"cfg_tpls": [
{
"tpl": "/etc/gobroke/tpl/dnsmasq/ra_dhcpv6.conf.tpl",
"dest": "/etc/dnsmasq.d/ra_dhcpv6.conf",
"perms": {
"file": {
"user": "",
"group": "",
"mode": 384
},
"dir": {
"user": "",
"group": "",
"mode": 448
}
},
"cmds": [
{
"bin": "/usr/local/bin/somecmd",
"args": [
"-f", "foo"
],
"isol8_env": false,
"env": [
"SOMEENV=SOMEVAL"
],
"on_change": true,
"is_tpl": false
}
]
},
{
"tpl": "/etc/gobroke/tpl/stat.tpl",
"dest": "/tmp/gobroke.dump"
}
],
"cmds": [
{
"bin": "systemctl",
"args": [
"restart",
"someservice"
],
"on_change": true
}
]
},
{
"tun_id": 456,
"username": "specific_user",
"update_key": "defghi"
}
],
"cmds": [
{
"bin": "/usr/local/bin/alltunsprogram"
}
]
}

View File

@@ -0,0 +1,280 @@
# This file is heavily commented explaining various configuration options.
# The other configuration file examples are uncommented, but their field names
# should be easily visually mapped to the ones in here.
# All example configuration files evaluate to the same configuration.
# The uncommented.toml file is the exact same is this but without
# empty newlines and comments.
# DefaultUsername specifies the default username to use for
# authenticating to tunnelbroker.net.
# It is optional, as the username can be specified for each Tunnel,
# but at least one or the other *must* be provided.
# This makes it easier if you have multiple tunnels under the same account
# (as possible in higher levels of HE IPv6 certification).
# If a username is specified in Tunnel.Username, it will be used.
# If not (and, of course, DefaultUsername is specified), then
# DefaultUsername will be used for that Tunnel.
DefaultUsername = 'default_user'
# Frequency specifies the check frequency in daemon mode.
# (Not used in single-run mode.)
# If not specified, it defaults to 5 minutes.
# Note that this does not specify how often the client IP is set/updated
# upstream, it specifies how often to *check* if it needs to be updated.
# It will always attempt to be updated if there is a mismatch, this just
# controls how often that check runs.
# It must be a string compatible with Golang's time.ParseDuration.
# (https://pkg.go.dev/time#ParseDuration)
# Note that there may be some "drift" from this; the timer is restarted
# after a check/update *completes* to avoid duplicate job duplication.
# Likewise, if SingleTunnel (below) is true, each run may take even
# longer than expected.
Frequency = '5m'
# If SingleTunnel is true, each Tunnel below will be run in order instead of
# concurrently.
# If there is any concern about race conditions (e.g. the same service being
# restarted by multiple tunnels, etc.), then it is HIGHLY RECOMMENDED
# you set this to true.
SingleTunnel = true
#############
## Tunnels ##
#############
# Each Tunnel represents a single tunnelbroker.net tunnel configuration.
# Note that each Tunnel is run concurrently. If this is undesired due to
# potential race conditions, set the root-level directive SingleTunnel
# to true.
# IMPORTANT: *DO NOT* define multiple tunnels with the same TunnelID.
# It makes no sense to do so, and GoBroke assumes that there are no
# duplicates.
[[Tunnel]]
# The TunnelID can be found by logging into https://tunnelbroker.net/ and,
# at the "Main Page" that loads when logging in, clicking on the desired
# tunnel name.
# The tunnel ID is then displayed in both the URL bar:
# https://tunnelbroker.net/tunnel_detail.php?tid=<TunnelID>
# And as the first line on the first tab ("IPv6 Tunnel" tab),
# labeled "Tunnel ID".
TunnelID = 123
# If you wish to use a different or explicit "Client IPv4 address",
# this can be specified via ExplicitClientIP.
# If it is empty or is not specified, the public IP of this host will be determined
# via an external service.
# This *must* be an IPv4 address (if specified).
ExplicitClientIP = '203.0.113.1'
# If you have specified a custom MTU under the "Advanced" tab for this tunnel,
# you can set this value here.
# If you have not set a custom one, leave this option unspecified;
# the default (and maximum allowed), 1480 MTU, will be used in that case.
# This is not used by anything directly in GoBroke, but is contained here
# to assist in templating that may be configured.
MTU = 1450
# The Username field is optional IF DefaultUsername was specified.
# This also allows you to specify tunnels from different accounts
# by providing a tunnel-specific username.
Username = "specific_user"
# The UpdateKey can be found under the "Advanced" tab on your tunnelbroker.net
# tunnel's page, labeled "Update Key".
# Your real token is likely to be a bit longer and more random.
# This token is used to not only update the client-side tunnel IP but also to
# query the HE Tunnelbroker "API" (it's really just a single endpoint)
# to get the tunnel configuration.
UpdateKey = "abcdef"
######################
## Config Templates ##
######################
# Each ConfigTemplate consists of a path to a template file and a destination
# file at the bere minimum. In addition, Commands may be provided.
# Any paths leading up to Destination that don't exist will (attempt to be)
# created.
# The template is always rendered in memory, but the destination is only written
# if:
# * The Destination doesn't exist
# * The Destination differs from the buffered rendering of the template
[[Tunnel.ConfigTemplate]]
# Template points to where the template file can be found.
# It must be in a Golang text/template syntax/format; see:
# https://pkg.go.dev/text/template
# Refer to this library's definition of the runner.TunnelResult struct;
# this is the object that is passed to the template.
Template = "/etc/gobroke/tpl/dnsmasq/ra_dhcpv6.conf.tpl"
# Destination is the file to write to.
# It will only be written to if:
# * The path does not exist
# * The path exists but is different from the in-memory rendered buffer
# An attempt will be made to create any leading components that are not
# present.
# It is recommended to enforce permissions/ownership of these via the
# Commands.
Destination = "/etc/dnsmasq.d/ra_dhcpv6.conf"
#################################
## Config Template Permissions ##
#################################
# Permissions can be defined for the Destination file.
# They are completely optional, in which case the default umask, user,
# group, etc. for the runtime user will be used, and permissions/ownership
# will not be enforced for existing Destination files.
# If the file exists and permissions are defined, they will
# be enforced.
# If the file exists but no permissions are defined, they
# will be left as-is.
[[Tunnel.ConfigTemplate.Permissions]]
# Permissions are/may be defined for both the file being written
# and the parent directory (see below).
[[Tunnel.ConfigTemplate.Permissions.File]]
# The User is optional.
# If specified as '-1', the owner will not be modified/enforced.
# If specified as an empty string (the default), the runtime EUID is enforced.
# Otherwise, it may be a username or a UID (checked in that order).
# (For new files/directories, the OS default behavior is used.)
User = ""
# Group is also optional, and follows the same exact logic as User except
# for EGID/groupnames/GIDs.
Group = ""
# Mode is optional also.
# It *must* be equal to the octal mode bits (e.g. it must be an
# unsigned integer 0-4095), but may be represented in multiple ways.
# e.g.:
# Mode = 0o0600
# Mode = 0o600
# Mode = 0x0180
# Mode = 0x180
# Mode = 0b110000000
# Mode = 384
# All evaluate to the exact same value in TOML:
# https://toml.io/en/v1.0.0#integer
# For consistency with `chmod(1)`, it is recommended to use the
# octal representation (0o0600 or 0o600 above).
# If you need help determining what number you should actually use,
# you can use the calculator here:
# https://rubendougall.co.uk/projects/permissions-calculator/
# (source: https://github.com/Ruben9922/permissions-calculator )
# (Supports/includes "special" bits)
# or here:
# https://wintelguy.com/permissions-calc.pl
# (beware of ads)
# (provides an explanation of the bits)
# Or see https://en.wikipedia.org/wiki/Chmod
# Note that this does, technically, work on Windows but only read vs. read-write
# for the User is used (https://pkg.go.dev/os?GOOS=windows#Chmod).
# If not specified, the default is 0o0600 for files and 0o0700 for directories.
Mode = 0o0600
# Dir permissions specifiy permissions/ownership of the parent directory of File.
# The same rules, logic, behavior, etc. as in File apply here.
[[Tunnel.ConfigTemplate.Permissions.Dir]]
User = ""
Group = ""
Mode = 0o0700
##############################
## Config Template Commands ##
##############################
# Commands are am optional collection of commands to run as part of this template
# run.
# Multiple Commands may be specified; they will be run in the order specified.
# The below Command would be equivalent to:
# SOMEENV=SOMEVAL /usr/local/bin/somecmd -f foo
# on the shell.
[[Tunnel.ConfigTemplate.Command]]
# ProgramPath should be the absolute path to the binary to run.
# It behaves as an (os/)exec.Cmd.Path (https://pkg.go.dev/os/exec#Cmd),
# It is recommended to use an absolute path.
ProgramPath = '/usr/local/bin/somecmd'
# Args are optional for a Command.
# They should conform to the rules for (os/)exec.Cmd.Args.
Args = [
'-f', 'foo',
]
# If IsolatedEnv is false (the default), the runtime environment variables
# will be applied to the command.
# If true, *only* the EnvVars, if specified, will be used for the spawned
# command (an empty environment will be used if IsolateEnv is true and
# no EnvVars are specified).
IsolatedEnv = false
# If provided, EnvVars can be used to add/replace environment variables.
# They should conform to the rules for (os/)exec.Cmd.Env.
# Whether they are added to/selectively replace or completely replace
# the current runtime environment variables depends on how IsolateEnv
# is configured.
EnvVars = [
'SOMEENV=SOMEVAL',
]
# If OnChange is true, this Command will run *only if SOMETHING CHANGED*.
# (e.g. a /48 was added to the tunnel, the client IP is different, etc.)
# If false, this Command will run *only if NOTHING CHANGED*.
# If unspecified, the default is to always run this command regardless
# of change status.
# Writing out this template to disk as a new file counts as a "change".
OnChange = true
# By default, this Command will be run literally/as-is.
# However, in some cases it may be useful to dynamically template out
# commands to run.
# If IsTemplate is set to true, then this Command.ProgramPath, each
# of the Command.Args, and each of the Command.EnvVars will be
# treated as Golang text/template strings as well, and will also
# be passed a runner.TunnelResult.
# Note that if IsolateEnv is false, runtime/inherited environment
# variables will *not* be templated.
# It is recommended to not enable this unless necessary as it can add
# a non-negligible amount of resource overhead/execution time.
IsTemplate = false
#######################################################################
# Multiple ConfigTemplates may be specified.
[[Tunnel.ConfigTemplate]]
Template = "/etc/gobroke/tpl/stat.tpl"
Destination = "/tmp/gobroke.dump"
#####################
## Tunnel Commands ##
#####################
# Each Tunnel also supports its own commands. The syntax, spcification,
# behavior, etc. is the same as the Tunnel.ConfigTemplate.Command.
# These are executed after all Tunnel.ConfigTemplate (if any) are executed.
# This is particularly useful for consolidating service restarts.
[[Tunnel.Command]]
ProgramPath = 'systemctl'
Args = [
'restart',
'someservice',
]
# OnChange in a Tunnel.Command is scoped to any updates of the tunnel
# and any changes in ANY of the Tunnel.ConfigTemplate specified
# for this Tunnel (if true and ConfigTemplate were specified).
OnChange = true
###############################################################################
# Multiple tunnel configurations are supported as well.
[[Tunnel]]
TunnelID = 456
Username = "specific_user"
UpdateKey = "defghi"
######################
## General Commands ##
######################
# Command items may be specified at the root level as well.
# The syntax is like all other Commands items, with two exceptions:
# * There is no templating performed...
# * As such, there is no IsTemplate directive for these.
# A root-level Command is run after all tunnels complete.
# The OnChange directive is true if any Tunnels result in any changes.
[[Command]]
ProgramPath = "/usr/local/bin/alltunpsrogram"

View File

@@ -0,0 +1,60 @@
<!--
See the example TOML for detailed comments and explanations.
-->
<config defaultUser="default_user"
freq="5m"
oneTun="true">
<tunnels>
<tunnel id="123"
addr="203.0.113.1"
mtu="1450"
username="specific_user"
key="abcdef">
<config>
<tpl tpl="/etc/gobroke/tpl/dnsmasq/ra_dhcpv6.conf.tpl"
dest="/etc/dnsmasq.d/ra_dhcpv6.conf">
<perms>
<file user=""
group=""
mode="384"/>
<dir user=""
group=""
mode="448"/>
</perms>
<cmds>
<cmd bin="/usr/local/bin/somecmd"
isol8Env="false"
onChange="true"
isTpl="false">
<args>
<arg>-f</arg>
<arg>foo</arg>
</args>
<envs>
<env>SOMEENV=SOMEVAL</env>
</envs>
</cmd>
</cmds>
</tpl>
<tpl tpl="/etc/gobroke/tpl/stat.tpl"
dest="/tmp/gobroke.dump"/>
</config>
<commands>
<cmd bin="systemctl"
onChange="true">
<args>
<arg>restart</arg>
<arg>someservice</arg>
</args>
</cmd>
</commands>
</tunnel>
<tunnel id="456"
mtu="1480"
username="specific_user"
key="defghi"/>
</tunnels>
<commands>
<cmd bin="/usr/local/bin/alltunsprogram" isol8Env="false"/>
</commands>
</config>

View File

@@ -0,0 +1,49 @@
# See the example TOML for detailed comments and explanations.
Default Username: default_user
Frequency: 5m
Single Tunnel: true
Tunnels:
- Tunnel ID: 123
Explicit Client IP Address: 203.0.113.1
MTU: 1450
Username: specific_user
Update Key: abcdef
Configuration File Templates:
- Template File Path: /etc/gobroke/tpl/dnsmasq/ra_dhcpv6.conf.tpl
Destination File Path: /etc/dnsmasq.d/ra_dhcpv6.conf
Permissions and Ownership:
File:
User: ''
Group: ''
Mode: 384
Directory:
User: ''
Group: ''
Mode: 448
Commands:
- Program Path: /usr/local/bin/somecmd
Arguments:
- '-f'
- 'foo'
Isolated Environment: false
Environment Variables:
- SOMEENV=SOMEVAL
On Change: true
Is Template: false
- Template File Path: /etc/gobroke/tpl/stat.tpl
Destination File Path: /tmp/gobroke.dump
Commands:
- Program Path: systemctl
Arguments:
- restart
- someservice
On Change: true
- Tunnel ID: 456
Username: specific_user
Update Key: defghi
Commands:
- Program Path: /usr/local/bin/alltunsprogram

View File

@@ -0,0 +1,48 @@
DefaultUsername = 'default_user'
Frequency = '5m'
SingleTunnel = true
[[Tunnel]]
TunnelID = 123
ExplicitClientIP = '203.0.113.1'
MTU = 1450
Username = "specific_user"
UpdateKey = "abcdef"
[[Tunnel.ConfigTemplate]]
Template = "/etc/gobroke/tpl/dnsmasq/ra_dhcpv6.conf.tpl"
Destination = "/etc/dnsmasq.d/ra_dhcpv6.conf"
[[Tunnel.ConfigTemplate.Permissions]]
[[Tunnel.ConfigTemplate.Permissions.File]]
User = ""
Group = ""
Mode = 0o0600
[[Tunnel.ConfigTemplate.Permissions.Dir]]
User = ""
Group = ""
Mode = 0o0700
[[Tunnel.ConfigTemplate.Command]]
ProgramPath = '/usr/local/bin/somecmd'
Args = [
'-f', 'foo',
]
IsolatedEnv = false
EnvVars = [
'SOMEENV=SOMEVAL',
]
OnChange = true
IsTemplate = false
[[Tunnel.ConfigTemplate]]
Template = "/etc/gobroke/tpl/stat.tpl"
Destination = "/tmp/gobroke.dump"
[[Tunnel.Command]]
ProgramPath = 'systemctl'
Args = [
'restart',
'someservice',
]
OnChange = true
[[Tunnel]]
TunnelID = 456
Username = "specific_user"
UpdateKey = "defghi"
[[Command]]
ProgramPath = "/usr/local/bin/alltunpsrogram"

View File

@@ -0,0 +1,118 @@
{{- /*gotype: r00t2.io/gobroke/runner.TunnelResult*/ -}}
{{- $res := . -}}
{{- /*
In addition to all functions from net, net/netip, and go4.org/netipx
(with the exceptions of functions duplicated by methods which can be used by objects
returned from the above-mentioned functions),
the sprig func map (https://masterminds.github.io/sprig/) is also available.
*/ -}}
{{- /*
Data
*/ -}}
{{- /*
Arbitrary data may be assigned as JSON within the template, and parsed in using the fromJson function.
*/ -}}
{{- $dataMap := fromJson `{"enp1s0": {"tag": "wan"}}` -}}
{{- /*
Or explicitly created via sprig.
*/ -}}
{{- $wan_ifaces := splitList "," "enp1s0,enp2s0" -}}
{{- /*
Or via the various networking functionality.
*/ -}}
{{- $pfx := $res.TunnelAfter.Routed64 -}}
{{- if $res.TunnelAfter.Has48 -}}
{{- $pfx = $res.TunnelAfter.Routed48 }}
{{- end -}}
{{- /*
Settings
*/ -}}
{{- $v4_wan := -}}
{{- /* SLAAC */ -}}
{{- /*
Maximum seconds allowed between sending unsolicited multicast RAs. 4 < x < 1800
If using Mobile Extensions, 0.07 < x 1800
*/ -}}
{{- $max_inter := 60 -}}
{{- /*
Minimum seconds allowed between sending unsolicited multicast RAs. 3 < x < (0.75 * max_inter)
If using Mobile Extensions, 0.33 < x (e.g. 0.75 * max_inter)
*/ -}}
{{- $min_inter := 10 -}}
{{- /*
Minimum seconds between sending multicast RAs (solicited and unsolicited).
If using Mobile Extensions, 0.03 < x
*/ -}}
{{- $min_delay := 3 -}}
{{- /*
The lifetime associated with the default router in units of seconds. 0 OR max_inter < x < 9000
*/ -}}
{{- $lifetime := 9000 -}}
{{- /* DHCPv6 */ -}}
{{- /*
How long the lease should last until a new one is requested.
*/ -}}
{{- $lease_life := 21600 -}}{{- /* 6 hours == 21600 seconds */ -}}
{{- /*
How long the options are valid for.
It generally makes sense to align these with $lease_life.
It doesn't have to, but it's a good default most of the time.
*/ -}}
{{- $opts_life := $lease_life -}}
{{-/*
Config
*/-}}
# This file should be *included* in your dnsmasq configuration.
# Generated by GoBroke.
# See "dnsmasq --help dhcp6" for matching option identifers ("dhcp-option = ..., option6: <option>").
enable-ra
{{- range $pfxIdx, $pfx := }}
{{- set assign_loop = loop -}}
{%- set ra_opts = [] -%}
{%- if assignment.ra_tag -%}
{%- set id_set = 'tag:' + assignment.ra_tag -%}
{%- set identifier = id_set -%}
{%- set do_listen = false -%}
{%- else -%}
{%- set id_set = 'set:' + assignment.iface -%}
{%- set identifier = 'tag:' + assignment.iface -%}
{%- set do_listen = true -%}
{%- endif -%}
{%- if assignment.ra_dhcp is false -%}
{%- do ra_opts.append('ra-only') -%}
{%- if assignment.ra_other is true -%}
{%- do ra_opts.append('ra-stateless') -%}
{%- endif -%}
{%- endif -%}
{%- do ra_opts.append('slaac') -%}
{%- do ra_opts.append('ra-names') -%}
# {{ assignment.iface }} assignment
# Assignment blocks:
{%- for b in assignment.iface_blocks %}
# * {{ b|string }}
{%- endfor %}
{%- if do_listen %}
listen-address = {{ assignment.iface_ll }}
{%- endif %}
ra-param = {{ assignment.iface }}, mtu:{{ common_opts.mtu }}, high, {{ common_opts.min_delay }}, {{ common_opts.lifetime }}
{%- if assignment.ra_dhcp %}
{%- for block in assignment.assign_objs %}
{%- set dhcp_range = block.dhcp6_range|join(', ') -%}
{%- if loop.index0 == 0 %}
dhcp-range = {{ id_set }}, {{ dhcp_range }}, {{ ra_opts|join(', ') }}, {{ common_opts.lease_life }}
{%- else %}
dhcp-range = {{ identifier }}, {{ dhcp_range }}, {{ ra_opts|join(', ') }}, {{ common_opts.lease_life }}
{%- endif %}
{%- endfor %}
{%- else %}
dhcp-range = {{ id_set }}, ::, {{ ra_opts|join(', ') }}, {{ common_opts.lease_life }}{#- TODO: check this. #}
{%- endif %}
dhcp-option = {{ identifier }}, option6:information-refresh-time, {{ common_opts.opts_life }}
{%- if assignment.ra_dns %}
dhcp-option = {{ identifier }}, option6:dns-server, [{{ assignment.iface_ll }}]
{%- endif %}
{%- if assignment.ra_domains %}
dhcp-option = {{ identifier }}, option6:domain-search, {{ assignment.ra_domains|join(',') }}
{%- endif %}
{% endfor %}