Created join-mesh, list-meshes command

This commit is contained in:
Tim Beatham 2023-09-19 13:45:49 +01:00
parent b679b7fb6e
commit 86756903c7
10 changed files with 179 additions and 72 deletions

View File

@ -6,6 +6,7 @@ import (
"os"
"github.com/akamensky/argparse"
"github.com/tim-beatham/wgmesh/pkg/ctrlserver"
)
const SockAddr = "/tmp/wgmesh_ipc.sock"
@ -22,11 +23,36 @@ func createNewMesh(client *rpc.Client) {
fmt.Println(reply)
}
func listMeshes(client *rpc.Client) {
var reply map[string]ctrlserver.Mesh
err := client.Call("Mesh.ListMeshes", "", &reply)
if err != nil {
fmt.Println(err.Error())
return
}
for sharedKey := range reply {
fmt.Println(sharedKey)
}
}
func joinMesh(client *rpc.Client, meshId string, ipAddress string) {
fmt.Println(meshId + " " + ipAddress)
}
func main() {
parser := argparse.NewParser("wg-mesh",
"wg-mesh Manipulate WireGuard meshes")
newMeshCmd := parser.NewCommand("new-mesh", "Create a new mesh")
listMeshCmd := parser.NewCommand("list-meshes", "List meshes the node is connected to")
joinMeshCmd := parser.NewCommand("join-mesh", "Join a mesh network")
var meshId *string = joinMeshCmd.StringPositional(&argparse.Options{Required: true})
var ipAddress *string = joinMeshCmd.StringPositional(&argparse.Options{Required: true})
err := parser.Parse(os.Args)
if err != nil {
@ -43,4 +69,12 @@ func main() {
if newMeshCmd.Happened() {
createNewMesh(client)
}
if listMeshCmd.Happened() {
listMeshes(client)
}
if joinMeshCmd.Happened() {
joinMesh(client, *meshId, *ipAddress)
}
}

View File

@ -1,14 +1,24 @@
package main
import (
"fmt"
ctrlserver "github.com/tim-beatham/wgmesh/pkg/ctrlserver"
"github.com/tim-beatham/wgmesh/pkg/ctrlserver/api"
"github.com/tim-beatham/wgmesh/pkg/ctrlserver/ipc"
wg "github.com/tim-beatham/wgmesh/pkg/wg"
)
func main() {
ctrlServer := ctrlserver.NewCtrlServer("0.0.0.0", 21910)
wgClient, err := wg.CreateClient("wgmesh")
if err != nil {
fmt.Println(err)
return
}
ctrlServer := ctrlserver.NewCtrlServer("0.0.0.0", 21910, wgClient)
ipc.RunIpcHandler(ctrlServer)
r := api.RunAPI(ctrlServer)
ipc.RunIpcHandler()
r.Run(ctrlServer.GetEndpoint())
}

9
go.mod
View File

@ -2,16 +2,18 @@ module github.com/tim-beatham/wgmesh
go 1.21.1
require golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
require (
github.com/akamensky/argparse v1.4.0
github.com/gin-gonic/gin v1.9.1
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
)
require (
github.com/akamensky/argparse v1.4.0 // indirect
github.com/bytedance/sonic v1.10.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.15.4 // indirect
@ -39,5 +41,4 @@ require (
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gopkg.in/zeromq/goczmq.v4 v4.1.0 // indirect
)

14
go.sum
View File

@ -11,6 +11,7 @@ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpV
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
@ -18,6 +19,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
@ -58,6 +61,7 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@ -68,6 +72,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
@ -76,20 +81,14 @@ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
@ -102,11 +101,10 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/zeromq/goczmq.v4 v4.1.0 h1:CE+FE81mGVs2aSlnbfLuS1oAwdcVywyMM2AC1g33imI=
gopkg.in/zeromq/goczmq.v4 v4.1.0/go.mod h1:h4IlfePEYMpFdywGr5gAwKhBBj+hiBl/nF4VoSE4k+0=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -1,23 +1,23 @@
package mesh
import (
"net/http"
"net/http"
"github.com/gin-gonic/gin"
ctrlserver "github.com/tim-beatham/wgmesh/pkg/ctrlserver"
"github.com/gin-gonic/gin"
ctrlserver "github.com/tim-beatham/wgmesh/pkg/ctrlserver"
)
type JoinMeshInput struct {
MeshId string `json:"mesh-id" binding:"required`
MeshId string `json:"mesh-id" binding:"required`
}
func JoinMesh(c *gin.Context, server *ctrlserver.MeshCtrlServer) {
var input JoinMeshInput
var input JoinMeshInput
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "success"})
c.JSON(http.StatusOK, gin.H{"status": "success"})
}

View File

@ -1,21 +1,23 @@
package ctrlserver
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
/*
* Create a new control server instance running
* on the provided port.
*/
func NewCtrlServer(host string, port int) *MeshCtrlServer {
func NewCtrlServer(host string, port int, wgClient *wgctrl.Client) *MeshCtrlServer {
ctrlServer := new(MeshCtrlServer)
ctrlServer.Port = port
ctrlServer.Meshes = make(map[string]MeshNode)
ctrlServer.Meshes = make(map[string]Mesh)
ctrlServer.Host = host
ctrlServer.Client = wgClient
return ctrlServer
}
@ -37,12 +39,22 @@ func (server *MeshCtrlServer) GetEndpoint() string {
*/
func (server *MeshCtrlServer) Run() bool {
r := gin.Default()
r.GET("/hello", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "hello",
})
})
r.Run(server.GetEndpoint())
return true
}
func (server *MeshCtrlServer) CreateMesh() (*Mesh, error) {
key, err := wgtypes.GenerateKey()
if err != nil {
return nil, err
}
var mesh Mesh = Mesh{
SharedKey: &key,
Nodes: make(map[string]MeshNode),
}
server.Meshes[key.String()] = mesh
return &mesh, nil
}

