topology

package module
v0.0.0-...-f0e42d2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 4, 2021 License: BSD-2-Clause Imports: 12 Imported by: 0

README

Wireguard Topology

Table of Contents

What is Wireguard Topology

Wireguard Topology is a tool that create all the necessary files for systemd-networkd to run a full-secured wireguard VPNs with optionnaly some others network services like vxlans.

Use Case

If you have 10 linux servers, and you want to create a mesh VPN between them with Wireguard, then you have to :

  • generate 10 private keys
  • generate 45 Pre Shared Keys
  • write 20 files and 10 of theses files must list 10 combinaisons of 9 pair of public keys and IP Addresses

If you want to use only 1 vxlan to have a layer 2 VPN then you will 20 others files and again 10 of theses files must list 10 combinaison of 9 IP Addresses

It's a lot of files, and Wireguard Topology can generate them from only 1 single JSON.

Usage

Installation

go install -u github.com/nathanaelle/wireguard-topology/cmd/wg-topology

command line options
  • -dont-generate-cryptographic-keys this option is useful for tests or when the crypto part is delegated to another process
  • -in <JSON source> this mandatory option specify the JSON source file. "-" means stdin.
  • -out <destination> this option specify the destination directory or tar file. the default output destination is the current directory
  • -tmpl <templates> this mandatory option specify the templates directory. The template use the official text/template grammar.

JSON configuration

  • config-name specify the name of the destination where all the configuration will be created
  • prefix-ipv6/cidr mandatory option in case of DNS resolution
  • hosts is a list of unique hosts
    • host is a mandatory unique field which should contain a FQDN and may contain a unique identifier when ipv6 is provided
    • ipv6 is an optionnal field which contains an IPv6. this field will be constructed from the global prefix-ipv6/cidr and the first IPv4 found in the resolution of the FQDN in host.
  • clusters is a list of cluster
    • cluster is a mandatory non unique field wich describe a dense sub network
    • members is the list of FQDN which each peer is connected to every others.

You can read the type declaration in config.go to find all the available options.

Example

the following configuration will produce a VPN where each peer is connected to the 3 others :

{
	"config-name" : "1-network",
	"iface": "wg",
	"prefix-ipv6/cidr": "fd00::/16",
	"hosts": [
		{	"host": "n1",	"ipv6": "fd00:dead:1dea::1/96"	},
		{	"host": "n2",	"ipv6": "fd00:dead:1dea::2/96"	},
		{	"host": "n3",	"ipv6": "fd00:dead:1dea::3/96"	},
		{	"host": "n4",	"ipv6": "fd00:dead:1dea::4/96"	}
	],
	"clusters": [
		{
			"cluster": "network",
			"templates": [ "wg.netdev", "wg.network" ],
			"members": [ "n1", "n2", "n3", "n4" ]
		}
	]
}

There is others examples in examples/

Main Goals

  • systemd-networkd compliant
  • secure Wireguard mesh with unique PSK per edge
  • can configure vxlans
  • use templating for config files
  • use a linear description for a combinatorial situation
  • Coping with custom AllowedIP

Security Statements

  • this code was audited 0 time

License & credits

License

2-Clause BSD

Credits

Thanks to Bruno Bellamy to allow me to use one of his draw as an illustration.

To do

  • Coping with custom AllowedIP
  • cleanup some historical weird stuff in the configuration
  • Improve code comments
  • Improve documentations

Documentation

Index

Constants

View Source
const WGKeyLen int = 32

WGKeyLen is the length of a Curve25519 key

Variables

This section is empty.

Functions

func GenKeyPair

func GenKeyPair() (priv string, pub string, err error)

GenKeyPair generates a pair of base64 encoded Curve25519 keys

func GenPSK

func GenPSK() (psk string, err error)

GenPSK generate en base64 encoded PreSharedKey

func Render

func Render(output Output, t Template, clusters map[string]*NetCluster) error

Render applys templates on the data and export the result in output

func ValidateConf

func ValidateConf(config *Config, noKey bool) error

ValidateConf takes the json Config, validates some input and propagate parameters

Types

type Cluster

type Cluster struct {
	ClusterName string   `json:"cluster"`
	Templates   []string `json:"templates"`
	Members     []string `json:"members"`
}

type Config

type Config struct {
	ConfigName          string                 `json:"config-name"`
	IPv6Prefix          string                 `json:"prefix-ipv6/cidr"`
	PersistentKeepalive *uint16                `json:"persistent-keepalive"`
	Iface               string                 `json:"iface"`
	ListenPort          uint16                 `json:"port"`
	Hosts               []*Host                `json:"hosts"`
	HostsMap            map[string]*Host       `json:"-"`
	Clusters            []*Cluster             `json:"clusters"`
	Misc                map[string]interface{} `json:"Misc"`
}

type EdgeFunc

type EdgeFunc func(nodeA, nodeB string) (string, error)

type Forest

type Forest struct {
	Nodes  map[string]nothing
	Graphs map[string]Graph
}

Forest is a set of graph

func NewForest

func NewForest() *Forest

NewForest create a set of graphs

func (*Forest) AddDenseSubGraph

func (f *Forest) AddDenseSubGraph(graphName string, nodes []string, applyOnPair EdgeFunc) error

AddDenseSubGraph connects a subset of nodes a dense subgraph

func (*Forest) AddNodes

func (f *Forest) AddNodes(nodes []string)

AddNodes prepare a new graph to a set of Graphs

func (*Forest) ForNodes

func (f *Forest) ForNodes(nodeFunc func(node string) error) error

func (*Forest) GetEdge

func (f *Forest) GetEdge(graphName string, nodeA, nodeB string) (string, bool)

func (*Forest) GetEdges

func (f *Forest) GetEdges(graphName string, node string) ([]string, bool)

func (*Forest) Len

func (f *Forest) Len(graphName string) int

type Graph

type Graph map[string]map[string]string

Graph is a graph of PreSharedKeys between two hosts

type Host

type Host struct {
	Name                string                 `json:"host"`
	Templates           []string               `json:"templates"`
	Iface               string                 `json:"iface"`
	PersistentKeepalive *uint16                `json:"persistent-keepalive"`
	ListenPort          uint16                 `json:"port"`
	PrivateIPv6         string                 `json:"-"`
	AllowedIPv6         []string               `json:"-"`
	PrivateIPv6CIDR     string                 `json:"ipv6"`
	PrivateKey          string                 `json:"-"`
	PublicKey           string                 `json:"public-key"`
	Misc                map[string]interface{} `json:"Misc"`
}

type NetCluster

type NetCluster struct {
	Ifaces map[string]*WGInterface
}

type Output

type Output interface {
	AddFolder(name ...string) error
	AddEntry(name ...string) (io.WriteCloser, error)
}

func NewDirOutput

func NewDirOutput(rootDir string) Output

type Template

type Template interface {
	Execute(template string, dest io.Writer, data interface{}) (err error)
}

func LoadTemplates

func LoadTemplates(dir string) (Template, error)

LoadTemplates compiles all the available templates in a folder (not the subfolders) a template is a file with the extension .tmpl

type WGInterface

type WGInterface struct {
	Host         string
	Address      string
	LocalIP      string
	Iface        string
	PrivateKey   string
	ListenPort   uint16
	FirewallMark uint32
	Peers        map[string]*WGPeer
	Templates    []string
	Misc         map[string]interface{}
}

type WGPeer

type WGPeer struct {
	Host                string
	PublicKey           string
	PreSharedKey        string
	AllowedIPs          string
	Address             string
	PeerIP              string
	EndPoint            string
	PersistentKeepalive uint16
}

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL