migrate to golang.zx2c4.com/wireguard/wgctrl (#239)
* migrate to golang.zx2c4.com/wireguard/wgctrl This commit introduces the usage of wgctrl. It avoids the usage of exec calls of the wg command and parsing the output of `wg show`. Signed-off-by: leonnicolas <leonloechner@gmx.de> * vendor wgctrl Signed-off-by: leonnicolas <leonloechner@gmx.de> * apply suggestions from code review Remove wireguard.Enpoint struct and use net.UDPAddr for the resolved endpoint and addr string (dnsanme:port) if a DN was supplied. Signed-off-by: leonnicolas <leonloechner@gmx.de> * pkg/*: use wireguard.Enpoint This commit introduces the wireguard.Enpoint struct. It encapsulates a DN name with port and a net.UPDAddr. The fields are private and only accessible over exported Methods to avoid accidental modification. Also iptables.GetProtocol is improved to avoid ipv4 rules being applied by `ip6tables`. Signed-off-by: leonnicolas <leonloechner@gmx.de> * pkg/wireguard/conf_test.go: add tests for Endpoint Signed-off-by: leonnicolas <leonloechner@gmx.de> * cmd/kg/main.go: validate port range Signed-off-by: leonnicolas <leonloechner@gmx.de> * add suggestions from review Signed-off-by: leonnicolas <leonloechner@gmx.de> * pkg/mesh/mesh.go: use Equal func Implement an Equal func for Enpoint and use it instead of comparing strings. Signed-off-by: leonnicolas <leonloechner@gmx.de> * cmd/kgctl/main.go: check port range Signed-off-by: leonnicolas <leonloechner@gmx.de> * vendor Signed-off-by: leonnicolas <leonloechner@gmx.de>
This commit is contained in:
		| @@ -18,6 +18,8 @@ import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/spf13/cobra" | ||||
| 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes" | ||||
|  | ||||
| 	"github.com/squat/kilo/pkg/mesh" | ||||
| ) | ||||
|  | ||||
| @@ -65,7 +67,7 @@ func runGraph(_ *cobra.Command, _ []string) error { | ||||
| 			peers[p.Name] = p | ||||
| 		} | ||||
| 	} | ||||
| 	t, err := mesh.NewTopology(nodes, peers, opts.granularity, hostname, 0, []byte{}, subnet, nodes[hostname].PersistentKeepalive, nil) | ||||
| 	t, err := mesh.NewTopology(nodes, peers, opts.granularity, hostname, 0, wgtypes.Key{}, subnet, nodes[hostname].PersistentKeepalive, nil) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create topology: %v", err) | ||||
| 	} | ||||
|   | ||||
| @@ -21,6 +21,7 @@ import ( | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/go-kit/kit/log" | ||||
| 	"github.com/spf13/cobra" | ||||
| 	apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" | ||||
| 	"k8s.io/client-go/kubernetes" | ||||
| @@ -61,7 +62,7 @@ var ( | ||||
| 	opts struct { | ||||
| 		backend     mesh.Backend | ||||
| 		granularity mesh.Granularity | ||||
| 		port        uint32 | ||||
| 		port        int | ||||
| 	} | ||||
| 	backend       string | ||||
| 	granularity   string | ||||
| @@ -70,6 +71,10 @@ var ( | ||||
| ) | ||||
|  | ||||
| func runRoot(_ *cobra.Command, _ []string) error { | ||||
| 	if opts.port < 1 || opts.port > 1<<16-1 { | ||||
| 		return fmt.Errorf("invalid port: port mus be in range [%d:%d], but got %d", 1, 1<<16-1, opts.port) | ||||
| 	} | ||||
|  | ||||
| 	opts.granularity = mesh.Granularity(granularity) | ||||
| 	switch opts.granularity { | ||||
| 	case mesh.LogicalGranularity: | ||||
| @@ -88,7 +93,7 @@ func runRoot(_ *cobra.Command, _ []string) error { | ||||
| 		c := kubernetes.NewForConfigOrDie(config) | ||||
| 		kc := kiloclient.NewForConfigOrDie(config) | ||||
| 		ec := apiextensions.NewForConfigOrDie(config) | ||||
| 		opts.backend = k8s.New(c, kc, ec, topologyLabel) | ||||
| 		opts.backend = k8s.New(c, kc, ec, topologyLabel, log.NewNopLogger()) | ||||
| 	default: | ||||
| 		return fmt.Errorf("backend %v unknown; posible values are: %s", backend, availableBackends) | ||||
| 	} | ||||
| @@ -119,7 +124,7 @@ func main() { | ||||
| 		defaultKubeconfig = filepath.Join(os.Getenv("HOME"), ".kube/config") | ||||
| 	} | ||||
| 	cmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", defaultKubeconfig, "Path to kubeconfig.") | ||||
| 	cmd.PersistentFlags().Uint32Var(&opts.port, "port", mesh.DefaultKiloPort, "The WireGuard port over which the nodes communicate.") | ||||
| 	cmd.PersistentFlags().IntVar(&opts.port, "port", mesh.DefaultKiloPort, "The WireGuard port over which the nodes communicate.") | ||||
| 	cmd.PersistentFlags().StringVar(&topologyLabel, "topology-label", k8s.RegionLabelKey, "Kubernetes node label used to group nodes into logical locations.") | ||||
|  | ||||
| 	for _, subCmd := range []*cobra.Command{ | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| // Copyright 2019 the Kilo authors | ||||
| // Copyright 2021 the Kilo authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| @@ -15,14 +15,15 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/spf13/cobra" | ||||
| 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| @@ -47,7 +48,7 @@ var ( | ||||
| 	}, ", ") | ||||
| 	allowedIPs   []string | ||||
| 	showConfOpts struct { | ||||
| 		allowedIPs []*net.IPNet | ||||
| 		allowedIPs []net.IPNet | ||||
| 		serializer *json.Serializer | ||||
| 		output     string | ||||
| 		asPeer     bool | ||||
| @@ -89,7 +90,7 @@ func runShowConf(c *cobra.Command, args []string) error { | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("allowed-ips must contain only valid CIDRs; got %q", allowedIPs[i]) | ||||
| 		} | ||||
| 		showConfOpts.allowedIPs = append(showConfOpts.allowedIPs, aip) | ||||
| 		showConfOpts.allowedIPs = append(showConfOpts.allowedIPs, *aip) | ||||
| 	} | ||||
| 	return runRoot(c, args) | ||||
| } | ||||
| @@ -151,14 +152,14 @@ func runShowConfNode(_ *cobra.Command, args []string) error { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	t, err := mesh.NewTopology(nodes, peers, opts.granularity, hostname, opts.port, []byte{}, subnet, nodes[hostname].PersistentKeepalive, nil) | ||||
| 	t, err := mesh.NewTopology(nodes, peers, opts.granularity, hostname, int(opts.port), wgtypes.Key{}, subnet, nodes[hostname].PersistentKeepalive, nil) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create topology: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	var found bool | ||||
| 	for _, p := range t.PeerConf("").Peers { | ||||
| 		if bytes.Equal(p.PublicKey, nodes[hostname].Key) { | ||||
| 		if p.PublicKey == nodes[hostname].Key { | ||||
| 			found = true | ||||
| 			break | ||||
| 		} | ||||
| @@ -182,6 +183,9 @@ func runShowConfNode(_ *cobra.Command, args []string) error { | ||||
| 		fallthrough | ||||
| 	case outputFormatYAML: | ||||
| 		p := t.AsPeer() | ||||
| 		if p == nil { | ||||
| 			return errors.New("cannot generate config from nil peer") | ||||
| 		} | ||||
| 		p.AllowedIPs = append(p.AllowedIPs, showConfOpts.allowedIPs...) | ||||
| 		p.DeduplicateIPs() | ||||
| 		k8sp := translatePeer(p) | ||||
| @@ -189,10 +193,13 @@ func runShowConfNode(_ *cobra.Command, args []string) error { | ||||
| 		return showConfOpts.serializer.Encode(k8sp, os.Stdout) | ||||
| 	case outputFormatWireGuard: | ||||
| 		p := t.AsPeer() | ||||
| 		if p == nil { | ||||
| 			return errors.New("cannot generate config from nil peer") | ||||
| 		} | ||||
| 		p.AllowedIPs = append(p.AllowedIPs, showConfOpts.allowedIPs...) | ||||
| 		p.DeduplicateIPs() | ||||
| 		c, err := (&wireguard.Conf{ | ||||
| 			Peers: []*wireguard.Peer{p}, | ||||
| 			Peers: []wireguard.Peer{*p}, | ||||
| 		}).Bytes() | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to generate configuration: %v", err) | ||||
| @@ -244,7 +251,11 @@ func runShowConfPeer(_ *cobra.Command, args []string) error { | ||||
| 		return fmt.Errorf("did not find any peer named %q in the cluster", peer) | ||||
| 	} | ||||
|  | ||||
| 	t, err := mesh.NewTopology(nodes, peers, opts.granularity, hostname, mesh.DefaultKiloPort, []byte{}, subnet, peers[peer].PersistentKeepalive, nil) | ||||
| 	pka := time.Duration(0) | ||||
| 	if p := peers[peer].PersistentKeepaliveInterval; p != nil { | ||||
| 		pka = *p | ||||
| 	} | ||||
| 	t, err := mesh.NewTopology(nodes, peers, opts.granularity, hostname, mesh.DefaultKiloPort, wgtypes.Key{}, subnet, pka, nil) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create topology: %v", err) | ||||
| 	} | ||||
| @@ -272,7 +283,7 @@ func runShowConfPeer(_ *cobra.Command, args []string) error { | ||||
| 		p.AllowedIPs = append(p.AllowedIPs, showConfOpts.allowedIPs...) | ||||
| 		p.DeduplicateIPs() | ||||
| 		c, err := (&wireguard.Conf{ | ||||
| 			Peers: []*wireguard.Peer{p}, | ||||
| 			Peers: []wireguard.Peer{*p}, | ||||
| 		}).Bytes() | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to generate configuration: %v", err) | ||||
| @@ -284,6 +295,7 @@ func runShowConfPeer(_ *cobra.Command, args []string) error { | ||||
| } | ||||
|  | ||||
| // translatePeer translates a wireguard.Peer to a Peer CRD. | ||||
| // TODO this function has many similarities to peerBackend.Set(name, peer) | ||||
| func translatePeer(peer *wireguard.Peer) *v1alpha1.Peer { | ||||
| 	if peer == nil { | ||||
| 		return &v1alpha1.Peer{} | ||||
| @@ -291,36 +303,33 @@ func translatePeer(peer *wireguard.Peer) *v1alpha1.Peer { | ||||
| 	var aips []string | ||||
| 	for _, aip := range peer.AllowedIPs { | ||||
| 		// Skip any invalid IPs. | ||||
| 		if aip == nil { | ||||
| 		// TODO all IPs should be valid, so no need to skip here? | ||||
| 		if aip.String() == (&net.IPNet{}).String() { | ||||
| 			continue | ||||
| 		} | ||||
| 		aips = append(aips, aip.String()) | ||||
| 	} | ||||
| 	var endpoint *v1alpha1.PeerEndpoint | ||||
| 	if peer.Endpoint != nil && peer.Endpoint.Port > 0 && (peer.Endpoint.IP != nil || peer.Endpoint.DNS != "") { | ||||
| 		var ip string | ||||
| 		if peer.Endpoint.IP != nil { | ||||
| 			ip = peer.Endpoint.IP.String() | ||||
| 		} | ||||
| 	if peer.Endpoint.Port() > 0 || !peer.Endpoint.HasDNS() { | ||||
| 		endpoint = &v1alpha1.PeerEndpoint{ | ||||
| 			DNSOrIP: v1alpha1.DNSOrIP{ | ||||
| 				DNS: peer.Endpoint.DNS, | ||||
| 				IP:  ip, | ||||
| 				IP:  peer.Endpoint.IP().String(), | ||||
| 				DNS: peer.Endpoint.DNS(), | ||||
| 			}, | ||||
| 			Port: peer.Endpoint.Port, | ||||
| 			Port: uint32(peer.Endpoint.Port()), | ||||
| 		} | ||||
| 	} | ||||
| 	var key string | ||||
| 	if len(peer.PublicKey) > 0 { | ||||
| 		key = string(peer.PublicKey) | ||||
| 	if peer.PublicKey != (wgtypes.Key{}) { | ||||
| 		key = peer.PublicKey.String() | ||||
| 	} | ||||
| 	var psk string | ||||
| 	if len(peer.PresharedKey) > 0 { | ||||
| 		psk = string(peer.PresharedKey) | ||||
| 	if peer.PresharedKey != nil { | ||||
| 		psk = peer.PresharedKey.String() | ||||
| 	} | ||||
| 	var pka int | ||||
| 	if peer.PersistentKeepalive > 0 { | ||||
| 		pka = peer.PersistentKeepalive | ||||
| 	if peer.PersistentKeepaliveInterval != nil && *peer.PersistentKeepaliveInterval > time.Duration(0) { | ||||
| 		pka = int(*peer.PersistentKeepaliveInterval) | ||||
| 	} | ||||
| 	return &v1alpha1.Peer{ | ||||
| 		TypeMeta: metav1.TypeMeta{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user