View File

@ -1,16 +1,23 @@
package ctrlserver
import "github.com/gin-gonic/gin"
import (
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
/*
* Represents a WireGuard node
*/
type MeshNode struct {
Host string
CtrlPort string
WgPort string
WgHost string
GinServer gin.Engine
Host string
CtrlPort string
WgPort string
WgHost string
}
type Mesh struct {
SharedKey *wgtypes.Key
Nodes map[string]MeshNode
}
/*
@ -20,5 +27,6 @@ type MeshNode struct {
type MeshCtrlServer struct {
Host string
Port int
Meshes map[string]MeshNode
Client *wgctrl.Client
Meshes map[string]Mesh
}

View File

@ -7,34 +7,45 @@ import (
"net/rpc"
"os"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"github.com/tim-beatham/wgmesh/pkg/ctrlserver"
"github.com/tim-beatham/wgmesh/pkg/wg"
)
const SockAddr = "/tmp/wgmesh_ipc.sock"
type Mesh struct {
Server *ctrlserver.MeshCtrlServer
}
/*
* Create a new WireGuard mesh network
*/
func (n Mesh) CreateNewMesh(name *string, reply *string) error {
key, err := wgtypes.GenerateKey()
wg.CreateInterface("wgmesh")
mesh, err := n.Server.CreateMesh()
if err != nil {
return err
}
*reply = key.String()
*reply = mesh.SharedKey.String()
return nil
}
func RunIpcHandler() error {
func (n Mesh) ListMeshes(name *string, reply *map[string]ctrlserver.Mesh) error {
meshes := n.Server.Meshes
*reply = meshes
return nil
}
func RunIpcHandler(server *ctrlserver.MeshCtrlServer) error {
if err := os.RemoveAll(SockAddr); err != nil {
return errors.New("Could not find to address")
}
newMeshIpc := new(Mesh)
newMeshIpc.Server = server
rpc.Register(newMeshIpc)
rpc.HandleHTTP()

View File

@ -1,28 +0,0 @@
package meshtypes
import (
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
/*
* Represents a WireGuard mesh.
*/
type WgMesh struct {
SharedKey wgtypes.Key
}
/*
* Create a new WireGuard mesh with a new pre-shared key.
*/
func NewWgMesh() (*WgMesh, error) {
key, err := wgtypes.GenerateKey()
if err != nil {
return nil, err
}
wgMesh := new(WgMesh)
wgMesh.SharedKey = key
return wgMesh, nil
}

61
pkg/wg/wg.go Normal file
View File

@ -0,0 +1,61 @@
package wg
import (
"fmt"
"net"
"os/exec"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
/*
* All WireGuard mesh interface called wgmesh
*/
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 {
fmt.Println(err.Error())
return err
}
}
return nil
}
/*
* Create and configure a new WireGuard client
*/
func CreateClient(ifName string) (*wgctrl.Client, error) {
err := CreateInterface(ifName)
if err != nil {
return nil, err
}
client, err := wgctrl.New()
if err != nil {
return nil, err
}
wgListenPort := 5000
privateKey, err := wgtypes.GeneratePrivateKey()
if err != nil {
return nil, err
}
var cfg wgtypes.Config = wgtypes.Config{
PrivateKey: &privateKey,
ListenPort: &wgListenPort,
}
client.ConfigureDevice(ifName, cfg)
return client, nil
}