forked from extern/smegmesh
8aab4e99d8
In the CLI when the peer is not selected as the type throwing an error stating either client or peer must be selected
381 lines
9.9 KiB
Go
381 lines
9.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
ipcRpc "net/rpc"
|
|
"os"
|
|
|
|
"github.com/akamensky/argparse"
|
|
"github.com/tim-beatham/wgmesh/pkg/ipc"
|
|
logging "github.com/tim-beatham/wgmesh/pkg/log"
|
|
)
|
|
|
|
const SockAddr = "/tmp/wgmesh_ipc.sock"
|
|
|
|
type CreateMeshParams struct {
|
|
Client *ipcRpc.Client
|
|
Endpoint string
|
|
WgArgs ipc.WireGuardArgs
|
|
AdvertiseRoutes bool
|
|
AdvertiseDefault bool
|
|
}
|
|
|
|
func createMesh(params *CreateMeshParams) string {
|
|
var reply string
|
|
newMeshParams := ipc.NewMeshArgs{
|
|
WgArgs: params.WgArgs,
|
|
}
|
|
|
|
err := params.Client.Call("IpcHandler.CreateMesh", &newMeshParams, &reply)
|
|
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
|
|
return reply
|
|
}
|
|
|
|
func listMeshes(client *ipcRpc.Client) {
|
|
reply := new(ipc.ListMeshReply)
|
|
|
|
err := client.Call("IpcHandler.ListMeshes", "", &reply)
|
|
|
|
if err != nil {
|
|
logging.Log.WriteErrorf(err.Error())
|
|
return
|
|
}
|
|
|
|
for _, meshId := range reply.Meshes {
|
|
fmt.Println(meshId)
|
|
}
|
|
}
|
|
|
|
type JoinMeshParams struct {
|
|
Client *ipcRpc.Client
|
|
MeshId string
|
|
IpAddress string
|
|
Endpoint string
|
|
WgArgs ipc.WireGuardArgs
|
|
AdvertiseRoutes bool
|
|
AdvertiseDefault bool
|
|
}
|
|
|
|
func joinMesh(params *JoinMeshParams) string {
|
|
var reply string
|
|
|
|
args := ipc.JoinMeshArgs{
|
|
MeshId: params.MeshId,
|
|
IpAdress: params.IpAddress,
|
|
WgArgs: params.WgArgs,
|
|
}
|
|
|
|
err := params.Client.Call("IpcHandler.JoinMesh", &args, &reply)
|
|
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
|
|
return reply
|
|
}
|
|
|
|
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 getGraph(client *ipcRpc.Client, meshId string) {
|
|
var reply string
|
|
|
|
err := client.Call("IpcHandler.GetDOT", &meshId, &reply)
|
|
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
|
|
fmt.Println(reply)
|
|
}
|
|
|
|
func queryMesh(client *ipcRpc.Client, meshId, query string) {
|
|
var reply string
|
|
|
|
err := client.Call("IpcHandler.Query", &ipc.QueryMesh{MeshId: meshId, Query: query}, &reply)
|
|
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
|
|
fmt.Println(reply)
|
|
}
|
|
|
|
// putDescription: puts updates the description about the node to the meshes
|
|
func putDescription(client *ipcRpc.Client, description string) {
|
|
var reply string
|
|
|
|
err := client.Call("IpcHandler.PutDescription", &description, &reply)
|
|
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
|
|
fmt.Println(reply)
|
|
}
|
|
|
|
// putAlias: puts an alias for the node
|
|
func putAlias(client *ipcRpc.Client, alias string) {
|
|
var reply string
|
|
|
|
err := client.Call("IpcHandler.PutAlias", &alias, &reply)
|
|
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
|
|
fmt.Println(reply)
|
|
}
|
|
|
|
func setService(client *ipcRpc.Client, service, value string) {
|
|
var reply string
|
|
|
|
serviceArgs := &ipc.PutServiceArgs{
|
|
Service: service,
|
|
Value: value,
|
|
}
|
|
|
|
err := client.Call("IpcHandler.PutService", serviceArgs, &reply)
|
|
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
|
|
fmt.Println(reply)
|
|
}
|
|
|
|
func deleteService(client *ipcRpc.Client, service string) {
|
|
var reply string
|
|
|
|
err := client.Call("IpcHandler.PutService", &service, &reply)
|
|
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
|
|
fmt.Println(reply)
|
|
}
|
|
|
|
func main() {
|
|
parser := argparse.NewParser("wg-mesh",
|
|
"wg-mesh Manipulate WireGuard mesh networks")
|
|
|
|
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")
|
|
getGraphCmd := parser.NewCommand("get-graph", "Convert a mesh into DOT format")
|
|
leaveMeshCmd := parser.NewCommand("leave-mesh", "Leave a mesh network")
|
|
queryMeshCmd := parser.NewCommand("query-mesh", "Query a mesh network using JMESPath")
|
|
putDescriptionCmd := parser.NewCommand("put-description", "Place a description for the node")
|
|
putAliasCmd := parser.NewCommand("put-alias", "Place an alias for the node")
|
|
setServiceCmd := parser.NewCommand("set-service", "Place a service into your advertisements")
|
|
deleteServiceCmd := parser.NewCommand("delete-service", "Remove a service from your advertisements")
|
|
|
|
var newMeshPort *int = newMeshCmd.Int("p", "wgport", &argparse.Options{
|
|
Default: 0,
|
|
Help: "WireGuard port to use to the interface. A default of 0 uses an unused ephmeral port.",
|
|
})
|
|
|
|
var newMeshEndpoint *string = newMeshCmd.String("e", "endpoint", &argparse.Options{
|
|
Help: "Publicly routeable endpoint to advertise within the mesh",
|
|
})
|
|
|
|
var newMeshRole *string = newMeshCmd.Selector("r", "role", []string{"peer", "client"}, &argparse.Options{
|
|
Default: "peer",
|
|
Help: "Role in the mesh network. A value of peer means that the node is publicly routeable and thus considered" +
|
|
" in the gossip protocol. Client means that the node is not publicly routeable and is not a candidate in the gossip" +
|
|
" protocol",
|
|
})
|
|
var newMeshKeepAliveWg *int = newMeshCmd.Int("k", "KeepAliveWg", &argparse.Options{
|
|
Default: 0,
|
|
Help: "WireGuard KeepAlive value for NAT traversal and firewall holepunching",
|
|
})
|
|
|
|
var newMeshAdvertiseRoutes *bool = newMeshCmd.Flag("a", "advertise", &argparse.Options{
|
|
Help: "Advertise routes to other mesh network into the mesh",
|
|
})
|
|
|
|
var newMeshAdvertiseDefaults *bool = newMeshCmd.Flag("d", "defaults", &argparse.Options{
|
|
Help: "Advertise ::/0 into the mesh network",
|
|
})
|
|
|
|
var joinMeshId *string = joinMeshCmd.String("m", "meshid", &argparse.Options{
|
|
Required: true,
|
|
Help: "MeshID of the mesh network to join",
|
|
})
|
|
|
|
var joinMeshIpAddress *string = joinMeshCmd.String("i", "ip", &argparse.Options{
|
|
Required: true,
|
|
Help: "IP address of the bootstrapping node to join through",
|
|
})
|
|
|
|
var joinMeshEndpoint *string = joinMeshCmd.String("e", "endpoint", &argparse.Options{
|
|
Help: "Publicly routeable endpoint to advertise within the mesh",
|
|
})
|
|
|
|
var joinMeshRole *string = joinMeshCmd.Selector("r", "role", []string{"peer", "client"}, &argparse.Options{
|
|
Default: "peer",
|
|
Help: "Role in the mesh network. A value of peer means that the node is publicly routeable and thus considered" +
|
|
" in the gossip protocol. Client means that the node is not publicly routeable and is not a candidate in the gossip" +
|
|
" protocol",
|
|
})
|
|
|
|
var joinMeshPort *int = joinMeshCmd.Int("p", "wgport", &argparse.Options{
|
|
Default: 0,
|
|
Help: "WireGuard port to use to the interface. A default of 0 uses an unused ephmeral port.",
|
|
})
|
|
|
|
var joinMeshKeepAliveWg *int = joinMeshCmd.Int("k", "KeepAliveWg", &argparse.Options{
|
|
Default: 0,
|
|
Help: "WireGuard KeepAlive value for NAT traversal and firewall ho;lepunching",
|
|
})
|
|
|
|
var joinMeshAdvertiseRoutes *bool = joinMeshCmd.Flag("a", "advertise", &argparse.Options{
|
|
Help: "Advertise routes to other mesh network into the mesh",
|
|
})
|
|
|
|
var joinMeshAdvertiseDefaults *bool = joinMeshCmd.Flag("d", "defaults", &argparse.Options{
|
|
Help: "Advertise ::/0 into the mesh network",
|
|
})
|
|
|
|
var getGraphMeshId *string = getGraphCmd.String("m", "mesh", &argparse.Options{
|
|
Required: true,
|
|
Help: "MeshID of the graph to get",
|
|
})
|
|
|
|
var leaveMeshMeshId *string = leaveMeshCmd.String("m", "mesh", &argparse.Options{
|
|
Required: true,
|
|
Help: "MeshID of the mesh to leave",
|
|
})
|
|
|
|
var queryMeshMeshId *string = queryMeshCmd.String("m", "mesh", &argparse.Options{
|
|
Required: true,
|
|
Help: "MeshID of the mesh to query",
|
|
})
|
|
var queryMeshQuery *string = queryMeshCmd.String("q", "query", &argparse.Options{
|
|
Required: true,
|
|
Help: "JMESPath Query Of The Mesh Network To Query",
|
|
})
|
|
|
|
var description *string = putDescriptionCmd.String("d", "description", &argparse.Options{
|
|
Required: true,
|
|
Help: "Description of the node in the mesh",
|
|
})
|
|
|
|
var alias *string = putAliasCmd.String("a", "alias", &argparse.Options{
|
|
Required: true,
|
|
Help: "Alias of the node to set can be used in DNS to lookup an IP address",
|
|
})
|
|
|
|
var serviceKey *string = setServiceCmd.String("s", "service", &argparse.Options{
|
|
Required: true,
|
|
Help: "Key of the service to advertise in the mesh network",
|
|
})
|
|
var serviceValue *string = setServiceCmd.String("v", "value", &argparse.Options{
|
|
Required: true,
|
|
Help: "Value of the service to advertise in the mesh network",
|
|
})
|
|
|
|
var deleteServiceKey *string = deleteServiceCmd.String("s", "service", &argparse.Options{
|
|
Required: true,
|
|
Help: "Key of the service to remove",
|
|
})
|
|
|
|
err := parser.Parse(os.Args)
|
|
|
|
if err != nil {
|
|
fmt.Print(parser.Usage(err))
|
|
return
|
|
}
|
|
|
|
client, err := ipcRpc.DialHTTP("unix", SockAddr)
|
|
if err != nil {
|
|
fmt.Println(err.Error())
|
|
return
|
|
}
|
|
|
|
if newMeshCmd.Happened() {
|
|
fmt.Println(createMesh(&CreateMeshParams{
|
|
Client: client,
|
|
Endpoint: *newMeshEndpoint,
|
|
WgArgs: ipc.WireGuardArgs{
|
|
Endpoint: *newMeshEndpoint,
|
|
Role: *newMeshRole,
|
|
WgPort: *newMeshPort,
|
|
KeepAliveWg: *newMeshKeepAliveWg,
|
|
AdvertiseDefaultRoute: *newMeshAdvertiseDefaults,
|
|
AdvertiseRoutes: *newMeshAdvertiseRoutes,
|
|
},
|
|
}))
|
|
}
|
|
|
|
if listMeshCmd.Happened() {
|
|
listMeshes(client)
|
|
}
|
|
|
|
if joinMeshCmd.Happened() {
|
|
fmt.Println(joinMesh(&JoinMeshParams{
|
|
Client: client,
|
|
IpAddress: *joinMeshIpAddress,
|
|
MeshId: *joinMeshId,
|
|
Endpoint: *joinMeshEndpoint,
|
|
WgArgs: ipc.WireGuardArgs{
|
|
Endpoint: *joinMeshEndpoint,
|
|
Role: *joinMeshRole,
|
|
WgPort: *joinMeshPort,
|
|
KeepAliveWg: *joinMeshKeepAliveWg,
|
|
AdvertiseDefaultRoute: *joinMeshAdvertiseDefaults,
|
|
AdvertiseRoutes: *joinMeshAdvertiseRoutes,
|
|
},
|
|
}))
|
|
}
|
|
|
|
if getGraphCmd.Happened() {
|
|
getGraph(client, *getGraphMeshId)
|
|
}
|
|
|
|
if leaveMeshCmd.Happened() {
|
|
leaveMesh(client, *leaveMeshMeshId)
|
|
}
|
|
|
|
if queryMeshCmd.Happened() {
|
|
queryMesh(client, *queryMeshMeshId, *queryMeshQuery)
|
|
}
|
|
|
|
if putDescriptionCmd.Happened() {
|
|
putDescription(client, *description)
|
|
}
|
|
|
|
if putAliasCmd.Happened() {
|
|
putAlias(client, *alias)
|
|
}
|
|
|
|
if setServiceCmd.Happened() {
|
|
setService(client, *serviceKey, *serviceValue)
|
|
}
|
|
|
|
if deleteServiceCmd.Happened() {
|
|
deleteService(client, *deleteServiceKey)
|
|
}
|
|
}
|