mirror of
https://github.com/tim-beatham/smegmesh.git
synced 2025-01-20 20:48:54 +01:00
Standardising filenames, interfacing out
for tests and modifying network device manipulation
This commit is contained in:
parent
5757d81a81
commit
472718c9a3
@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
ipcRpc "net/rpc"
|
||||
"os"
|
||||
"strings"
|
||||
@ -15,14 +14,22 @@ import (
|
||||
|
||||
const SockAddr = "/tmp/wgmesh_ipc.sock"
|
||||
|
||||
func createMesh(client *ipcRpc.Client, ifName string, wgPort int) string {
|
||||
type CreateMeshParams struct {
|
||||
Client *ipcRpc.Client
|
||||
IfName string
|
||||
WgPort int
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
func createMesh(args *CreateMeshParams) string {
|
||||
var reply string
|
||||
newMeshParams := ipc.NewMeshArgs{
|
||||
IfName: ifName,
|
||||
WgPort: wgPort,
|
||||
IfName: args.IfName,
|
||||
WgPort: args.WgPort,
|
||||
Endpoint: args.Endpoint,
|
||||
}
|
||||
|
||||
err := client.Call("IpcHandler.CreateMesh", &newMeshParams, &reply)
|
||||
err := args.Client.Call("IpcHandler.CreateMesh", &newMeshParams, &reply)
|
||||
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
@ -46,17 +53,26 @@ func listMeshes(client *ipcRpc.Client) {
|
||||
}
|
||||
}
|
||||
|
||||
func joinMesh(client *ipcRpc.Client, meshId string, ipAddress string, ifName string, wgPort int) string {
|
||||
type JoinMeshParams struct {
|
||||
Client *ipcRpc.Client
|
||||
MeshId string
|
||||
IpAddress string
|
||||
IfName string
|
||||
WgPort int
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
func joinMesh(params *JoinMeshParams) string {
|
||||
var reply string
|
||||
|
||||
args := ipc.JoinMeshArgs{
|
||||
MeshId: meshId,
|
||||
IpAdress: ipAddress,
|
||||
IfName: ifName,
|
||||
Port: wgPort,
|
||||
MeshId: params.MeshId,
|
||||
IpAdress: params.IpAddress,
|
||||
IfName: params.IfName,
|
||||
Port: params.WgPort,
|
||||
}
|
||||
|
||||
err := client.Call("IpcHandler.JoinMesh", &args, &reply)
|
||||
err := params.Client.Call("IpcHandler.JoinMesh", &args, &reply)
|
||||
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
@ -71,7 +87,7 @@ func getMesh(client *ipcRpc.Client, meshId string) {
|
||||
err := client.Call("IpcHandler.GetMesh", &meshId, &reply)
|
||||
|
||||
if err != nil {
|
||||
log.Panic(err.Error())
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@ -89,6 +105,19 @@ func getMesh(client *ipcRpc.Client, meshId string) {
|
||||
}
|
||||
}
|
||||
|
||||
func leaveMesh(client *ipcRpc.Client, meshId string) {
|
||||
var reply string
|
||||
|
||||
err := client.Call("IpcHandler.LeaveMesh", &meshId, &reply)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(reply)
|
||||
}
|
||||
|
||||
func enableInterface(client *ipcRpc.Client, meshId string) {
|
||||
var reply string
|
||||
|
||||
@ -125,19 +154,24 @@ func main() {
|
||||
getMeshCmd := parser.NewCommand("get-mesh", "Get a mesh network")
|
||||
enableInterfaceCmd := parser.NewCommand("enable-interface", "Enable A Specific Mesh Interface")
|
||||
getGraphCmd := parser.NewCommand("get-graph", "Convert a mesh into DOT format")
|
||||
leaveMeshCmd := parser.NewCommand("leave-mesh", "Leave a mesh network")
|
||||
|
||||
var newMeshIfName *string = newMeshCmd.String("f", "ifname", &argparse.Options{Required: true})
|
||||
var newMeshPort *int = newMeshCmd.Int("p", "wgport", &argparse.Options{Required: true})
|
||||
var newMeshEndpoint *string = newMeshCmd.String("e", "endpoint", &argparse.Options{})
|
||||
|
||||
var meshId *string = joinMeshCmd.String("m", "mesh", &argparse.Options{Required: true})
|
||||
var ipAddress *string = joinMeshCmd.String("i", "ip", &argparse.Options{Required: true})
|
||||
var joinMeshId *string = joinMeshCmd.String("m", "mesh", &argparse.Options{Required: true})
|
||||
var joinMeshIpAddress *string = joinMeshCmd.String("i", "ip", &argparse.Options{Required: true})
|
||||
var joinMeshIfName *string = joinMeshCmd.String("f", "ifname", &argparse.Options{Required: true})
|
||||
var joinMeshPort *int = joinMeshCmd.Int("p", "wgport", &argparse.Options{Required: true})
|
||||
var joinMeshEndpoint *string = joinMeshCmd.String("e", "endpoint", &argparse.Options{})
|
||||
|
||||
var getMeshId *string = getMeshCmd.String("m", "mesh", &argparse.Options{Required: true})
|
||||
var enableInterfaceMeshId *string = enableInterfaceCmd.String("m", "mesh", &argparse.Options{Required: true})
|
||||
var getGraphMeshId *string = getGraphCmd.String("m", "mesh", &argparse.Options{Required: true})
|
||||
|
||||
var leaveMeshMeshId *string = leaveMeshCmd.String("m", "mesh", &argparse.Options{Required: true})
|
||||
|
||||
err := parser.Parse(os.Args)
|
||||
|
||||
if err != nil {
|
||||
@ -152,7 +186,12 @@ func main() {
|
||||
}
|
||||
|
||||
if newMeshCmd.Happened() {
|
||||
fmt.Println(createMesh(client, *newMeshIfName, *newMeshPort))
|
||||
fmt.Println(createMesh(&CreateMeshParams{
|
||||
Client: client,
|
||||
IfName: *newMeshIfName,
|
||||
WgPort: *newMeshPort,
|
||||
Endpoint: *newMeshEndpoint,
|
||||
}))
|
||||
}
|
||||
|
||||
if listMeshCmd.Happened() {
|
||||
@ -160,7 +199,14 @@ func main() {
|
||||
}
|
||||
|
||||
if joinMeshCmd.Happened() {
|
||||
fmt.Println(joinMesh(client, *meshId, *ipAddress, *joinMeshIfName, *joinMeshPort))
|
||||
fmt.Println(joinMesh(&JoinMeshParams{
|
||||
Client: client,
|
||||
IfName: *joinMeshIfName,
|
||||
WgPort: *joinMeshPort,
|
||||
IpAddress: *joinMeshIpAddress,
|
||||
MeshId: *joinMeshId,
|
||||
Endpoint: *joinMeshEndpoint,
|
||||
}))
|
||||
}
|
||||
|
||||
if getMeshCmd.Happened() {
|
||||
@ -174,4 +220,8 @@ func main() {
|
||||
if enableInterfaceCmd.Happened() {
|
||||
enableInterface(client, *enableInterfaceMeshId)
|
||||
}
|
||||
|
||||
if leaveMeshCmd.Happened() {
|
||||
leaveMesh(client, *leaveMeshMeshId)
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/tim-beatham/wgmesh/pkg/conf"
|
||||
ctrlserver "github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
||||
"github.com/tim-beatham/wgmesh/pkg/ip"
|
||||
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
||||
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
||||
"github.com/tim-beatham/wgmesh/pkg/middleware"
|
||||
@ -49,7 +48,6 @@ func main() {
|
||||
|
||||
robinIpcParams := robin.RobinIpcParams{
|
||||
CtrlServer: ctrlServer,
|
||||
Allocator: &ip.ULABuilder{},
|
||||
}
|
||||
|
||||
robinRpc.Server = ctrlServer
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"github.com/tim-beatham/wgmesh/pkg/lib"
|
||||
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
||||
"github.com/tim-beatham/wgmesh/pkg/mesh"
|
||||
"github.com/tim-beatham/wgmesh/pkg/wg"
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
@ -66,21 +65,22 @@ func (c *CrdtMeshManager) Load(bytes []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type NewCrdtNodeMangerParams struct {
|
||||
MeshId string
|
||||
DevName string
|
||||
Port int
|
||||
Conf conf.WgMeshConfiguration
|
||||
Client *wgctrl.Client
|
||||
}
|
||||
|
||||
// NewCrdtNodeManager: Create a new crdt node manager
|
||||
func NewCrdtNodeManager(meshId, devName string, port int, conf conf.WgMeshConfiguration, client *wgctrl.Client) (*CrdtMeshManager, error) {
|
||||
func NewCrdtNodeManager(params *NewCrdtNodeMangerParams) (*CrdtMeshManager, error) {
|
||||
var manager CrdtMeshManager
|
||||
manager.MeshId = meshId
|
||||
manager.MeshId = params.MeshId
|
||||
manager.doc = automerge.New()
|
||||
manager.IfName = devName
|
||||
manager.Client = client
|
||||
manager.conf = &conf
|
||||
|
||||
err := wg.CreateWgInterface(client, devName, port)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
manager.IfName = params.DevName
|
||||
manager.Client = params.Client
|
||||
manager.conf = ¶ms.Conf
|
||||
return &manager, nil
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ func (c *CrdtMeshManager) removeNode(endpoint string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNode: returns a mesh node crdt.
|
||||
// GetNode: returns a mesh node crdt.Close releases resources used by a Client.
|
||||
func (m *CrdtMeshManager) GetNode(endpoint string) (*MeshNodeCrdt, error) {
|
||||
node, err := m.doc.Path("nodes").Map().Get(endpoint)
|
||||
|
||||
|
@ -1,10 +0,0 @@
|
||||
package crdt
|
||||
|
||||
import "github.com/tim-beatham/wgmesh/pkg/mesh"
|
||||
|
||||
type CrdtProviderFactory struct{}
|
||||
|
||||
func (f *CrdtProviderFactory) CreateMesh(params *mesh.MeshProviderFactoryParams) (mesh.MeshProvider, error) {
|
||||
return NewCrdtNodeManager(params.MeshId, params.DevName, params.Port,
|
||||
*params.Conf, params.Client)
|
||||
}
|
55
pkg/automerge/factory.go
Normal file
55
pkg/automerge/factory.go
Normal file
@ -0,0 +1,55 @@
|
||||
package crdt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tim-beatham/wgmesh/pkg/conf"
|
||||
"github.com/tim-beatham/wgmesh/pkg/lib"
|
||||
"github.com/tim-beatham/wgmesh/pkg/mesh"
|
||||
)
|
||||
|
||||
type CrdtProviderFactory struct{}
|
||||
|
||||
func (f *CrdtProviderFactory) CreateMesh(params *mesh.MeshProviderFactoryParams) (mesh.MeshProvider, error) {
|
||||
return NewCrdtNodeManager(&NewCrdtNodeMangerParams{
|
||||
MeshId: params.MeshId,
|
||||
DevName: params.DevName,
|
||||
Conf: *params.Conf,
|
||||
Client: params.Client,
|
||||
})
|
||||
}
|
||||
|
||||
type MeshNodeFactory struct {
|
||||
Config conf.WgMeshConfiguration
|
||||
}
|
||||
|
||||
// Build builds the mesh node that represents the host machine to add
|
||||
// to the mesh
|
||||
func (f *MeshNodeFactory) Build(params *mesh.MeshNodeFactoryParams) mesh.MeshNode {
|
||||
hostName := f.getAddress(params)
|
||||
|
||||
return &MeshNodeCrdt{
|
||||
HostEndpoint: fmt.Sprintf("%s:%s", hostName, f.Config.GrpcPort),
|
||||
PublicKey: params.PublicKey.String(),
|
||||
WgEndpoint: fmt.Sprintf("%s:%d", hostName, params.WgPort),
|
||||
WgHost: fmt.Sprintf("%s/128", params.NodeIP.String()),
|
||||
// Always set the routes as empty.
|
||||
// Routes handled by external component
|
||||
Routes: map[string]interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
// getAddress returns the routable address of the machine.
|
||||
func (f *MeshNodeFactory) getAddress(params *mesh.MeshNodeFactoryParams) string {
|
||||
var hostName string = ""
|
||||
|
||||
if params.Endpoint != "" {
|
||||
hostName = params.Endpoint
|
||||
} else if len(f.Config.Endpoint) != 0 {
|
||||
hostName = f.Config.Endpoint
|
||||
} else {
|
||||
hostName = lib.GetOutboundIP().String()
|
||||
}
|
||||
|
||||
return hostName
|
||||
}
|
@ -9,18 +9,25 @@ import (
|
||||
)
|
||||
|
||||
type WgMeshConfiguration struct {
|
||||
CertificatePath string `yaml:"certificatePath"`
|
||||
PrivateKeyPath string `yaml:"privateKeyPath"`
|
||||
CaCertificatePath string `yaml:"caCertificatePath"`
|
||||
SkipCertVerification bool `yaml:"skipCertVerification"`
|
||||
GrpcPort string `yaml:"gRPCPort"`
|
||||
// CertificatePath is the path to the certificate to use in mTLS
|
||||
CertificatePath string `yaml:"certificatePath"`
|
||||
// PrivateKeypath is the path to the clients private key in mTLS
|
||||
PrivateKeyPath string `yaml:"privateKeyPath"`
|
||||
// CaCeritifcatePath path to the certificate of the trust certificate authority
|
||||
CaCertificatePath string `yaml:"caCertificatePath"`
|
||||
// SkipCertVerification specify to skip certificate verification. Should only be used
|
||||
// in test environments
|
||||
SkipCertVerification bool `yaml:"skipCertVerification"`
|
||||
// Port to run the GrpcServer on
|
||||
GrpcPort string `yaml:"gRPCPort"`
|
||||
// AdvertiseRoutes advertises other meshes if the node is in multiple meshes
|
||||
AdvertiseRoutes bool `yaml:"advertiseRoutes"`
|
||||
// PublicEndpoint is the IP in which this computer is publicly reachable.
|
||||
// usecase is when the node is behind NAT.
|
||||
PublicEndpoint string `yaml:"publicEndpoint"`
|
||||
// Endpoint is the IP in which this computer is publicly reachable.
|
||||
// usecase is when the node has multiple IP addresses
|
||||
Endpoint string `yaml:"publicEndpoint"`
|
||||
}
|
||||
|
||||
// ParseConfiguration parses the mesh configuration
|
||||
func ParseConfiguration(filePath string) (*WgMeshConfiguration, error) {
|
||||
var conf WgMeshConfiguration
|
||||
|
||||
|
@ -4,8 +4,11 @@ import (
|
||||
crdt "github.com/tim-beatham/wgmesh/pkg/automerge"
|
||||
"github.com/tim-beatham/wgmesh/pkg/conf"
|
||||
"github.com/tim-beatham/wgmesh/pkg/conn"
|
||||
"github.com/tim-beatham/wgmesh/pkg/ip"
|
||||
"github.com/tim-beatham/wgmesh/pkg/lib"
|
||||
"github.com/tim-beatham/wgmesh/pkg/mesh"
|
||||
"github.com/tim-beatham/wgmesh/pkg/rpc"
|
||||
"github.com/tim-beatham/wgmesh/pkg/wg"
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
)
|
||||
|
||||
@ -22,10 +25,27 @@ type NewCtrlServerParams struct {
|
||||
// operation failed
|
||||
func NewCtrlServer(params *NewCtrlServerParams) (*MeshCtrlServer, error) {
|
||||
ctrlServer := new(MeshCtrlServer)
|
||||
factory := crdt.CrdtProviderFactory{}
|
||||
ctrlServer.MeshManager = mesh.NewMeshManager(*params.Conf, params.Client, &factory)
|
||||
ctrlServer.Conf = params.Conf
|
||||
meshFactory := crdt.CrdtProviderFactory{}
|
||||
nodeFactory := crdt.MeshNodeFactory{
|
||||
Config: *params.Conf,
|
||||
}
|
||||
idGenerator := &lib.UUIDGenerator{}
|
||||
ipAllocator := &ip.ULABuilder{}
|
||||
interfaceManipulator := wg.NewWgInterfaceManipulator(params.Client)
|
||||
|
||||
meshManagerParams := &mesh.NewMeshManagerParams{
|
||||
Conf: *params.Conf,
|
||||
Client: params.Client,
|
||||
MeshProvider: &meshFactory,
|
||||
NodeFactory: &nodeFactory,
|
||||
IdGenerator: idGenerator,
|
||||
IPAllocator: ipAllocator,
|
||||
InterfaceManipulator: interfaceManipulator,
|
||||
}
|
||||
|
||||
ctrlServer.MeshManager = mesh.NewMeshManager(meshManagerParams)
|
||||
|
||||
ctrlServer.Conf = params.Conf
|
||||
connManagerParams := conn.NewConnectionManageParams{
|
||||
CertificatePath: params.Conf.CertificatePath,
|
||||
PrivateKey: params.Conf.PrivateKeyPath,
|
||||
|
@ -11,15 +11,27 @@ import (
|
||||
)
|
||||
|
||||
type NewMeshArgs struct {
|
||||
// IfName is the interface that the mesh instance will run on
|
||||
IfName string
|
||||
// WgPort is the WireGuard port to expose
|
||||
WgPort int
|
||||
// Endpoint is the routable alias of the machine. Can be an IP
|
||||
// or DNS entry
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
type JoinMeshArgs struct {
|
||||
MeshId string
|
||||
// MeshId is the ID of the mesh to join
|
||||
MeshId string
|
||||
// IpAddress is a routable IP in another mesh
|
||||
IpAdress string
|
||||
IfName string
|
||||
Port int
|
||||
// IfName is the interface name of the mesh
|
||||
IfName string
|
||||
// Port is the WireGuard port to expose
|
||||
Port int
|
||||
// Endpoint is the routable address of this machine. If not provided
|
||||
// defaults to the default address
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
type GetMeshReply struct {
|
||||
@ -34,6 +46,7 @@ type MeshIpc interface {
|
||||
CreateMesh(args *NewMeshArgs, reply *string) error
|
||||
ListMeshes(name string, reply *ListMeshReply) error
|
||||
JoinMesh(args JoinMeshArgs, reply *string) error
|
||||
LeaveMesh(meshId string, reply *string) error
|
||||
GetMesh(meshId string, reply *GetMeshReply) error
|
||||
EnableInterface(meshId string, reply *string) error
|
||||
GetDOT(meshId string, reply *string) error
|
||||
|
17
pkg/lib/id.go
Normal file
17
pkg/lib/id.go
Normal file
@ -0,0 +1,17 @@
|
||||
package lib
|
||||
|
||||
import "github.com/google/uuid"
|
||||
|
||||
// IdGenerator generates unique ids
|
||||
type IdGenerator interface {
|
||||
// GetId generates a unique ID or an error if something went wrong
|
||||
GetId() (string, error)
|
||||
}
|
||||
|
||||
type UUIDGenerator struct {
|
||||
}
|
||||
|
||||
func (g *UUIDGenerator) GetId() (string, error) {
|
||||
id := uuid.New()
|
||||
return id.String(), nil
|
||||
}
|
@ -5,8 +5,10 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tim-beatham/wgmesh/pkg/conf"
|
||||
"github.com/tim-beatham/wgmesh/pkg/ip"
|
||||
"github.com/tim-beatham/wgmesh/pkg/lib"
|
||||
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
||||
"github.com/tim-beatham/wgmesh/pkg/wg"
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
@ -17,16 +19,19 @@ type MeshManager struct {
|
||||
Client *wgctrl.Client
|
||||
// HostParameters contains information that uniquely locates
|
||||
// the node in the mesh network.
|
||||
HostParameters *HostParameters
|
||||
conf *conf.WgMeshConfiguration
|
||||
meshProviderFactory MeshProviderFactory
|
||||
configApplyer MeshConfigApplyer
|
||||
interfaceEnabler MeshInterface
|
||||
HostParameters *HostParameters
|
||||
conf *conf.WgMeshConfiguration
|
||||
meshProviderFactory MeshProviderFactory
|
||||
nodeFactory MeshNodeFactory
|
||||
configApplyer MeshConfigApplyer
|
||||
idGenerator lib.IdGenerator
|
||||
ipAllocator ip.IPAllocator
|
||||
interfaceManipulator wg.WgInterfaceManipulator
|
||||
}
|
||||
|
||||
// CreateMesh: Creates a new mesh, stores it and returns the mesh id
|
||||
func (m *MeshManager) CreateMesh(devName string, port int) (string, error) {
|
||||
key, err := wgtypes.GenerateKey()
|
||||
meshId, err := m.idGenerator.GetId()
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -37,47 +42,48 @@ func (m *MeshManager) CreateMesh(devName string, port int) (string, error) {
|
||||
Port: port,
|
||||
Conf: m.conf,
|
||||
Client: m.Client,
|
||||
MeshId: key.String(),
|
||||
MeshId: meshId,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
m.Meshes[key.String()] = nodeManager
|
||||
return key.String(), err
|
||||
m.Meshes[meshId] = nodeManager
|
||||
return meshId, err
|
||||
}
|
||||
|
||||
type AddMeshParams struct {
|
||||
MeshId string
|
||||
DevName string
|
||||
WgPort int
|
||||
MeshBytes []byte
|
||||
}
|
||||
|
||||
// AddMesh: Add the mesh to the list of meshes
|
||||
func (m *MeshManager) AddMesh(meshId string, devName string, port int, meshBytes []byte) error {
|
||||
func (m *MeshManager) AddMesh(params *AddMeshParams) error {
|
||||
meshProvider, err := m.meshProviderFactory.CreateMesh(&MeshProviderFactoryParams{
|
||||
DevName: devName,
|
||||
Port: port,
|
||||
DevName: params.DevName,
|
||||
Port: params.WgPort,
|
||||
Conf: m.conf,
|
||||
Client: m.Client,
|
||||
MeshId: meshId,
|
||||
MeshId: params.MeshId,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = meshProvider.Load(meshBytes)
|
||||
err = meshProvider.Load(params.MeshBytes)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Meshes[meshId] = meshProvider
|
||||
m.Meshes[params.MeshId] = meshProvider
|
||||
return err
|
||||
}
|
||||
|
||||
// AddMeshNode: Add a mesh node
|
||||
func (m *MeshManager) AddMeshNode(meshId string, node MeshNode) error {
|
||||
m.Meshes[meshId].AddNode(node)
|
||||
return m.RouteManager.UpdateRoutes()
|
||||
}
|
||||
|
||||
// HasChanges returns true if the mesh has changes
|
||||
func (m *MeshManager) HasChanges(meshId string) bool {
|
||||
return m.Meshes[meshId].HasChanges()
|
||||
@ -97,7 +103,25 @@ func (s *MeshManager) EnableInterface(meshId string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.interfaceEnabler.EnableInterface(meshId)
|
||||
meshNode, err := s.GetSelf(meshId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mesh := s.GetMesh(meshId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dev, err := mesh.GetDevice()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.interfaceManipulator.EnableInterface(dev.Name, meshNode.GetWgHost().String())
|
||||
}
|
||||
|
||||
// GetPublicKey: Gets the public key of the WireGuard mesh
|
||||
@ -117,6 +141,54 @@ func (s *MeshManager) GetPublicKey(meshId string) (*wgtypes.Key, error) {
|
||||
return &dev.PublicKey, nil
|
||||
}
|
||||
|
||||
type AddSelfParams struct {
|
||||
// MeshId is the ID of the mesh to add this instance to
|
||||
MeshId string
|
||||
// WgPort is the WireGuard port to advertise
|
||||
WgPort int
|
||||
// Endpoint is the alias of the machine to send routable packets
|
||||
// to
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
// AddSelf adds this host to the mesh
|
||||
func (s *MeshManager) AddSelf(params *AddSelfParams) error {
|
||||
pubKey, err := s.GetPublicKey(params.MeshId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeIP, err := s.ipAllocator.GetIP(*pubKey, params.MeshId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
node := s.nodeFactory.Build(&MeshNodeFactoryParams{
|
||||
PublicKey: pubKey,
|
||||
NodeIP: nodeIP,
|
||||
WgPort: params.WgPort,
|
||||
Endpoint: params.Endpoint,
|
||||
})
|
||||
|
||||
s.Meshes[params.MeshId].AddNode(node)
|
||||
return s.RouteManager.UpdateRoutes()
|
||||
}
|
||||
|
||||
// LeaveMesh leaves the mesh network
|
||||
func (s *MeshManager) LeaveMesh(meshId string) error {
|
||||
_, exists := s.Meshes[meshId]
|
||||
|
||||
if !exists {
|
||||
return errors.New(fmt.Sprintf("mesh %s does not exist", meshId))
|
||||
}
|
||||
|
||||
// For now just delete the mesh with the ID.
|
||||
delete(s.Meshes, meshId)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MeshManager) GetSelf(meshId string) (MeshNode, error) {
|
||||
meshInstance, ok := s.Meshes[meshId]
|
||||
|
||||
@ -152,15 +224,26 @@ func (s *MeshManager) UpdateTimeStamp() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewMeshManagerParams params required to create an instance of a mesh manager
|
||||
type NewMeshManagerParams struct {
|
||||
Conf conf.WgMeshConfiguration
|
||||
Client *wgctrl.Client
|
||||
MeshProvider MeshProviderFactory
|
||||
NodeFactory MeshNodeFactory
|
||||
IdGenerator lib.IdGenerator
|
||||
IPAllocator ip.IPAllocator
|
||||
InterfaceManipulator wg.WgInterfaceManipulator
|
||||
}
|
||||
|
||||
// Creates a new instance of a mesh manager with the given parameters
|
||||
func NewMeshManager(conf conf.WgMeshConfiguration, client *wgctrl.Client, meshProvider MeshProviderFactory) *MeshManager {
|
||||
func NewMeshManager(params *NewMeshManagerParams) *MeshManager {
|
||||
hostParams := HostParameters{}
|
||||
|
||||
switch conf.PublicEndpoint {
|
||||
switch params.Conf.Endpoint {
|
||||
case "":
|
||||
hostParams.HostEndpoint = fmt.Sprintf("%s:%s", lib.GetOutboundIP().String(), conf.GrpcPort)
|
||||
hostParams.HostEndpoint = fmt.Sprintf("%s:%s", lib.GetOutboundIP().String(), params.Conf.GrpcPort)
|
||||
default:
|
||||
hostParams.HostEndpoint = fmt.Sprintf("%s:%s", conf.PublicEndpoint, conf.GrpcPort)
|
||||
hostParams.HostEndpoint = fmt.Sprintf("%s:%s", params.Conf.Endpoint, params.Conf.GrpcPort)
|
||||
}
|
||||
|
||||
logging.Log.WriteInfof("Endpoint %s", hostParams.HostEndpoint)
|
||||
@ -168,12 +251,15 @@ func NewMeshManager(conf conf.WgMeshConfiguration, client *wgctrl.Client, meshPr
|
||||
m := &MeshManager{
|
||||
Meshes: make(map[string]MeshProvider),
|
||||
HostParameters: &hostParams,
|
||||
meshProviderFactory: meshProvider,
|
||||
Client: client,
|
||||
conf: &conf,
|
||||
meshProviderFactory: params.MeshProvider,
|
||||
nodeFactory: params.NodeFactory,
|
||||
Client: params.Client,
|
||||
conf: ¶ms.Conf,
|
||||
}
|
||||
m.configApplyer = NewWgMeshConfigApplyer(m)
|
||||
m.RouteManager = NewRouteManager(m)
|
||||
m.interfaceEnabler = NewWgMeshInterface(m)
|
||||
m.idGenerator = params.IdGenerator
|
||||
m.ipAllocator = params.IPAllocator
|
||||
m.interfaceManipulator = params.InterfaceManipulator
|
||||
return m
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package mesh
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/tim-beatham/wgmesh/pkg/wg"
|
||||
)
|
||||
|
||||
// MeshInterfaces manipulates interfaces to do with meshes
|
||||
type MeshInterface interface {
|
||||
EnableInterface(meshId string) error
|
||||
}
|
||||
|
||||
type WgMeshInterface struct {
|
||||
manager *MeshManager
|
||||
}
|
||||
|
||||
// EnableInterface enables the interface at the given endpoint
|
||||
func (m *WgMeshInterface) EnableInterface(meshId string) error {
|
||||
mesh, ok := m.manager.Meshes[meshId]
|
||||
|
||||
if !ok {
|
||||
return errors.New("the provided mesh does not exist")
|
||||
}
|
||||
|
||||
dev, err := mesh.GetDevice()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self, err := m.manager.GetSelf(meshId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return wg.EnableInterface(dev.Name, self.GetWgHost().String())
|
||||
}
|
||||
|
||||
func NewWgMeshInterface(manager *MeshManager) MeshInterface {
|
||||
return &WgMeshInterface{manager: manager}
|
||||
}
|
@ -68,7 +68,7 @@ type MeshProvider interface {
|
||||
// HostParameters contains the IDs of a node
|
||||
type HostParameters struct {
|
||||
HostEndpoint string
|
||||
// TODO: Contain the WireGuard identifier in this
|
||||
// TODO: Contain the WireGungracefullyuard identifier in this
|
||||
}
|
||||
|
||||
// MeshProviderFactoryParams parameters required to build a mesh provider
|
||||
@ -84,3 +84,17 @@ type MeshProviderFactoryParams struct {
|
||||
type MeshProviderFactory interface {
|
||||
CreateMesh(params *MeshProviderFactoryParams) (MeshProvider, error)
|
||||
}
|
||||
|
||||
// MeshNodeFactoryParams are the parameters required to construct
|
||||
// a mesh node
|
||||
type MeshNodeFactoryParams struct {
|
||||
PublicKey *wgtypes.Key
|
||||
NodeIP net.IP
|
||||
WgPort int
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
// MeshBuilder build the hosts mesh node for it to be added to the mesh
|
||||
type MeshNodeFactory interface {
|
||||
Build(params *MeshNodeFactoryParams) MeshNode
|
||||
}
|
||||
|
@ -7,15 +7,11 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
crdt "github.com/tim-beatham/wgmesh/pkg/automerge"
|
||||
"github.com/tim-beatham/wgmesh/pkg/ctrlserver"
|
||||
"github.com/tim-beatham/wgmesh/pkg/ip"
|
||||
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
||||
"github.com/tim-beatham/wgmesh/pkg/lib"
|
||||
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
||||
"github.com/tim-beatham/wgmesh/pkg/mesh"
|
||||
"github.com/tim-beatham/wgmesh/pkg/rpc"
|
||||
"github.com/tim-beatham/wgmesh/pkg/wg"
|
||||
)
|
||||
|
||||
type IpcHandler struct {
|
||||
@ -24,42 +20,17 @@ type IpcHandler struct {
|
||||
}
|
||||
|
||||
func (n *IpcHandler) CreateMesh(args *ipc.NewMeshArgs, reply *string) error {
|
||||
wg.CreateInterface(args.IfName)
|
||||
|
||||
meshId, err := n.Server.MeshManager.CreateMesh(args.IfName, args.WgPort)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubKey, err := n.Server.MeshManager.GetPublicKey(meshId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeIP, err := n.ipAllocator.GetIP(*pubKey, meshId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
outBoundIp := lib.GetOutboundIP()
|
||||
|
||||
meshNode := crdt.MeshNodeCrdt{
|
||||
HostEndpoint: fmt.Sprintf("%s:%s", outBoundIp.String(), n.Server.Conf.GrpcPort),
|
||||
PublicKey: pubKey.String(),
|
||||
WgEndpoint: fmt.Sprintf("%s:%d", outBoundIp.String(), args.WgPort),
|
||||
WgHost: nodeIP.String() + "/128",
|
||||
Routes: map[string]interface{}{},
|
||||
}
|
||||
|
||||
err = n.Server.MeshManager.AddMeshNode(meshId, &meshNode)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = n.Server.MeshManager.AddSelf(&mesh.AddSelfParams{
|
||||
MeshId: meshId,
|
||||
WgPort: args.WgPort,
|
||||
Endpoint: args.Endpoint,
|
||||
})
|
||||
*reply = meshId
|
||||
return nil
|
||||
}
|
||||
@ -101,45 +72,42 @@ func (n *IpcHandler) JoinMesh(args ipc.JoinMeshArgs, reply *string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = n.Server.MeshManager.AddMesh(args.MeshId, args.IfName, args.Port, meshReply.Mesh)
|
||||
err = n.Server.MeshManager.AddMesh(&mesh.AddMeshParams{
|
||||
MeshId: args.MeshId,
|
||||
DevName: args.IfName,
|
||||
WgPort: args.Port,
|
||||
MeshBytes: meshReply.Mesh,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubKey, err := n.Server.MeshManager.GetPublicKey(args.MeshId)
|
||||
err = n.Server.MeshManager.AddSelf(&mesh.AddSelfParams{
|
||||
MeshId: args.MeshId,
|
||||
WgPort: args.Port,
|
||||
Endpoint: args.Endpoint,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ipAddr, err := n.ipAllocator.GetIP(*pubKey, args.MeshId)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logging.Log.WriteInfof("WgIP: " + ipAddr.String())
|
||||
|
||||
outBoundIP := lib.GetOutboundIP()
|
||||
|
||||
node := crdt.MeshNodeCrdt{
|
||||
HostEndpoint: fmt.Sprintf("%s:%s", outBoundIP.String(), n.Server.Conf.GrpcPort),
|
||||
WgEndpoint: fmt.Sprintf("%s:%d", outBoundIP.String(), args.Port),
|
||||
PublicKey: pubKey.String(),
|
||||
WgHost: ipAddr.String() + "/128",
|
||||
Routes: make(map[string]interface{}),
|
||||
}
|
||||
err = n.Server.MeshManager.AddMeshNode(args.MeshId, &node)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*reply = strconv.FormatBool(true)
|
||||
return nil
|
||||
}
|
||||
|
||||
// LeaveMesh leaves a mesh network
|
||||
func (n *IpcHandler) LeaveMesh(meshId string, reply *string) error {
|
||||
err := n.Server.MeshManager.LeaveMesh(meshId)
|
||||
|
||||
if err == nil {
|
||||
*reply = fmt.Sprintf("Left Mesh %s", meshId)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (n *IpcHandler) GetMesh(meshId string, reply *ipc.GetMeshReply) error {
|
||||
mesh := n.Server.MeshManager.GetMesh(meshId)
|
||||
meshSnapshot, err := mesh.GetMesh()
|
||||
@ -175,7 +143,6 @@ func (n *IpcHandler) GetMesh(meshId string, reply *ipc.GetMeshReply) error {
|
||||
}
|
||||
|
||||
*reply = ipc.GetMeshReply{Nodes: nodes}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -206,12 +173,10 @@ func (n *IpcHandler) GetDOT(meshId string, reply *string) error {
|
||||
|
||||
type RobinIpcParams struct {
|
||||
CtrlServer *ctrlserver.MeshCtrlServer
|
||||
Allocator ip.IPAllocator
|
||||
}
|
||||
|
||||
func NewRobinIpc(ipcParams RobinIpcParams) IpcHandler {
|
||||
return IpcHandler{
|
||||
Server: ipcParams.CtrlServer,
|
||||
ipAllocator: ipcParams.Allocator,
|
||||
Server: ipcParams.CtrlServer,
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,12 @@ func (s *SyncRequesterImpl) GetMesh(meshId string, ifName string, port int, endP
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.server.MeshManager.AddMesh(meshId, ifName, port, reply.Mesh)
|
||||
err = s.server.MeshManager.AddMesh(&mesh.AddMeshParams{
|
||||
MeshId: meshId,
|
||||
DevName: ifName,
|
||||
WgPort: port,
|
||||
MeshBytes: reply.Mesh,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
|
22
pkg/wg/types.go
Normal file
22
pkg/wg/types.go
Normal file
@ -0,0 +1,22 @@
|
||||
package wg
|
||||
|
||||
type WgError struct {
|
||||
msg string
|
||||
}
|
||||
|
||||
func (m *WgError) Error() string {
|
||||
return m.msg
|
||||
}
|
||||
|
||||
type CreateInterfaceParams struct {
|
||||
IfName string
|
||||
Port int
|
||||
}
|
||||
|
||||
type WgInterfaceManipulator interface {
|
||||
// CreateInterface creates a WireGuard interface
|
||||
CreateInterface(params *CreateInterfaceParams) error
|
||||
// Enable interface enables the given interface with
|
||||
// the IP. It overrides the IP at the interface
|
||||
EnableInterface(ifName string, ip string) error
|
||||
}
|
70
pkg/wg/wg.go
70
pkg/wg/wg.go
@ -1,6 +1,7 @@
|
||||
package wg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
|
||||
@ -9,29 +10,30 @@ import (
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
/*
|
||||
* All WireGuard mesh interface called wgmesh
|
||||
*/
|
||||
func CreateInterface(ifName string) error {
|
||||
// createInterface uses ip link to create an interface. If the interface exists
|
||||
// it returns an error
|
||||
func createInterface(ifName string) error {
|
||||
_, err := net.InterfaceByName(ifName)
|
||||
|
||||
// Check if the interface exists
|
||||
if err != nil {
|
||||
cmd := exec.Command("/usr/bin/ip", "link", "add", "dev", ifName, "type", "wireguard")
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err == nil {
|
||||
return &WgError{msg: fmt.Sprintf("Interface %s already exists", ifName)}
|
||||
}
|
||||
|
||||
// Check if the interface exists
|
||||
cmd := exec.Command("/usr/bin/ip", "link", "add", "dev", ifName, "type", "wireguard")
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
* Create and configure a new WireGuard client
|
||||
*/
|
||||
func CreateWgInterface(client *wgctrl.Client, ifName string, port int) error {
|
||||
err := CreateInterface(ifName)
|
||||
type WgInterfaceManipulatorImpl struct {
|
||||
client *wgctrl.Client
|
||||
}
|
||||
|
||||
func (m *WgInterfaceManipulatorImpl) CreateInterface(params *CreateInterfaceParams) error {
|
||||
err := createInterface(params.IfName)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@ -45,18 +47,37 @@ func CreateWgInterface(client *wgctrl.Client, ifName string, port int) error {
|
||||
|
||||
var cfg wgtypes.Config = wgtypes.Config{
|
||||
PrivateKey: &privateKey,
|
||||
ListenPort: &port,
|
||||
ListenPort: ¶ms.Port,
|
||||
}
|
||||
|
||||
client.ConfigureDevice(ifName, cfg)
|
||||
m.client.ConfigureDevice(params.IfName, cfg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func EnableInterface(ifName string, ip string) error {
|
||||
cmd := exec.Command("/usr/bin/ip", "link", "set", "up", "dev", ifName)
|
||||
// flushInterface flushes the specified interface
|
||||
func flushInterface(ifName string) error {
|
||||
_, err := net.InterfaceByName(ifName)
|
||||
|
||||
if err != nil {
|
||||
return &WgError{msg: fmt.Sprintf("Interface %s does not exist cannot flush", ifName)}
|
||||
}
|
||||
|
||||
cmd := exec.Command("/usr/bin/ip", "addr", "flush", "dev", ifName)
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
logging.Log.WriteErrorf(err.Error())
|
||||
logging.Log.WriteErrorf(fmt.Sprintf("%s error flushing interface %s", err.Error(), ifName))
|
||||
return &WgError{msg: fmt.Sprintf("Failed to flush interface %s", ifName)}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnableInterface flushes the interface and sets the ip address of the
|
||||
// interface
|
||||
func (m *WgInterfaceManipulatorImpl) EnableInterface(ifName string, ip string) error {
|
||||
err := flushInterface(ifName)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -66,11 +87,14 @@ func EnableInterface(ifName string, ip string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd = exec.Command("/usr/bin/ip", "addr", "add", hostIp.String()+"/64", "dev", ifName)
|
||||
cmd := exec.Command("/usr/bin/ip", "addr", "add", hostIp.String()+"/64", "dev", ifName)
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewWgInterfaceManipulator(client *wgctrl.Client) WgInterfaceManipulator {
|
||||
return &WgInterfaceManipulatorImpl{client: client}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user