diff --git a/_extras/example_configs/gobroke.json b/_extras/example_configs/gobroke.json new file mode 100644 index 0000000..9005313 --- /dev/null +++ b/_extras/example_configs/gobroke.json @@ -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" + } + ] +} diff --git a/_extras/example_configs/gobroke.toml b/_extras/example_configs/gobroke.toml new file mode 100644 index 0000000..5918e9a --- /dev/null +++ b/_extras/example_configs/gobroke.toml @@ -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= + # 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" diff --git a/_extras/example_configs/gobroke.xml b/_extras/example_configs/gobroke.xml new file mode 100644 index 0000000..52289cf --- /dev/null +++ b/_extras/example_configs/gobroke.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + -f + foo + + + SOMEENV=SOMEVAL + + + + + + + + + + restart + someservice + + + + + + + + + + diff --git a/_extras/example_configs/gobroke.yml b/_extras/example_configs/gobroke.yml new file mode 100644 index 0000000..3dff57c --- /dev/null +++ b/_extras/example_configs/gobroke.yml @@ -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 diff --git a/conf/_testdata/test_uncommented.toml b/_extras/example_configs/uncommented.toml similarity index 83% rename from conf/_testdata/test_uncommented.toml rename to _extras/example_configs/uncommented.toml index c836043..38c12c3 100644 --- a/conf/_testdata/test_uncommented.toml +++ b/_extras/example_configs/uncommented.toml @@ -1,15 +1,6 @@ -DefaultUsername = "default_user" +DefaultUsername = 'default_user' +Frequency = '5m' SingleTunnel = true -CacheDbPath = '/var/cache/gobroke.db' -[CacheDbPerms] - [CacheDbPerms.File] - User = "" - Group = "" - Mode = 0o0600 - [CacheDbPerms.Dir] - User = "" - Group = "" - Mode = 0o0700 [[Tunnel]] TunnelID = 123 ExplicitClientIP = '203.0.113.1' diff --git a/_extras/example_tpls/dnsmasq/ra_dhcpv6.conf.tpl b/_extras/example_tpls/dnsmasq/ra_dhcpv6.conf.tpl new file mode 100644 index 0000000..8fca982 --- /dev/null +++ b/_extras/example_tpls/dnsmasq/ra_dhcpv6.conf.tpl @@ -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: