diff --git a/cmd/server.go b/cmd/server.go index 69bcd12..dff217e 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -2,8 +2,12 @@ package cmd import ( "log" + "net" + "net/http" + "os" "github.com/urfave/cli/v2" + "gopkg.in/ini.v1" ) var CmdServer = &cli.Command{ @@ -33,6 +37,11 @@ var CmdServer = &cli.Command{ Action: runServer, } +type request struct { + publicKey string + ip net.IP +} + func runServer(ctx *cli.Context) error { inter := ctx.String("interface") config := ctx.String("config") @@ -41,9 +50,15 @@ func runServer(ctx *cli.Context) error { } listen := ctx.String("listen") + addQueue := make(chan request) + go adder(addQueue, inter, config) + + gateQueue := make(chan request) + go gater(gateQueue, addQueue) + // TODO: Rate limiting - http.HandleFunc("/pub", func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc("/info", func(w http.ResponseWriter, r *http.Request) { // Produce the public key }) @@ -52,6 +67,7 @@ func runServer(ctx *cli.Context) error { // Assign an IP address // Enqueue request into the gate // Wait for flush of configuration + // Produce configuration to client }) log.Println(inter) @@ -60,3 +76,63 @@ func runServer(ctx *cli.Context) error { return nil } + +func adder(queue chan request, inter string, config string) { + // Write requests to config and add peer + for req := range queue { + configAddPeer(config, req) + interAddPeer(inter, req) + } +} + +func gater(queue chan request, result chan request) { + // Receive requests and prompt the admin + for req := range queue { + // For now, accept all + log.Println(req) + result <- req + } +} + +func configAddPeer(config string, req request) { + // For every request, we'll just open the config file again and rewrite it + // We don't need to optimise this because it happens infrequently + + // Preferably in the future, we treat the configuration as a database + + // For now, we append to the config file + cfg := ini.Empty() + sec, _ := cfg.NewSection("Peer") + publicKey := sec.Key("PublicKey") + // TODO: Do we need validation? + publicKey.SetValue(req.publicKey) + allowedIPs := sec.Key("AllowedIPs") + allowedHost := ipToIPNetWithHostMask(req.ip) + allowedIPs.AddShadow((&allowedHost).String()) + + f, err := os.OpenFile(config, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Fatal(err) + } + _, err = cfg.WriteTo(f) + if err != nil { + log.Fatal(err) + } +} + +func ipToIPNetWithHostMask(ip net.IP) net.IPNet { + if ip4 := ip.To4(); ip4 != nil { + return net.IPNet{ + IP: ip, + Mask: net.CIDRMask(32, 32), + } + } + return net.IPNet{ + IP: ip, + Mask: net.CIDRMask(128, 128), + } +} + +func interAddPeer(inter string, req request) { + +} diff --git a/go.mod b/go.mod index 96655b5..b0d71c9 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module github.com/serverwentdown/wireguard-negotiator go 1.13 -require github.com/urfave/cli/v2 v2.0.0 +require ( + github.com/urfave/cli/v2 v2.0.0 + gopkg.in/ini.v1 v1.51.0 +) diff --git a/go.sum b/go.sum index 0b808dd..3e76cf3 100644 --- a/go.sum +++ b/go.sum @@ -10,4 +10,6 @@ github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli/v2 v2.0.0 h1:+HU9SCbu8GnEUFtIBfuUNXN39ofWViIEJIp6SURMpCg= github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=