From 516e820ab7886823e965bc2322f2bc51f37bbec5 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Thu, 11 Aug 2022 16:27:18 -0500 Subject: [PATCH 01/10] Adds ability to user-supplied private keys. --- cmd/cli/add.go | 8 ++++++-- cmd/root.go | 12 +++++++++--- lib/peer.go | 16 ++++++++++++---- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/cmd/cli/add.go b/cmd/cli/add.go index d922844..55ad7a9 100644 --- a/cmd/cli/add.go +++ b/cmd/cli/add.go @@ -9,12 +9,16 @@ import ( ) // Add prompts for the required information and creates a new peer -func Add(hostname, owner, description string, confirm bool) { +func Add(hostname string, readKey bool, owner, description string, confirm bool) { // TODO accept existing pubkey config, err := LoadConfigFile() check(err, "failed to load configuration file") server := GetServer(config) + var key string + if readKey { + key = MustPromptString("private key", true) + } if owner == "" { owner = MustPromptString("owner", true) } @@ -30,7 +34,7 @@ func Add(hostname, owner, description string, confirm bool) { // newline (not on stdout) to separate config fmt.Fprintln(os.Stderr) - peer, err := lib.NewPeer(server, owner, hostname, description) + peer, err := lib.NewPeer(server, key, owner, hostname, description) check(err, "failed to get new peer") // TODO Some kind of recovery here would be nice, to avoid diff --git a/cmd/root.go b/cmd/root.go index 528d2ec..4fd4705 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -56,8 +56,8 @@ var ( } addCmd = &cobra.Command{ - Use: "add [hostname]", - Short: "Add a new peer + sync", + Use: "add ", + Short: "Add a new peer + sync, optionally using a provided WireGuard private key", PreRunE: func(cmd *cobra.Command, args []string) error { // Make sure we have the hostname if len(args) != 1 { @@ -66,7 +66,11 @@ var ( return nil }, Run: func(cmd *cobra.Command, args []string) { - cli.Add(args[0], owner, description, confirm) + userKey, err := cmd.PersistentFlags().GetBool("key") + if err != nil { + cli.ExitFail("%w - error processing key flag", err) + } + cli.Add(args[0], userKey, owner, description, confirm) }, } @@ -123,6 +127,7 @@ var ( Use: "version", Short: "Print version", } + ) func init() { @@ -131,6 +136,7 @@ func init() { addCmd.Flags().StringVar(&owner, "owner", "", "owner of the new peer") addCmd.Flags().StringVar(&description, "description", "", "description of the new peer") addCmd.Flags().BoolVar(&confirm, "confirm", false, "confirm") + addCmd.PersistentFlags().BoolP("key", "k", false, "User-supplied key on stdin") removeCmd.Flags().BoolVar(&confirm, "confirm", false, "confirm") // Environment variable handling. diff --git a/lib/peer.go b/lib/peer.go index f17a56c..f7710d0 100644 --- a/lib/peer.go +++ b/lib/peer.go @@ -37,7 +37,7 @@ type Peer struct { KeepAlive time.Duration } -func NewPeer(server *Server, owner string, hostname string, description string) (Peer, error) { +func NewPeer(server *Server, key, owner, hostname, description string) (Peer, error) { if owner == "" { return Peer{}, errors.New("missing owner") } @@ -45,9 +45,17 @@ func NewPeer(server *Server, owner string, hostname string, description string) return Peer{}, errors.New("missing hostname") } - privateKey, err := GenerateJSONPrivateKey() - if err != nil { - return Peer{}, fmt.Errorf("failed to generate private key: %s", err) + var privateKey JSONKey + if key != "" { + userKey := &JSONKey{} + userKey.UnmarshalJSON([]byte(key)) + privateKey = *userKey + } else { + var err error + privateKey, err = GenerateJSONPrivateKey() + if err != nil { + return Peer{}, fmt.Errorf("failed to generate private key: %s", err) + } } publicKey := privateKey.PublicKey() From e02790b24abc6cb02bfbdcca5ea2974b4520a8df Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 12 Aug 2022 11:43:54 -0500 Subject: [PATCH 02/10] Remove spurious newline. --- cmd/root.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/root.go b/cmd/root.go index 4fd4705..ed9e6bf 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -127,7 +127,6 @@ var ( Use: "version", Short: "Print version", } - ) func init() { From 9cd98ff65451e7ada751b2341142f6e8f403ddff Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 12 Aug 2022 14:09:36 -0500 Subject: [PATCH 03/10] Implements code comment to-do as well: allow user to provide public key. --- cmd/cli/add.go | 14 ++++++++------ cmd/root.go | 8 +++++--- lib/peer.go | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/cmd/cli/add.go b/cmd/cli/add.go index 55ad7a9..cba5fa4 100644 --- a/cmd/cli/add.go +++ b/cmd/cli/add.go @@ -9,15 +9,17 @@ import ( ) // Add prompts for the required information and creates a new peer -func Add(hostname string, readKey bool, owner, description string, confirm bool) { - // TODO accept existing pubkey +func Add(hostname string, privKey, pubKey bool, owner, description string, confirm bool) { config, err := LoadConfigFile() check(err, "failed to load configuration file") server := GetServer(config) - var key string - if readKey { - key = MustPromptString("private key", true) + var private, public string + if privKey { + private = MustPromptString("private key", true) + } + if pubKey { + public = MustPromptString("public key", true) } if owner == "" { owner = MustPromptString("owner", true) @@ -34,7 +36,7 @@ func Add(hostname string, readKey bool, owner, description string, confirm bool) // newline (not on stdout) to separate config fmt.Fprintln(os.Stderr) - peer, err := lib.NewPeer(server, key, owner, hostname, description) + peer, err := lib.NewPeer(server, private, public, owner, hostname, description) check(err, "failed to get new peer") // TODO Some kind of recovery here would be nice, to avoid diff --git a/cmd/root.go b/cmd/root.go index ed9e6bf..126c9c3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -66,11 +66,12 @@ var ( return nil }, Run: func(cmd *cobra.Command, args []string) { - userKey, err := cmd.PersistentFlags().GetBool("key") + privKey, err := cmd.PersistentFlags().GetBool("private-key") + pubKey, err := cmd.PersistentFlags().GetBool("public-key") if err != nil { cli.ExitFail("%w - error processing key flag", err) } - cli.Add(args[0], userKey, owner, description, confirm) + cli.Add(args[0], privKey, pubKey, owner, description, confirm) }, } @@ -135,7 +136,8 @@ func init() { addCmd.Flags().StringVar(&owner, "owner", "", "owner of the new peer") addCmd.Flags().StringVar(&description, "description", "", "description of the new peer") addCmd.Flags().BoolVar(&confirm, "confirm", false, "confirm") - addCmd.PersistentFlags().BoolP("key", "k", false, "User-supplied key on stdin") + addCmd.PersistentFlags().BoolP("private-key", "r", false, "Accept user-supplied private key. If supplied, dsnet will generate a public key.") + addCmd.PersistentFlags().BoolP("public-key", "u", false, "Accept user-supplied public key. If supplied, the user must add the private key to the generated config (or provide it with --private-key).") removeCmd.Flags().BoolVar(&confirm, "confirm", false, "confirm") // Environment variable handling. diff --git a/lib/peer.go b/lib/peer.go index f7710d0..9d324ea 100644 --- a/lib/peer.go +++ b/lib/peer.go @@ -4,7 +4,11 @@ import ( "errors" "fmt" "net" + "os" + "strings" "time" + + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // PeerType is what configuration to use when generating @@ -37,7 +41,15 @@ type Peer struct { KeepAlive time.Duration } -func NewPeer(server *Server, key, owner, hostname, description string) (Peer, error) { +// NewPeer generates a peer from the supplied arguments and generates keys if needed. +// - server is required and provides network information +// - private is a base64-encoded private key; if the empty string, a new key will be generated +// - public is a base64-encoded public key. If empty, it will be generated from the private key. +// If **not** empty, the private key will be included IFF a private key was provided. +// - owner is the owner name (required) +// - hostname is the name of the peer (required) +// - description is the annotation for the peer +func NewPeer(server *Server, private, public, owner, hostname, description string) (Peer, error) { if owner == "" { return Peer{}, errors.New("missing owner") } @@ -46,9 +58,9 @@ func NewPeer(server *Server, key, owner, hostname, description string) (Peer, er } var privateKey JSONKey - if key != "" { + if private != "" { userKey := &JSONKey{} - userKey.UnmarshalJSON([]byte(key)) + userKey.UnmarshalJSON([]byte(private)) privateKey = *userKey } else { var err error @@ -57,7 +69,21 @@ func NewPeer(server *Server, key, owner, hostname, description string) (Peer, er return Peer{}, fmt.Errorf("failed to generate private key: %s", err) } } - publicKey := privateKey.PublicKey() + + var publicKey JSONKey + if public != "" { + b64Key := strings.Trim(string(public), "\"") + key, err := wgtypes.ParseKey(b64Key) + if err != nil { + return Peer{}, err + } + publicKey = JSONKey { Key: key } + if private == "" { + privateKey = JSONKey { Key: wgtypes.Key([wgtypes.KeyLen]byte{}) } + } + } else { + publicKey = privateKey.PublicKey() + } presharedKey, err := GenerateJSONKey() if err != nil { @@ -74,6 +100,8 @@ func NewPeer(server *Server, key, owner, hostname, description string) (Peer, er PresharedKey: presharedKey, Networks: []JSONIPNet{}, } +fmt.Fprintf(os.Stderr, "peer public key => %s\n", newPeer.PublicKey) +fmt.Fprintf(os.Stderr, "peer Private key => %s\n", newPeer.PrivateKey) if len(server.Network.IPNet.Mask) > 0 { newIP, err := server.AllocateIP() From f0180df5e4ef64ea4235b3150767f6348ee9db98 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 12 Aug 2022 14:26:00 -0500 Subject: [PATCH 04/10] Adds key validation for user data --- lib/peer.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/peer.go b/lib/peer.go index 9d324ea..9311270 100644 --- a/lib/peer.go +++ b/lib/peer.go @@ -80,6 +80,12 @@ func NewPeer(server *Server, private, public, owner, hostname, description strin publicKey = JSONKey { Key: key } if private == "" { privateKey = JSONKey { Key: wgtypes.Key([wgtypes.KeyLen]byte{}) } + } else { + pubK := privateKey.PublicKey() + ascK := pubK.Key.String() + if ascK != public { + return Peer{}, fmt.Errorf("user-supplied private and public keys are not related") + } } } else { publicKey = privateKey.PublicKey() From ee0d0712283dfd00ec9851ce03c7fac184da1612 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 2 Sep 2022 09:18:30 -0500 Subject: [PATCH 05/10] Remove trace code --- lib/peer.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/peer.go b/lib/peer.go index 9311270..dba5ecc 100644 --- a/lib/peer.go +++ b/lib/peer.go @@ -42,13 +42,13 @@ type Peer struct { } // NewPeer generates a peer from the supplied arguments and generates keys if needed. -// - server is required and provides network information -// - private is a base64-encoded private key; if the empty string, a new key will be generated -// - public is a base64-encoded public key. If empty, it will be generated from the private key. -// If **not** empty, the private key will be included IFF a private key was provided. -// - owner is the owner name (required) -// - hostname is the name of the peer (required) -// - description is the annotation for the peer +// - server is required and provides network information +// - private is a base64-encoded private key; if the empty string, a new key will be generated +// - public is a base64-encoded public key. If empty, it will be generated from the private key. +// If **not** empty, the private key will be included IFF a private key was provided. +// - owner is the owner name (required) +// - hostname is the name of the peer (required) +// - description is the annotation for the peer func NewPeer(server *Server, private, public, owner, hostname, description string) (Peer, error) { if owner == "" { return Peer{}, errors.New("missing owner") @@ -77,9 +77,9 @@ func NewPeer(server *Server, private, public, owner, hostname, description strin if err != nil { return Peer{}, err } - publicKey = JSONKey { Key: key } + publicKey = JSONKey{Key: key} if private == "" { - privateKey = JSONKey { Key: wgtypes.Key([wgtypes.KeyLen]byte{}) } + privateKey = JSONKey{Key: wgtypes.Key([wgtypes.KeyLen]byte{})} } else { pubK := privateKey.PublicKey() ascK := pubK.Key.String() @@ -106,8 +106,6 @@ func NewPeer(server *Server, private, public, owner, hostname, description strin PresharedKey: presharedKey, Networks: []JSONIPNet{}, } -fmt.Fprintf(os.Stderr, "peer public key => %s\n", newPeer.PublicKey) -fmt.Fprintf(os.Stderr, "peer Private key => %s\n", newPeer.PrivateKey) if len(server.Network.IPNet.Mask) > 0 { newIP, err := server.AllocateIP() From cfcea9e62415220864f15912f3eded60978973f7 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 4 Nov 2022 08:59:40 -0500 Subject: [PATCH 06/10] The merge keeps missing this, and I didn't catch it this time. --- lib/peer.go | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/peer.go b/lib/peer.go index 9522b6c..8935a1d 100644 --- a/lib/peer.go +++ b/lib/peer.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "net" - "os" "strings" "time" From 40b2766181c7a21fa2b2dd63e2cb242695de7526 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 4 Nov 2022 09:35:20 -0500 Subject: [PATCH 07/10] Adds a code snippet for rending a nice table from the report in a CLI --- contrib/report_rendering/README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/contrib/report_rendering/README.md b/contrib/report_rendering/README.md index 1cbdcea..c455d00 100644 --- a/contrib/report_rendering/README.md +++ b/contrib/report_rendering/README.md @@ -31,3 +31,33 @@ Courtesy of [@frillip](https://github.com/frillip/) ![dsnet report table](https://raw.githubusercontent.com/naggie/dsnet/master/etc/dsnet-report-js.png) +On the command line, you can use [jtbl](https://github.com/kellyjonbrazil/jtbl) (and [jq](https://stedolan.github.io/jq/)) for a nice table rendering with this snippet: + +```bash +sudo dsnet report | jq '.Peers' | jtbl +``` + +The output looks like: +``` +╒═════════╤═══════╤══════════╤══════════╤══════════╤══════════╤═════════╤════════╤══════════╤══════════╤══════════╤══════════╤══════════╤══════════╤══════════╕ +│ Owner │ IP6 │ Hostna │ Descri │ Online │ Dorman │ Added │ IP │ Extern │ Networ │ LastHa │ Receiv │ Transm │ Receiv │ Transm │ +│ │ │ me │ ption │ │ t │ │ │ alIP │ ks │ ndshak │ eBytes │ itByte │ eBytes │ itByte │ +│ │ │ │ │ │ │ │ │ │ │ eTime │ │ s │ SI │ sSI │ +╞═════════╪═══════╪══════════╪══════════╪══════════╪══════════╪═════════╪════════╪══════════╪══════════╪══════════╪══════════╪══════════╪══════════╪══════════╡ +│ xyz │ │ eaetl │ eaetl. │ True │ False │ 2222-0 │ 99.99. │ dddd:d │ [] │ 1111-1 │ 175995 │ 447007 │ 175.9 │ 32.7 M │ +│ │ │ │ fooo │ │ │ 2-22T1 │ 99.9 │ dd:ddd │ │ 1-11T1 │ 424 │ 28 │ MB │ B │ +│ │ │ │ │ │ │ 2:22:5 │ │ d:dddd │ │ 1:11:1 │ │ │ │ │ +│ │ │ │ │ │ │ 2.2274 │ │ :dddd: │ │ 1.1111 │ │ │ │ │ +│ │ │ │ │ │ │ 22222- │ │ dddd:d │ │ 11111- │ │ │ │ │ +│ │ │ │ │ │ │ 22:20 │ │ ddd:dd │ │ 11:11 │ │ │ │ │ +│ │ │ │ │ │ │ │ │ dd │ │ │ │ │ │ │ +├─────────┼───────┼──────────┼──────────┼──────────┼──────────┼─────────┼────────┼──────────┼──────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ +│ xyz │ │ ammedu │ ammedu │ True │ False │ 2222-0 │ 88.88. │ eeee:e │ [] │ 1111-1 │ 751670 │ 759741 │ 6.7 GB │ 727.7 │ +│ │ │ │ .mymy. │ │ │ 2-22T1 │ 88.8 │ eee:ee │ │ 1-11T1 │ 2852 │ 076 │ │ MB │ +│ │ │ │ com │ │ │ 2:22:4 │ │ ee:eee │ │ 1:11:1 │ │ │ │ │ +│ │ │ │ │ │ │ 2.2292 │ │ e::e │ │ 1.1111 │ │ │ │ │ +│ │ │ │ │ │ │ 22226- │ │ │ │ 11111- │ │ │ │ │ +│ │ │ │ │ │ │ 22:20 │ │ │ │ 11:11 │ │ │ │ │ +├─────────┼───────┼──────────┼──────────┼──────────┼──────────┼─────────┼────────┼──────────┼──────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ +... +``` \ No newline at end of file From 8c7b1df3427bd399043590e10497692e31d8371d Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 4 Nov 2022 09:41:37 -0500 Subject: [PATCH 08/10] Adds a big header like the other sections. --- contrib/report_rendering/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/report_rendering/README.md b/contrib/report_rendering/README.md index c455d00..9cbf6a5 100644 --- a/contrib/report_rendering/README.md +++ b/contrib/report_rendering/README.md @@ -31,6 +31,8 @@ Courtesy of [@frillip](https://github.com/frillip/) ![dsnet report table](https://raw.githubusercontent.com/naggie/dsnet/master/etc/dsnet-report-js.png) +# CLI (bash) + On the command line, you can use [jtbl](https://github.com/kellyjonbrazil/jtbl) (and [jq](https://stedolan.github.io/jq/)) for a nice table rendering with this snippet: ```bash From 21d70477d5f017436a4ba4ef5fee55afcd45203d Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 4 Nov 2022 09:46:25 -0500 Subject: [PATCH 09/10] Add a little more color, for possibilities. --- contrib/report_rendering/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrib/report_rendering/README.md b/contrib/report_rendering/README.md index 9cbf6a5..e3c1aa6 100644 --- a/contrib/report_rendering/README.md +++ b/contrib/report_rendering/README.md @@ -62,4 +62,10 @@ The output looks like: │ │ │ │ │ │ │ 22:20 │ │ │ │ 11:11 │ │ │ │ │ ├─────────┼───────┼──────────┼──────────┼──────────┼──────────┼─────────┼────────┼──────────┼──────────┼──────────┼──────────┼──────────┼──────────┼──────────┤ ... +``` + +To tighten up the table, use JQ to remove columns you're not interested in: + +``` +sudo dsnet report | jq '.Peers | map(del(.Added,.Networks,.IP6,.Owner))' | jtbl ``` \ No newline at end of file From a0a7ed24fcaa37235bc2de905584d563f67397c7 Mon Sep 17 00:00:00 2001 From: Arti Zirk Date: Mon, 23 Oct 2023 16:47:47 +0300 Subject: [PATCH 10/10] Add support for MikroTik RouterOS config generation --- README.md | 22 +++++++++++++++++++++- lib/generator.go | 4 ++++ lib/peer.go | 3 +++ lib/templates.go | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 38e4559..318c4c8 100644 --- a/README.md +++ b/README.md @@ -209,13 +209,15 @@ default. It can also generate VyOS/Vyatta configuration for EdgeOS/Unifi devices such as the Edgerouter 4 using the [wireguard-vyatta](https://github.com/WireGuard/wireguard-vyatta-ubnt) package, as well as configuration for [NixOS](https://nixos.org), ready to be added to -`configuration.nix` environment definition. +`configuration.nix` environment definition. [MikroTik RouterOS](https://mikrotik.com/software) +support is also available. To change the config file format, set the following environment variables: * `DSNET_OUTPUT=vyatta` * `DSNET_OUTPUT=wg-quick` * `DSNET_OUTPUT=nixos` +* `DSNET_OUTPUT=routeros` Example vyatta output: @@ -263,6 +265,24 @@ Example NixOS output: }; }; +Example MikroTik RouterOS output: + + /interface wireguard + add name=wg0 private-key="CDWdi0IcMZgla1hCYI41JejjuFaPCle+vPBxvX5OvVE="; + /interface list member + add interface=wg0 list=LAN + /ip address + add address=10.55.148.2/22 interface=wg0 + /ipv6 address + add address=fd00:1965:946d:5000:5a88:878d:dc0:c777/64 advertise=no eui-64=no no-dad=no interface=wg0 + /interface wireguard peers + add interface=wg0 \ + public-key="iE7dleTu34JOCC4A8xdIZcnbNE+aoji8i1JpP+gdt0M=" \ + preshared-key="Ch0BdZ6Um29D34awlWBSNa+cz1wGOUuHshjYIyqKxGU=" \ + endpoint-address=198.51.100.73 \ + endpoint-port=51820 \ + persistent-keepalive=25s \ + allowed-address=10.55.148.0/22,fd00:1965:946d:5000::/64,192.168.10.0/24,fe80::1/64 # FAQ diff --git a/lib/generator.go b/lib/generator.go index bc35289..1d8e6f2 100644 --- a/lib/generator.go +++ b/lib/generator.go @@ -15,6 +15,8 @@ func getPeerConfTplString(peerType PeerType) (string, error) { return vyattaPeerConf, nil case NixOS: return nixosPeerConf, nil + case RouterOS: + return routerosPeerConf, nil default: return "", fmt.Errorf("unrecognized peer type") } @@ -84,6 +86,8 @@ func AsciiPeerConfig(peer Peer, peerType string, server Server) (*bytes.Buffer, return GetWGPeerTemplate(peer, Vyatta, server) case "nixos": return GetWGPeerTemplate(peer, NixOS, server) + case "routeros": + return GetWGPeerTemplate(peer, RouterOS, server) default: return nil, errors.New("unrecognised OUTPUT type") } diff --git a/lib/peer.go b/lib/peer.go index e522416..c577837 100644 --- a/lib/peer.go +++ b/lib/peer.go @@ -21,6 +21,9 @@ const ( // NixOS is a declartive linux distro // https://nixos.wiki/wiki/Wireguard NixOS + // RouterOS is proprietary Linux based OS by MikroTik + // https://help.mikrotik.com/docs/display/ROS/WireGuard + RouterOS ) type Peer struct { diff --git a/lib/templates.go b/lib/templates.go index 5e7a3e9..bac9f07 100644 --- a/lib/templates.go +++ b/lib/templates.go @@ -90,3 +90,39 @@ const nixosPeerConf = `networking.wireguard.interfaces = {{ "{" }} {{ "};" }} {{ "};" }} ` + +const routerosPeerConf = `/interface wireguard +add name=wg0 private-key="{{ .Peer.PrivateKey.Key }}"; +/interface list member +add interface=wg0 list=LAN +/ip address +{{ if gt (.Server.Network.IPNet.IP | len) 0 -}} +add address={{ .Peer.IP }}/{{ .CidrSize }} interface=wg0 +{{ end -}} +/ipv6 address +{{ if gt (.Server.Network6.IPNet.IP | len) 0 -}} +add address={{ .Peer.IP6 }}/{{ .CidrSize6 }} advertise=no interface=wg0 +{{ end -}} +/interface wireguard peers +{{/* MikroTik RouterOS does not like trailing commas in arrays */ -}} +{{ $first := true -}} +add interface=wg0 \ + public-key="{{ .Server.PrivateKey.PublicKey.Key }}" \ + preshared-key="{{ .Peer.PresharedKey.Key }}" \ + endpoint-address={{ .Endpoint }} \ + endpoint-port={{ .Server.ListenPort }} \ + persistent-keepalive={{ .Server.PersistentKeepalive }}s \ + allowed-address= + {{- if gt (.Server.Network.IPNet.IP | len) 0 }} + {{- if $first}}{{$first = false}}{{else}},{{end}} + {{- .Server.Network.IPNet.IP }}/{{ .CidrSize }} + {{- end }} + {{- if gt (.Server.Network6.IPNet.IP | len) 0 }} + {{- if $first}}{{$first = false}}{{else}},{{end}} + {{- .Server.Network6.IPNet.IP }}/{{ .CidrSize6 }} + {{- end }} + {{- range .Server.Networks }} + {{- if $first}}{{$first = false}}{{else}},{{end}} + {{- . }} + {{- end }} +`