Initial prototype server
parent
5801fb1087
commit
42eb0ea8ef
43
README.md
43
README.md
|
@ -11,7 +11,7 @@ In summary:
|
|||
|
||||
* Manage "client" keys
|
||||
* Exchange keys over HTTP(S)
|
||||
* Exchange IP addressing (DHCP-like)
|
||||
* Exchange IP addressing
|
||||
* Manually gate new peers
|
||||
* Sets up network interface on the "client"
|
||||
* Generate Ansible INI inventory
|
||||
|
@ -27,3 +27,44 @@ The primary scenario this tool is going to be used for is to manage machines usi
|
|||
# Usage
|
||||
|
||||
> TODO
|
||||
|
||||
# Operation
|
||||
|
||||
## Server
|
||||
|
||||
The "server" manages a WireGuard interface, treating a WireGuard configuration file as a database. It assumes this interface and configuration exists. It only adds new peers to the configuration file and interface, and does not delete existing configuration.
|
||||
|
||||
The "server" also exposes the HTTP server with the following endpoints:
|
||||
|
||||
### `POST /request`
|
||||
|
||||
Request for the assignment of an IP address and accepted as a peer. This blocks until the server has finished configuring the peer, therefore the client SHOULD NOT timeout.
|
||||
|
||||
#### Request Body
|
||||
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
| Name | Description | Required |
|
||||
|------|-------------|----------|
|
||||
| PublicKey | The public key of the "client" peer | X |
|
||||
|
||||
#### Response Body
|
||||
|
||||
Content-Type: application/json
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| PublicKey | String | Base64 encoded public key of the "server" peer |
|
||||
| Endpoint | String | The endpoint of the "server" peer |
|
||||
| PersistentKeepaliveInterval | Number | Suggests a PersistentKeepaliveInterval |
|
||||
| AllowedIPs | []String | List of allowed IP addresses in CIDR notation |
|
||||
| InterfaceIPs | []String | List of IP addresses assigned to the "client" interface |
|
||||
|
||||
## Client
|
||||
|
||||
The "client" sets up a WireGuard interface, and relies on network backends to do so. *It should not be run more than once*. The following network backends are supported:
|
||||
|
||||
- (Not implemented) `none`: Creates an interface and WireGuard configuration file
|
||||
- `networkd`: Creates a `systemd.netdev` file in `/etc/systemd/network`
|
||||
|
||||
It does so by performing `POST /request` to the "server".
|
||||
|
|
|
@ -19,33 +19,58 @@ var CmdRequest = &cli.Command{
|
|||
Usage: "Name for new WireGuard interface",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Name: "none",
|
||||
Aliases: []string{"c"},
|
||||
Value: "",
|
||||
DefaultText: "/etc/wireguard/<interface>.conf",
|
||||
Usage: "Path to the WireGuard configuration file",
|
||||
Usage: "Path to save a WireGuard configuration file",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "type",
|
||||
Value: "none",
|
||||
Usage: "Select network interface backend. Currently only none and networkd are implemented",
|
||||
Name: "networkd",
|
||||
Aliases: []string{"n"},
|
||||
Value: "",
|
||||
DefaultText: "/etc/systemd/network/<interface>.netdev",
|
||||
Usage: "Path to save a networkd configuration file",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "type",
|
||||
Aliases: []string{"t"},
|
||||
Value: "networkd",
|
||||
Usage: "Select network interface backend. Currently only networkd is implemented",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "server",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "wireguard-negotiator server URL",
|
||||
Required: true,
|
||||
EnvVars: []string{"WGN_SERVER_URL"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "insecure",
|
||||
Usage: "Disable TLS verification",
|
||||
EnvVars: []string{"WGN_SERVER_INSECURE"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func runRequest(ctx *cli.Context) error {
|
||||
inter := ctx.String("interface")
|
||||
config := ctx.String("config")
|
||||
if !ctx.IsSet("config") {
|
||||
config = "/etc/wireguard/" + inter + ".conf"
|
||||
}
|
||||
netBackend := ctx.String("type")
|
||||
noneConfig := ctx.String("none")
|
||||
if !ctx.IsSet("none") {
|
||||
noneConfig = "/etc/wireguard/" + inter + ".conf"
|
||||
}
|
||||
networkdConfig := ctx.String("networkd")
|
||||
if !ctx.IsSet("networkd") {
|
||||
networkdConfig = "/etc/systemd/network/" + inter + ".netdev"
|
||||
}
|
||||
|
||||
client := lib.NewClient(ctx.String("server"), ctx.Bool("insecure"))
|
||||
|
||||
log.Println(inter)
|
||||
log.Println(config)
|
||||
log.Println(netBackend)
|
||||
log.Println(noneConfig)
|
||||
log.Println(networkdConfig)
|
||||
log.Println(client)
|
||||
|
||||
return nil
|
||||
|
|
218
cmd/server.go
218
cmd/server.go
|
@ -1,16 +1,23 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
var ErrNoAddressesFound = fmt.Errorf("No address found on the interface")
|
||||
|
||||
var CmdServer = &cli.Command{
|
||||
Name: "server",
|
||||
Usage: "Start the wireguard-negotiator server",
|
||||
|
@ -26,13 +33,14 @@ var CmdServer = &cli.Command{
|
|||
Aliases: []string{"c"},
|
||||
Value: "",
|
||||
DefaultText: "/etc/wireguard/<interface>.conf",
|
||||
Usage: "Path to the WireGuard configuration file",
|
||||
Usage: "Path to the existing WireGuard configuration file",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "endpoint",
|
||||
Aliases: []string{"e"},
|
||||
Value: "",
|
||||
Usage: "Set the endpoint address",
|
||||
Name: "endpoint",
|
||||
Aliases: []string{"e"},
|
||||
Value: "",
|
||||
Required: true,
|
||||
Usage: "Set the endpoint address",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "listen",
|
||||
|
@ -51,33 +59,37 @@ type request struct {
|
|||
|
||||
func runServer(ctx *cli.Context) error {
|
||||
inter := ctx.String("interface")
|
||||
interf, err := net.InterfaceByName(inter)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
config := ctx.String("config")
|
||||
if !ctx.IsSet("config") {
|
||||
config = "/etc/wireguard/" + inter + ".conf"
|
||||
}
|
||||
endpoint := ctx.String("endpoint")
|
||||
if !ctx.IsSet("endpoint") {
|
||||
log.Fatal("Please specify endpoint with -endpoint")
|
||||
}
|
||||
listen := ctx.String("listen")
|
||||
|
||||
// Obtain the server's public key
|
||||
serverPublicKey := configReadInterfacePublicKey(config)
|
||||
// Obtain the network interface
|
||||
interf, err := net.InterfaceByName(inter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Obtain the server's public key
|
||||
serverPublicKey, err := configReadInterfacePublicKey(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Define this allocation method
|
||||
// TODO: Include allocation behaviour in README
|
||||
terribleCounterThatShouldNotExist := 1
|
||||
interfAddrs, err := interf.Addrs()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
// TODO: Define this allocation method
|
||||
// TODO: Include allocation behaviour in README
|
||||
|
||||
// Obtain interface address for use in allocation
|
||||
var interfIPNet *net.IPNet
|
||||
if len(interfAddrs) < 1 {
|
||||
log.Fatal("No address found on the interface")
|
||||
return ErrNoAddressesFound
|
||||
}
|
||||
_, interfIPNet, err = net.ParseCIDR(interfAddrs[0].String())
|
||||
|
||||
|
@ -90,62 +102,112 @@ func runServer(ctx *cli.Context) error {
|
|||
// TODO: Rate limiting
|
||||
|
||||
http.HandleFunc("/request", func(w http.ResponseWriter, r *http.Request) {
|
||||
publicKey := r.PostFormValue("public_key")
|
||||
// TODO: Ensure public key is new
|
||||
// Assign an IP address
|
||||
terribleCounterThatShouldNotExist += 1
|
||||
ip := incrementIP(interfIPNet.IP, terribleCounterThatShouldNotExist)
|
||||
if !interfIPNet.Contains(ip) {
|
||||
log.Fatal("Ran out of IP addresses to allocate")
|
||||
}
|
||||
// Enqueue request into the gate
|
||||
req := request{
|
||||
ip: ip,
|
||||
publicKey: publicKey,
|
||||
}
|
||||
// Wait for flush of configuration
|
||||
gateQueue <- req
|
||||
// Produce configuration to client
|
||||
ipNet := &net.IPNet{
|
||||
IP: ip,
|
||||
Mask: interfIPNet.Mask,
|
||||
}
|
||||
resp := struct {
|
||||
interfaceIP string `json:"interface_ip"`
|
||||
peerAllowedIPs string `json:"peer_allowed_ips"`
|
||||
peerPublicKey string `json:"peer_public_key"`
|
||||
peerEndpoint string `json:"peer_endpoint"`
|
||||
}{
|
||||
ipNet.String(),
|
||||
interfIPNet.IP.Mask(interfIPNet.Mask),
|
||||
"",
|
||||
"",
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
publicKey := r.PostFormValue("PublicKey")
|
||||
// TODO: Ensure public key is new
|
||||
if len(publicKey) == 0 {
|
||||
w.WriteHeader(400)
|
||||
return
|
||||
}
|
||||
|
||||
// Assign an IP address
|
||||
terribleCounterThatShouldNotExist += 1
|
||||
ip := incrementIP(interfIPNet.IP, terribleCounterThatShouldNotExist)
|
||||
if !interfIPNet.Contains(ip) {
|
||||
log.Println("WARNING: Ran out of addresses to allocate")
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
|
||||
// Enqueue request into the gate
|
||||
req := request{
|
||||
ip: ip,
|
||||
publicKey: publicKey,
|
||||
}
|
||||
|
||||
// Wait for flush of configuration
|
||||
gateQueue <- req
|
||||
|
||||
// Produce configuration to client
|
||||
ipNet := &net.IPNet{
|
||||
IP: ip,
|
||||
Mask: interfIPNet.Mask,
|
||||
}
|
||||
resp := struct {
|
||||
InterfaceIPs string
|
||||
AllowedIPs string
|
||||
PublicKey string
|
||||
Endpoint string
|
||||
PersistentKeepaliveInterval int
|
||||
}{
|
||||
ipNet.String(),
|
||||
interfIPNet.IP.Mask(interfIPNet.Mask).String(),
|
||||
serverPublicKey,
|
||||
endpoint,
|
||||
25,
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
default:
|
||||
w.WriteHeader(405)
|
||||
}
|
||||
})
|
||||
|
||||
http.ListenAndServe(listen, nil)
|
||||
// Shutdown notifier
|
||||
go func() {
|
||||
sigint := make(chan os.Signal, 1)
|
||||
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigint
|
||||
close(gateQueue)
|
||||
close(addQueue)
|
||||
/*
|
||||
if err := http.Shutdown(context.Background()); err != nil {
|
||||
log.Printf("Server shutdown error: %v\n", err)
|
||||
}
|
||||
*/
|
||||
}()
|
||||
|
||||
return nil
|
||||
return http.ListenAndServe(listen, 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, config)
|
||||
for {
|
||||
select {
|
||||
case req, ok := <-queue:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
err := configAddPeer(config, req)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
err = interAddPeer(inter, req, config)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
for {
|
||||
select {
|
||||
case req, ok := <-queue:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
// For now, accept all
|
||||
log.Println(req.ip.String(), req.publicKey)
|
||||
result <- req
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func configAddPeer(config string, req request) {
|
||||
func configAddPeer(config string, req request) error {
|
||||
// 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
|
||||
|
||||
|
@ -159,36 +221,44 @@ func configAddPeer(config string, req request) {
|
|||
publicKey.SetValue(req.publicKey)
|
||||
allowedIPs := sec.Key("AllowedIPs")
|
||||
allowedHost := ipToIPNetWithHostMask(req.ip)
|
||||
allowedIPs.AddShadow((&allowedHost).String())
|
||||
allowedIPs.SetValue((&allowedHost).String())
|
||||
|
||||
f, err := os.OpenFile(config, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return fmt.Errorf("opening %s failed: %w", config, err)
|
||||
}
|
||||
_, err = cfg.WriteTo(f)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return fmt.Errorf("writing to %s failed: %w", config, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func configReadInterfacePublicKey(config string) string {
|
||||
func configReadInterfacePublicKey(config string) (string, error) {
|
||||
cfg, err := ini.Load(config)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to read interface public key")
|
||||
return "", fmt.Errorf("read interface public key failed: %w", err)
|
||||
}
|
||||
|
||||
return cfg.Section("Interface").Key("PrivateKey")
|
||||
b64PrivateKey := cfg.Section("Interface").Key("PrivateKey").String()
|
||||
wgPrivateKey, err := wgtypes.ParseKey(b64PrivateKey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("read interface public key failed: %w", err)
|
||||
}
|
||||
wgPublicKey := wgPrivateKey.PublicKey()
|
||||
return wgPublicKey.String(), nil
|
||||
}
|
||||
|
||||
func interAddPeer(inter string, req request, config string) {
|
||||
func interAddPeer(inter string, req request, config string) error {
|
||||
// For every request, we also need to dynamically add the peer to the interface
|
||||
|
||||
// For now, we simply run one fixed command to reread from the config file
|
||||
cmd := exec.Command("wg", "setconf", inter, config)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return fmt.Errorf("wq setconf failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
@ -206,11 +276,19 @@ func ipToIPNetWithHostMask(ip net.IP) net.IPNet {
|
|||
}
|
||||
}
|
||||
|
||||
func incrementIP(ip net.IP) net.IP {
|
||||
func incrementIP(ip net.IP, inc int) net.IP {
|
||||
result := make(net.IP, len(ip))
|
||||
copy(result, ip)
|
||||
|
||||
for i := len(ip) - 1; i >= 0; i-- {
|
||||
ip[i]++
|
||||
if ip[i] != 0 {
|
||||
break
|
||||
remainder := inc % 256
|
||||
overflow := int(result[i])+remainder > 255
|
||||
|
||||
result[i] += byte(remainder)
|
||||
if overflow {
|
||||
inc += 256
|
||||
}
|
||||
inc /= 256
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
1
go.mod
1
go.mod
|
@ -4,5 +4,6 @@ go 1.13
|
|||
|
||||
require (
|
||||
github.com/urfave/cli/v2 v2.0.0
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20191219145116-fa6499c8e75f
|
||||
gopkg.in/ini.v1 v1.51.0
|
||||
)
|
||||
|
|
32
go.sum
32
go.sum
|
@ -1,6 +1,13 @@
|
|||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||
github.com/mdlayher/genetlink v0.0.0-20191205172946-651acf4b47ef/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
|
||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
|
@ -9,6 +16,31 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
|||
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=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191218084908-4a24b4065292/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.zx2c4.com/wireguard v0.0.20191012 h1:sdX+y3hrHkW8KJkjY7ZgzpT5Tqo8XnBkH55U1klphko=
|
||||
golang.zx2c4.com/wireguard v0.0.20191012/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20191219145116-fa6499c8e75f h1:xc7xbwx/flY4HCaTpfgGqvsEMELJ5EBF82MP2lvfdbo=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20191219145116-fa6499c8e75f/go.mod h1:QKgTDEXdhtb9dg1EdxK63hefKjD1e+bSXUbRmZBfCSw=
|
||||
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=
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
//"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
// ReadConfig is yet another INI-like configuration file parser, but for WireGuard
|
|
@ -0,0 +1,23 @@
|
|||
package lib
|
||||
|
||||
import "testing"
|
||||
|
||||
var testGoodConfiguration1 = `
|
||||
# Test = Example comment
|
||||
|
||||
[Interface]
|
||||
# Test comment 2
|
||||
ListenPort = 3333
|
||||
PrivateKey = MITUgapB4QfRFF54ITXL3TaiYiSsVYkchqfjAXjxM10=
|
||||
[Peer]
|
||||
PublicKey = pjFx72IjbMh84SH1nq8Qfbl7HD5mSScHXCV1eISR7lk=
|
||||
AllowedIPs = 192.168.10.2/32, 2001:470:ed5d:a::2/128
|
||||
|
||||
[Peer]
|
||||
AllowedIPs = 192.168.10.40/32, 2001:470:ed5d:a::28/128
|
||||
PublicKey = wXU+vSTdEoIwSi+Tmv35SCOFg17wCAwnmYxeQPpbzDg=
|
||||
`
|
||||
|
||||
func TestReadConfig(t *testing.T) {
|
||||
|
||||
}
|
14
main.go
14
main.go
|
@ -13,19 +13,7 @@ func main() {
|
|||
app := &cli.App{
|
||||
Name: "wireguard-negotiator",
|
||||
Usage: "Exchange WireGuard keys over HTTP(S)",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "server",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "wireguard-negotiator server URL",
|
||||
EnvVars: []string{"WGN_SERVER_URL"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "insecure",
|
||||
Usage: "Disable TLS verification",
|
||||
EnvVars: []string{"WGN_SERVER_INSECURE"},
|
||||
},
|
||||
},
|
||||
Flags: []cli.Flag{},
|
||||
Commands: []*cli.Command{
|
||||
cmd.CmdServer,
|
||||
cmd.CmdList,
|
||||
|
|
Loading…
Reference in New Issue