From dcf851a02e4d9603bb8d6de6a307d3bd7da5878a Mon Sep 17 00:00:00 2001 From: Tim Beatham Date: Tue, 19 Sep 2023 23:50:44 +0100 Subject: [PATCH] Ability to add peer to config --- cmd/wg-mesh/main.go | 43 ++- cmd/wgmeshd/main.go | 30 +-- pkg/ctrlserver/ctrlserver.go | 121 +++++++-- pkg/ctrlserver/ctrltypes.go | 9 +- pkg/ctrlserver/ipc/ipchandler.go | 35 ++- pkg/ctrlserver/rpc/ctrlserver.pb.go | 330 ++++++++++++++++++++--- pkg/ctrlserver/rpc/ctrlserver_grpc.pb.go | 36 +++ pkg/ctrlserver/rpc/rpchandler.go | 88 ++++++ pkg/ipc/ipctypes.go | 6 + pkg/wg/wg.go | 2 +- 10 files changed, 607 insertions(+), 93 deletions(-) diff --git a/cmd/wg-mesh/main.go b/cmd/wg-mesh/main.go index fc66da1..79644e9 100644 --- a/cmd/wg-mesh/main.go +++ b/cmd/wg-mesh/main.go @@ -12,16 +12,16 @@ import ( const SockAddr = "/tmp/wgmesh_ipc.sock" -func createNewMesh(client *ipcRpc.Client) { +func createNewMesh(client *ipcRpc.Client) string { var reply string err := client.Call("Mesh.CreateNewMesh", "", &reply) if err != nil { - fmt.Println(err.Error()) - return + return err.Error() } - fmt.Println(reply) + joinMesh(client, reply, "localhost") + return reply } func listMeshes(client *ipcRpc.Client) { @@ -30,7 +30,7 @@ func listMeshes(client *ipcRpc.Client) { err := client.Call("Mesh.ListMeshes", "", &reply) if err != nil { - fmt.Println(err.Error()) + err.Error() return } @@ -39,19 +39,37 @@ func listMeshes(client *ipcRpc.Client) { } } -func joinMesh(client *ipcRpc.Client, meshId string, ipAddress string) { +func joinMesh(client *ipcRpc.Client, meshId string, ipAddress string) string { var reply string args := ipc.JoinMeshArgs{MeshId: meshId, IpAdress: ipAddress} err := client.Call("Mesh.JoinMesh", &args, &reply) + if err != nil { + return err.Error() + } + + return reply +} + +func getMesh(client *ipcRpc.Client, meshId string) { + reply := new(ipc.GetMeshReply) + + err := client.Call("Mesh.GetMesh", &meshId, &reply) + if err != nil { fmt.Println(err.Error()) return } - fmt.Println(reply) + for _, node := range reply.Nodes { + fmt.Println("Public Key: " + node.PublicKey) + fmt.Println("WireGuard Endpoint: " + node.HostEndpoint) + fmt.Println("Control Endpoint: " + node.WgEndpoint) + fmt.Println("Wg IP: " + node.WgHost) + fmt.Println("---") + } } func main() { @@ -61,10 +79,13 @@ func main() { 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") + getMeshCmd := parser.NewCommand("get-mesh", "Get a mesh network") var meshId *string = joinMeshCmd.String("m", "mesh", &argparse.Options{Required: true}) var ipAddress *string = joinMeshCmd.String("i", "ip", &argparse.Options{Required: true}) + var getMeshId *string = getMeshCmd.String("m", "mesh", &argparse.Options{Required: true}) + err := parser.Parse(os.Args) if err != nil { @@ -79,7 +100,7 @@ func main() { } if newMeshCmd.Happened() { - createNewMesh(client) + fmt.Println(createNewMesh(client)) } if listMeshCmd.Happened() { @@ -87,6 +108,10 @@ func main() { } if joinMeshCmd.Happened() { - joinMesh(client, *meshId, *ipAddress) + fmt.Println(joinMesh(client, *meshId, *ipAddress)) + } + + if getMeshCmd.Happened() { + getMesh(client, *getMeshId) } } diff --git a/cmd/wgmeshd/main.go b/cmd/wgmeshd/main.go index b500d15..4a5b491 100644 --- a/cmd/wgmeshd/main.go +++ b/cmd/wgmeshd/main.go @@ -1,8 +1,6 @@ package main import ( - "context" - "errors" "fmt" "net" @@ -10,27 +8,8 @@ import ( "github.com/tim-beatham/wgmesh/pkg/ctrlserver/ipc" "github.com/tim-beatham/wgmesh/pkg/ctrlserver/rpc" wg "github.com/tim-beatham/wgmesh/pkg/wg" - "google.golang.org/grpc" ) -type meshCtrlServer struct { - rpc.UnimplementedMeshCtrlServerServer - server *ctrlserver.MeshCtrlServer -} - -func newServer(ctrl *ctrlserver.MeshCtrlServer) *meshCtrlServer { - return &meshCtrlServer{server: ctrl} -} - -func (m *meshCtrlServer) GetMesh(ctx context.Context, request *rpc.GetMeshRequest) (*rpc.GetMeshReply, error) { - mesh, contains := m.server.Meshes[request.MeshId] - - if !contains { - return nil, errors.New("Element is not in the mesh") - } - return &rpc.GetMeshReply{MeshId: mesh.SharedKey.String()}, nil -} - func main() { wgClient, err := wg.CreateClient("wgmesh") @@ -39,17 +18,12 @@ func main() { return } - ctrlServer := ctrlserver.NewCtrlServer("0.0.0.0", 21910, wgClient) + ctrlServer := ctrlserver.NewCtrlServer(wgClient, "wgmesh") fmt.Println("Running IPC Handler") go ipc.RunIpcHandler(ctrlServer) - fmt.Println("Running gRPC server") - - grpc := grpc.NewServer() - - rpcServer := newServer(ctrlServer) - rpc.RegisterMeshCtrlServerServer(grpc, rpcServer) + grpc := rpc.NewRpcServer(ctrlServer) lis, err := net.Listen("tcp", ":8080") if err := grpc.Serve(lis); err != nil { diff --git a/pkg/ctrlserver/ctrlserver.go b/pkg/ctrlserver/ctrlserver.go index 4b8e296..de62923 100644 --- a/pkg/ctrlserver/ctrlserver.go +++ b/pkg/ctrlserver/ctrlserver.go @@ -1,9 +1,12 @@ package ctrlserver import ( + "errors" + "fmt" + "math/rand" + "net" "strconv" - "github.com/gin-gonic/gin" "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -12,12 +15,11 @@ import ( * Create a new control server instance running * on the provided port. */ -func NewCtrlServer(host string, port int, wgClient *wgctrl.Client) *MeshCtrlServer { +func NewCtrlServer(wgClient *wgctrl.Client, ifName string) *MeshCtrlServer { ctrlServer := new(MeshCtrlServer) - ctrlServer.Port = port ctrlServer.Meshes = make(map[string]Mesh) - ctrlServer.Host = host ctrlServer.Client = wgClient + ctrlServer.IfName = ifName return ctrlServer } @@ -30,19 +32,6 @@ func (server *MeshCtrlServer) IsInMesh(meshId string) bool { return inMesh } -func (server *MeshCtrlServer) GetEndpoint() string { - return server.Host + ":" + strconv.Itoa(server.Port) -} - -/* - * Run the gin server instance - */ -func (server *MeshCtrlServer) Run() bool { - r := gin.Default() - r.Run(server.GetEndpoint()) - return true -} - func (server *MeshCtrlServer) CreateMesh() (*Mesh, error) { key, err := wgtypes.GenerateKey() @@ -58,3 +47,101 @@ func (server *MeshCtrlServer) CreateMesh() (*Mesh, error) { server.Meshes[key.String()] = mesh return &mesh, nil } + +type AddHostArgs struct { + HostEndpoint string + PublicKey string + MeshId string + WgEndpoint string +} + +func (server *MeshCtrlServer) AddHost(args AddHostArgs) error { + nodes, contains := server.Meshes[args.MeshId] + + if !contains { + return errors.New("Node does not exist in the mesh") + } + + _, contains = nodes.Nodes[args.HostEndpoint] + + if contains { + return errors.New("The node already has an endpoint in the mesh network") + } + + fmt.Println(args.WgEndpoint) + + node := MeshNode{ + HostEndpoint: args.HostEndpoint, + WgEndpoint: args.WgEndpoint, + PublicKey: args.PublicKey, + WgHost: "10.0.0." + strconv.Itoa(rand.Intn(253)+1) + "/32", + } + + err := addWgPeer(server.IfName, server.Client, node) + + if err == nil { + nodes.Nodes[args.MeshId] = node + } else { + fmt.Println(err.Error()) + } + + return err +} + +func (server *MeshCtrlServer) GetDevice() *wgtypes.Device { + dev, err := server.Client.Device(server.IfName) + + if err != nil { + return nil + } + + return dev +} + +func addWgPeer(ifName string, client *wgctrl.Client, node MeshNode) error { + peer := make([]wgtypes.PeerConfig, 1) + + peerPublic, err := wgtypes.ParseKey(node.PublicKey) + + if err != nil { + return err + } + + peerEndpoint, err := net.ResolveUDPAddr("udp", node.WgEndpoint) + + if err != nil { + fmt.Println("err") + return err + } + + allowedIps := make([]net.IPNet, 1) + _, ipnet, err := net.ParseCIDR(node.WgHost) + + if err != nil { + return err + } + + allowedIps[0] = *ipnet + + peer[0] = wgtypes.PeerConfig{ + PublicKey: peerPublic, + Endpoint: peerEndpoint, + AllowedIPs: allowedIps, + } + + cfg := wgtypes.Config{ + Peers: peer, + } + + err = client.ConfigureDevice(ifName, cfg) + + dev, _ := client.Device(ifName) + + fmt.Println(dev.Peers[0].Endpoint) + + if err != nil { + return err + } + + return nil +} diff --git a/pkg/ctrlserver/ctrltypes.go b/pkg/ctrlserver/ctrltypes.go index a2aa731..1d682ff 100644 --- a/pkg/ctrlserver/ctrltypes.go +++ b/pkg/ctrlserver/ctrltypes.go @@ -9,10 +9,10 @@ import ( * Represents a WireGuard node */ type MeshNode struct { - Host string - CtrlPort string - WgPort string - WgHost string + HostEndpoint string + WgEndpoint string + PublicKey string + WgHost string } type Mesh struct { @@ -29,4 +29,5 @@ type MeshCtrlServer struct { Port int Client *wgctrl.Client Meshes map[string]Mesh + IfName string } diff --git a/pkg/ctrlserver/ipc/ipchandler.go b/pkg/ctrlserver/ipc/ipchandler.go index 648ce6c..b3895a3 100644 --- a/pkg/ctrlserver/ipc/ipchandler.go +++ b/pkg/ctrlserver/ipc/ipchandler.go @@ -3,14 +3,17 @@ package ipc import ( "context" "errors" + "fmt" "net" "net/http" ipcRpc "net/rpc" "os" + "strconv" "time" "github.com/tim-beatham/wgmesh/pkg/ctrlserver" "github.com/tim-beatham/wgmesh/pkg/ctrlserver/rpc" + "github.com/tim-beatham/wgmesh/pkg/ipc" ipctypes "github.com/tim-beatham/wgmesh/pkg/ipc" "github.com/tim-beatham/wgmesh/pkg/wg" "google.golang.org/grpc" @@ -59,13 +62,41 @@ func (n Mesh) JoinMesh(args *ipctypes.JoinMeshArgs, reply *string) error { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - r, err := c.GetMesh(ctx, &rpc.GetMeshRequest{MeshId: args.MeshId}) + dev := n.Server.GetDevice() + + joinMeshReq := rpc.JoinMeshRequest{ + MeshId: args.MeshId, + HostPort: 8080, + PublicKey: dev.PublicKey.String(), + WgPort: int32(dev.ListenPort), + } + + r, err := c.JoinMesh(ctx, &joinMeshReq) if err != nil { return err } - *reply = r.GetMeshId() + *reply = strconv.FormatBool(r.GetSuccess()) + return nil +} + +func (n Mesh) GetMesh(meshId string, reply *ipc.GetMeshReply) error { + mesh, contains := n.Server.Meshes[meshId] + + if contains { + nodes := make([]ctrlserver.MeshNode, len(mesh.Nodes)) + + i := 0 + for _, n := range mesh.Nodes { + fmt.Println(n.PublicKey) + nodes[i] = n + i += 1 + } + + *reply = ipc.GetMeshReply{Nodes: nodes} + } else { + } return nil } diff --git a/pkg/ctrlserver/rpc/ctrlserver.pb.go b/pkg/ctrlserver/rpc/ctrlserver.pb.go index e4ea55d..7e92673 100644 --- a/pkg/ctrlserver/rpc/ctrlserver.pb.go +++ b/pkg/ctrlserver/rpc/ctrlserver.pb.go @@ -20,6 +20,69 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type MeshNode struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PublicKey string `protobuf:"bytes,1,opt,name=publicKey,proto3" json:"publicKey,omitempty"` + WgEndpoint string `protobuf:"bytes,2,opt,name=wgEndpoint,proto3" json:"wgEndpoint,omitempty"` + Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"` +} + +func (x *MeshNode) Reset() { + *x = MeshNode{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MeshNode) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MeshNode) ProtoMessage() {} + +func (x *MeshNode) ProtoReflect() protoreflect.Message { + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MeshNode.ProtoReflect.Descriptor instead. +func (*MeshNode) Descriptor() ([]byte, []int) { + return file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescGZIP(), []int{0} +} + +func (x *MeshNode) GetPublicKey() string { + if x != nil { + return x.PublicKey + } + return "" +} + +func (x *MeshNode) GetWgEndpoint() string { + if x != nil { + return x.WgEndpoint + } + return "" +} + +func (x *MeshNode) GetEndpoint() string { + if x != nil { + return x.Endpoint + } + return "" +} + type GetMeshRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -31,7 +94,7 @@ type GetMeshRequest struct { func (x *GetMeshRequest) Reset() { *x = GetMeshRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[0] + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -44,7 +107,7 @@ func (x *GetMeshRequest) String() string { func (*GetMeshRequest) ProtoMessage() {} func (x *GetMeshRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[0] + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -57,7 +120,7 @@ func (x *GetMeshRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMeshRequest.ProtoReflect.Descriptor instead. func (*GetMeshRequest) Descriptor() ([]byte, []int) { - return file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescGZIP(), []int{0} + return file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescGZIP(), []int{1} } func (x *GetMeshRequest) GetMeshId() string { @@ -72,13 +135,14 @@ type GetMeshReply struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - MeshId string `protobuf:"bytes,1,opt,name=meshId,proto3" json:"meshId,omitempty"` + MeshId string `protobuf:"bytes,1,opt,name=meshId,proto3" json:"meshId,omitempty"` + MeshNode []*MeshNode `protobuf:"bytes,2,rep,name=meshNode,proto3" json:"meshNode,omitempty"` } func (x *GetMeshReply) Reset() { *x = GetMeshReply{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[1] + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -91,7 +155,7 @@ func (x *GetMeshReply) String() string { func (*GetMeshReply) ProtoMessage() {} func (x *GetMeshReply) ProtoReflect() protoreflect.Message { - mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[1] + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -104,7 +168,7 @@ func (x *GetMeshReply) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMeshReply.ProtoReflect.Descriptor instead. func (*GetMeshReply) Descriptor() ([]byte, []int) { - return file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescGZIP(), []int{1} + return file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescGZIP(), []int{2} } func (x *GetMeshReply) GetMeshId() string { @@ -114,25 +178,184 @@ func (x *GetMeshReply) GetMeshId() string { return "" } +func (x *GetMeshReply) GetMeshNode() []*MeshNode { + if x != nil { + return x.MeshNode + } + return nil +} + +type JoinMeshRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MeshId string `protobuf:"bytes,1,opt,name=meshId,proto3" json:"meshId,omitempty"` + HostPort int32 `protobuf:"varint,2,opt,name=hostPort,proto3" json:"hostPort,omitempty"` + PublicKey string `protobuf:"bytes,3,opt,name=publicKey,proto3" json:"publicKey,omitempty"` + WgPort int32 `protobuf:"varint,4,opt,name=wgPort,proto3" json:"wgPort,omitempty"` +} + +func (x *JoinMeshRequest) Reset() { + *x = JoinMeshRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *JoinMeshRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JoinMeshRequest) ProtoMessage() {} + +func (x *JoinMeshRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JoinMeshRequest.ProtoReflect.Descriptor instead. +func (*JoinMeshRequest) Descriptor() ([]byte, []int) { + return file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescGZIP(), []int{3} +} + +func (x *JoinMeshRequest) GetMeshId() string { + if x != nil { + return x.MeshId + } + return "" +} + +func (x *JoinMeshRequest) GetHostPort() int32 { + if x != nil { + return x.HostPort + } + return 0 +} + +func (x *JoinMeshRequest) GetPublicKey() string { + if x != nil { + return x.PublicKey + } + return "" +} + +func (x *JoinMeshRequest) GetWgPort() int32 { + if x != nil { + return x.WgPort + } + return 0 +} + +type JoinMeshReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + MeshIp *string `protobuf:"bytes,2,opt,name=meshIp,proto3,oneof" json:"meshIp,omitempty"` +} + +func (x *JoinMeshReply) Reset() { + *x = JoinMeshReply{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *JoinMeshReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JoinMeshReply) ProtoMessage() {} + +func (x *JoinMeshReply) ProtoReflect() protoreflect.Message { + mi := &file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JoinMeshReply.ProtoReflect.Descriptor instead. +func (*JoinMeshReply) Descriptor() ([]byte, []int) { + return file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescGZIP(), []int{4} +} + +func (x *JoinMeshReply) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *JoinMeshReply) GetMeshIp() string { + if x != nil && x.MeshIp != nil { + return *x.MeshIp + } + return "" +} + var File_pkg_grpc_ctrlserver_ctrlserver_proto protoreflect.FileDescriptor var file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDesc = []byte{ 0x0a, 0x24, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x74, 0x72, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x63, 0x74, 0x72, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x72, 0x70, 0x63, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x22, 0x28, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x64, 0x22, 0x26, 0x0a, 0x0c, 0x47, 0x65, - 0x74, 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, - 0x73, 0x68, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x73, 0x68, - 0x49, 0x64, 0x32, 0x4f, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x74, 0x72, 0x6c, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x68, 0x12, - 0x18, 0x2e, 0x72, 0x70, 0x63, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, - 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x22, 0x00, 0x42, 0x14, 0x5a, 0x12, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x74, 0x72, 0x6c, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x22, 0x64, 0x0a, 0x08, 0x4d, 0x65, 0x73, 0x68, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x67, + 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x77, 0x67, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x28, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x73, 0x68, + 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x64, + 0x22, 0x56, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x68, + 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x72, 0x70, 0x63, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x08, + 0x6d, 0x65, 0x73, 0x68, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x7b, 0x0a, 0x0f, 0x4a, 0x6f, 0x69, 0x6e, + 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, + 0x65, 0x73, 0x68, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x73, + 0x68, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, + 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, + 0x06, 0x77, 0x67, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x77, + 0x67, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x51, 0x0a, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x4d, 0x65, 0x73, + 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x12, 0x1b, 0x0a, 0x06, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x00, 0x52, 0x06, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x70, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, + 0x07, 0x5f, 0x6d, 0x65, 0x73, 0x68, 0x49, 0x70, 0x32, 0x91, 0x01, 0x0a, 0x0e, 0x4d, 0x65, 0x73, + 0x68, 0x43, 0x74, 0x72, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x18, 0x2e, 0x72, 0x70, 0x63, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x72, 0x70, 0x63, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4d, + 0x65, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x08, 0x4a, 0x6f, + 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x12, 0x19, 0x2e, 0x72, 0x70, 0x63, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x72, 0x70, 0x63, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4a, 0x6f, 0x69, + 0x6e, 0x4d, 0x65, 0x73, 0x68, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x14, 0x5a, 0x12, + 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x74, 0x72, 0x6c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x72, + 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -147,19 +370,25 @@ func file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescGZIP() []byte { return file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDescData } -var file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_pkg_grpc_ctrlserver_ctrlserver_proto_goTypes = []interface{}{ - (*GetMeshRequest)(nil), // 0: rpctypes.GetMeshRequest - (*GetMeshReply)(nil), // 1: rpctypes.GetMeshReply + (*MeshNode)(nil), // 0: rpctypes.MeshNode + (*GetMeshRequest)(nil), // 1: rpctypes.GetMeshRequest + (*GetMeshReply)(nil), // 2: rpctypes.GetMeshReply + (*JoinMeshRequest)(nil), // 3: rpctypes.JoinMeshRequest + (*JoinMeshReply)(nil), // 4: rpctypes.JoinMeshReply } var file_pkg_grpc_ctrlserver_ctrlserver_proto_depIdxs = []int32{ - 0, // 0: rpctypes.MeshCtrlServer.GetMesh:input_type -> rpctypes.GetMeshRequest - 1, // 1: rpctypes.MeshCtrlServer.GetMesh:output_type -> rpctypes.GetMeshReply - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 0, // 0: rpctypes.GetMeshReply.meshNode:type_name -> rpctypes.MeshNode + 1, // 1: rpctypes.MeshCtrlServer.GetMesh:input_type -> rpctypes.GetMeshRequest + 3, // 2: rpctypes.MeshCtrlServer.JoinMesh:input_type -> rpctypes.JoinMeshRequest + 2, // 3: rpctypes.MeshCtrlServer.GetMesh:output_type -> rpctypes.GetMeshReply + 4, // 4: rpctypes.MeshCtrlServer.JoinMesh:output_type -> rpctypes.JoinMeshReply + 3, // [3:5] is the sub-list for method output_type + 1, // [1:3] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_pkg_grpc_ctrlserver_ctrlserver_proto_init() } @@ -169,7 +398,7 @@ func file_pkg_grpc_ctrlserver_ctrlserver_proto_init() { } if !protoimpl.UnsafeEnabled { file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetMeshRequest); i { + switch v := v.(*MeshNode); i { case 0: return &v.state case 1: @@ -181,6 +410,18 @@ func file_pkg_grpc_ctrlserver_ctrlserver_proto_init() { } } file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetMeshRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetMeshReply); i { case 0: return &v.state @@ -192,14 +433,39 @@ func file_pkg_grpc_ctrlserver_ctrlserver_proto_init() { return nil } } + file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*JoinMeshRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*JoinMeshReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } + file_pkg_grpc_ctrlserver_ctrlserver_proto_msgTypes[4].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_grpc_ctrlserver_ctrlserver_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 5, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/ctrlserver/rpc/ctrlserver_grpc.pb.go b/pkg/ctrlserver/rpc/ctrlserver_grpc.pb.go index 09aab0e..0a1f501 100644 --- a/pkg/ctrlserver/rpc/ctrlserver_grpc.pb.go +++ b/pkg/ctrlserver/rpc/ctrlserver_grpc.pb.go @@ -23,6 +23,7 @@ const _ = grpc.SupportPackageIsVersion7 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type MeshCtrlServerClient interface { GetMesh(ctx context.Context, in *GetMeshRequest, opts ...grpc.CallOption) (*GetMeshReply, error) + JoinMesh(ctx context.Context, in *JoinMeshRequest, opts ...grpc.CallOption) (*JoinMeshReply, error) } type meshCtrlServerClient struct { @@ -42,11 +43,21 @@ func (c *meshCtrlServerClient) GetMesh(ctx context.Context, in *GetMeshRequest, return out, nil } +func (c *meshCtrlServerClient) JoinMesh(ctx context.Context, in *JoinMeshRequest, opts ...grpc.CallOption) (*JoinMeshReply, error) { + out := new(JoinMeshReply) + err := c.cc.Invoke(ctx, "/rpctypes.MeshCtrlServer/JoinMesh", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MeshCtrlServerServer is the server API for MeshCtrlServer service. // All implementations must embed UnimplementedMeshCtrlServerServer // for forward compatibility type MeshCtrlServerServer interface { GetMesh(context.Context, *GetMeshRequest) (*GetMeshReply, error) + JoinMesh(context.Context, *JoinMeshRequest) (*JoinMeshReply, error) mustEmbedUnimplementedMeshCtrlServerServer() } @@ -57,6 +68,9 @@ type UnimplementedMeshCtrlServerServer struct { func (UnimplementedMeshCtrlServerServer) GetMesh(context.Context, *GetMeshRequest) (*GetMeshReply, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMesh not implemented") } +func (UnimplementedMeshCtrlServerServer) JoinMesh(context.Context, *JoinMeshRequest) (*JoinMeshReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method JoinMesh not implemented") +} func (UnimplementedMeshCtrlServerServer) mustEmbedUnimplementedMeshCtrlServerServer() {} // UnsafeMeshCtrlServerServer may be embedded to opt out of forward compatibility for this service. @@ -88,6 +102,24 @@ func _MeshCtrlServer_GetMesh_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _MeshCtrlServer_JoinMesh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(JoinMeshRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MeshCtrlServerServer).JoinMesh(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/rpctypes.MeshCtrlServer/JoinMesh", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MeshCtrlServerServer).JoinMesh(ctx, req.(*JoinMeshRequest)) + } + return interceptor(ctx, in, info, handler) +} + // MeshCtrlServer_ServiceDesc is the grpc.ServiceDesc for MeshCtrlServer service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -99,6 +131,10 @@ var MeshCtrlServer_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetMesh", Handler: _MeshCtrlServer_GetMesh_Handler, }, + { + MethodName: "JoinMesh", + Handler: _MeshCtrlServer_JoinMesh_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pkg/grpc/ctrlserver/ctrlserver.proto", diff --git a/pkg/ctrlserver/rpc/rpchandler.go b/pkg/ctrlserver/rpc/rpchandler.go index 9ab1e3e..c667f04 100644 --- a/pkg/ctrlserver/rpc/rpchandler.go +++ b/pkg/ctrlserver/rpc/rpchandler.go @@ -1 +1,89 @@ package rpc + +import ( + context "context" + "errors" + "fmt" + "net" + "strconv" + + "github.com/tim-beatham/wgmesh/pkg/ctrlserver" + "google.golang.org/grpc" + "google.golang.org/grpc/peer" +) + +type meshCtrlServer struct { + UnimplementedMeshCtrlServerServer + server *ctrlserver.MeshCtrlServer +} + +func nodeToRpcNode(node ctrlserver.MeshNode) *MeshNode { + return &MeshNode{ + PublicKey: node.PublicKey, + WgEndpoint: node.WgEndpoint, + Endpoint: node.HostEndpoint, + } +} + +func nodesToRpcNodes(nodes map[string]ctrlserver.MeshNode) []*MeshNode { + n := len(nodes) + meshNodes := make([]*MeshNode, n) + + var i int = 0 + + for _, v := range nodes { + meshNodes[i] = nodeToRpcNode(v) + i++ + } + + return meshNodes +} + +func (m *meshCtrlServer) GetMesh(ctx context.Context, request *GetMeshRequest) (*GetMeshReply, error) { + mesh, contains := m.server.Meshes[request.MeshId] + + if !contains { + return nil, errors.New("Element is not in the mesh") + } + + reply := GetMeshReply{ + MeshId: request.MeshId, + MeshNode: nodesToRpcNodes(mesh.Nodes), + } + + return &reply, nil +} + +func (m *meshCtrlServer) JoinMesh(ctx context.Context, request *JoinMeshRequest) (*JoinMeshReply, error) { + p, _ := peer.FromContext(ctx) + fmt.Println(p.Addr.String()) + + hostIp, _, err := net.SplitHostPort(p.Addr.String()) + + if err != nil { + return nil, err + } + + addHostArgs := ctrlserver.AddHostArgs{ + HostEndpoint: "[" + hostIp + "]" + ":" + strconv.Itoa(int(request.HostPort)), + PublicKey: request.PublicKey, + MeshId: request.MeshId, + WgEndpoint: "[" + hostIp + "]" + ":" + strconv.Itoa(int(request.WgPort)), + } + + err = m.server.AddHost(addHostArgs) + + if err != nil { + return &JoinMeshReply{Success: false}, nil + } + + fmt.Println("success!") + return &JoinMeshReply{Success: true}, nil +} + +func NewRpcServer(ctlServer *ctrlserver.MeshCtrlServer) *grpc.Server { + server := &meshCtrlServer{server: ctlServer} + grpc := grpc.NewServer() + RegisterMeshCtrlServerServer(grpc, server) + return grpc +} diff --git a/pkg/ipc/ipctypes.go b/pkg/ipc/ipctypes.go index aca1b57..6eddbda 100644 --- a/pkg/ipc/ipctypes.go +++ b/pkg/ipc/ipctypes.go @@ -1,6 +1,12 @@ package ipc +import "github.com/tim-beatham/wgmesh/pkg/ctrlserver" + type JoinMeshArgs struct { MeshId string IpAdress string } + +type GetMeshReply struct { + Nodes []ctrlserver.MeshNode +} diff --git a/pkg/wg/wg.go b/pkg/wg/wg.go index 80450bf..48261b2 100644 --- a/pkg/wg/wg.go +++ b/pkg/wg/wg.go @@ -44,7 +44,7 @@ func CreateClient(ifName string) (*wgctrl.Client, error) { return nil, err } - wgListenPort := 5000 + wgListenPort := 51820 privateKey, err := wgtypes.GeneratePrivateKey() if err != nil {