From e782db30e9ab2758c54fdfd8f48736121cb5a24e Mon Sep 17 00:00:00 2001 From: Andre Kelpe Date: Wed, 18 Nov 2020 23:37:32 +0100 Subject: [PATCH] Implements PostUp and PostDown commands using `/bin/sh` This introduces PostUp and PostDown in dsnet. PostUp and PostDown allow the user to run arbitrary commands after the device is up or down. These are typically used to change the firewall rules via iptables. A working example would be ... "PostUp" : "iptables -A FORWARD -i dsnet -j ACCEPT; iptables -A FORWARD -o dsnet -j ACCEPT; iptables -t nat -A POSTROUTING -o ens2 -j MASQUERADE ", "PostDown" : "iptables -D FORWARD -i dsnet -j ACCEPT; iptables -D FORWARD -o dsnet -j ACCEPT; iptables -t nat -D POSTROUTING -o ens2 -j MASQUERADE ", ... All commands are executed by `/bin/sh` and no filtering or sandboxing is applied. Users of this should know what they are doing. Fixes https://github.com/naggie/dsnet/issues/16 --- CONFIG.md | 8 ++++++++ README.md | 2 ++ add.go | 3 +-- configtypes.go | 8 +++++--- down.go | 5 +++++ reporttypes.go | 2 +- up.go | 5 +++++ util.go | 12 ++++++++++++ 8 files changed, 39 insertions(+), 6 deletions(-) diff --git a/CONFIG.md b/CONFIG.md index cbaa2d6..7e7f428 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -66,6 +66,14 @@ with [hugo](https://gohugo.io/) network overview page. The shortcode file is included in this repository under `etc/`. + "PostUp": "" + "PostDown": "" + +Allows a user to specify commands to run after the device is up or down. This is +typcially a collection of `iptables` invocations. The commands are executed by +`/bin/sh`. *NOTE* These commands run as root, so make sure you check that they +are secure. + "PrivateKey": "uC+xz3v1mfjWBHepwiCgAmPebZcY+EdhaHAvqX2r7U8=", The server private key, automatically generated and very sensitive! diff --git a/README.md b/README.md index 273d4d8..9b2952d 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,8 @@ Main (automatically generated) configuration example: "Networks": [], "ReportFile": "/var/lib/dsnetreport.json", "PrivateKey": "uC+xz3v1mfjWBHepwiCgAmPebZcY+EdhaHAvqX2r7U8=", + "PostUp": "", + "PostDown" "", "Peers": [ { "Hostname": "test", diff --git a/add.go b/add.go index 3a0a56d..548a90b 100644 --- a/add.go +++ b/add.go @@ -151,7 +151,6 @@ func PrintPeerCfg(peer PeerConfig, conf *DsnetConfig) { wgifSeed += int(b) } - t := template.Must(template.New("peerConf").Parse(peerConf)) err := t.Execute(os.Stdout, map[string]interface{}{ "Peer": peer, @@ -162,7 +161,7 @@ func PrintPeerCfg(peer PeerConfig, conf *DsnetConfig) { // vyatta requires an interface in range/format wg0-wg999 // deterministically choosing one in this range will probably allow use // of the config without a colliding interface name - "Wgif": fmt.Sprintf("wg%d", wgifSeed % 999), + "Wgif": fmt.Sprintf("wg%d", wgifSeed%999), }) check(err) } diff --git a/configtypes.go b/configtypes.go index 2e88658..7a72022 100644 --- a/configtypes.go +++ b/configtypes.go @@ -51,9 +51,11 @@ type DsnetConfig struct { // extra networks available, will be added to AllowedIPs Networks []JSONIPNet `validate:"required"` // TODO Default subnets to route via VPN - ReportFile string `validate:"required"` - PrivateKey JSONKey `validate:"required,len=44"` - Peers []PeerConfig `validate:"dive"` + ReportFile string `validate:"required"` + PrivateKey JSONKey `validate:"required,len=44"` + PostUp string + PostDown string + Peers []PeerConfig `validate:"dive"` } func MustLoadDsnetConfig() *DsnetConfig { diff --git a/down.go b/down.go index db82332..3103347 100644 --- a/down.go +++ b/down.go @@ -7,6 +7,11 @@ import ( func Down() { conf := MustLoadDsnetConfig() DelLink(conf) + RunPostDown(conf) +} + +func RunPostDown(conf *DsnetConfig) { + ShellOut(conf.PostDown, "PostDown") } func DelLink(conf *DsnetConfig) { diff --git a/reporttypes.go b/reporttypes.go index c3c12f2..63af1f5 100644 --- a/reporttypes.go +++ b/reporttypes.go @@ -163,7 +163,7 @@ type PeerReport struct { // date peer was added to dsnet config Added time.Time // Internal VPN IP address. Added to AllowedIPs in server config as a /32 - IP net.IP + IP net.IP IP6 net.IP // Last known external IP ExternalIP net.IP diff --git a/up.go b/up.go index 89ad419..3988197 100644 --- a/up.go +++ b/up.go @@ -10,6 +10,11 @@ func Up() { conf := MustLoadDsnetConfig() CreateLink(conf) ConfigureDevice(conf) + RunPostUp(conf) +} + +func RunPostUp(conf *DsnetConfig) { + ShellOut(conf.PostUp, "PostUp") } func CreateLink(conf *DsnetConfig) { diff --git a/util.go b/util.go index 3f8d3e8..a6b021a 100644 --- a/util.go +++ b/util.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "os" + "os/exec" "strings" ) @@ -35,6 +36,17 @@ func ExitFail(format string, a ...interface{}) { os.Exit(1) } +func ShellOut(command string, name string) { + if command != "" { + fmt.Printf("Running %s commands:\n %s", name, command) + shell := exec.Command("/bin/sh", "-c", command) + err := shell.Run() + if err != nil { + ExitFail("%s '%s' failed", name, command, err) + } + } +} + func ConfirmOrAbort(format string, a ...interface{}) { fmt.Fprintf(os.Stderr, format+" [y/n] ", a...)