add configuration support for self overrides

This commit is contained in:
Jordan Whited 2021-01-01 17:15:04 -08:00 committed by Jordan Whited
parent 6f78170fbe
commit 77622af207
3 changed files with 132 additions and 31 deletions

View File

@ -2,6 +2,8 @@ package wgsd
import ( import (
"fmt" "fmt"
"net"
"strconv"
"github.com/coredns/caddy" "github.com/coredns/caddy"
"github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/core/dnsserver"
@ -11,45 +13,83 @@ import (
) )
func init() { func init() {
plugin.Register("wgsd", setup) plugin.Register(pluginName, setup)
}
const (
optionSelfAllowedIPs = "self-allowed-ips"
optionSelfEndpoint = "self-endpoint"
)
func parse(c *caddy.Controller) (*WGSD, error) {
p := &WGSD{}
for c.Next() {
args := c.RemainingArgs()
if len(args) != 2 {
return nil, fmt.Errorf("expected 2 args, got %d", len(args))
}
p.zone = dns.Fqdn(args[0])
p.device = args[1]
for c.NextBlock() {
switch c.Val() {
case optionSelfAllowedIPs:
p.selfAllowedIPs = make([]net.IPNet, 0)
for _, aip := range c.RemainingArgs() {
_, prefix, err := net.ParseCIDR(aip)
if err != nil {
return nil, fmt.Errorf("invalid self-allowed-ips: %s err: %v", c.Val(), err)
}
p.selfAllowedIPs = append(p.selfAllowedIPs, *prefix)
}
case optionSelfEndpoint:
endpoint := c.RemainingArgs()
if len(endpoint) != 1 {
return nil, fmt.Errorf("expected 1 arg, got %d", len(endpoint))
}
host, portS, err := net.SplitHostPort(endpoint[0])
if err != nil {
return nil, fmt.Errorf("invalid self-endpoint, err: %v", err)
}
port, err := strconv.Atoi(portS)
if err != nil {
return nil, fmt.Errorf("error converting self-endpoint port: %v", err)
}
ip := net.ParseIP(host)
if ip == nil {
return nil, fmt.Errorf("invalid self-endpoint, invalid IP address: %s", host)
}
p.selfEndpoint = &net.UDPAddr{
IP: ip,
Port: port,
}
default:
return nil, c.ArgErr()
}
}
}
return p, nil
} }
func setup(c *caddy.Controller) error { func setup(c *caddy.Controller) error {
c.Next() // Ignore "wgsd" and give us the next token. wgsd, err := parse(c)
if err != nil {
// return an error if there is no zone specified return plugin.Error(pluginName, err)
if !c.NextArg() {
return plugin.Error("wgsd", c.ArgErr())
} }
zone := dns.Fqdn(c.Val())
// return an error if there is no device name specified
if !c.NextArg() {
return plugin.Error("wgsd", c.ArgErr())
}
device := c.Val()
// return an error if there are more tokens on this line
if c.NextArg() {
return plugin.Error("wgsd", c.ArgErr())
}
client, err := wgctrl.New() client, err := wgctrl.New()
if err != nil { if err != nil {
return plugin.Error("wgsd", return plugin.Error(pluginName,
fmt.Errorf("error constructing wgctrl client: %v", fmt.Errorf("error constructing wgctrl client: %v",
err)) err))
} }
c.OnFinalShutdown(client.Close) c.OnFinalShutdown(client.Close)
wgsd.client = client
// Add the Plugin to CoreDNS, so Servers can use it in their plugin chain. // Add the Plugin to CoreDNS, so Servers can use it in their plugin chain.
dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
return &WGSD{ wgsd.Next = next
Next: next, return wgsd
client: client,
zone: zone,
device: device,
}
}) })
return nil return nil

View File

@ -8,24 +8,78 @@ import (
func TestSetup(t *testing.T) { func TestSetup(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
input string input string
expectErr bool expectErr bool
expectSelfAllowedIPs []string
expectSelfEndpoint []string
}{ }{
{ {
"valid input", "valid input",
"wgsd example.com. wg0", "wgsd example.com. wg0",
false, false,
nil,
nil,
}, },
{ {
"missing token", "missing token",
"wgsd example.com.", "wgsd example.com.",
true, true,
nil,
nil,
}, },
{ {
"too many tokens", "too many tokens",
"wgsd example.com. wg0 extra", "wgsd example.com. wg0 extra",
true, true,
nil,
nil,
},
{
"valid self-allowed-ips",
`wgsd example.com. wg0 {
self-allowed-ips 10.0.0.1/32 10.0.0.2/32
}`,
false,
nil,
nil,
},
{
"invalid self-allowed-ips",
`wgsd example.com. wg0 {
self-allowed-ips 10.0.01/32 10.0.0.2/32
}`,
true,
nil,
nil,
},
{
"valid self-endpoint",
`wgsd example.com. wg0 {
self-endpoint 127.0.0.1:51820
}`,
false,
nil,
nil,
},
{
"invalid self-endpoint",
`wgsd example.com. wg0 {
self-endpoint hostname:51820
}`,
true,
nil,
nil,
},
{
"all options",
`wgsd example.com. wg0 {
self-allowed-ips 10.0.0.1/32 10.0.0.2/32
self-endpoint 127.0.0.1:51820
}`,
false,
nil,
nil,
}, },
} }
@ -36,6 +90,9 @@ func TestSetup(t *testing.T) {
if (err != nil) != tc.expectErr { if (err != nil) != tc.expectErr {
t.Fatalf("expectErr: %v, got err=%v", tc.expectErr, err) t.Fatalf("expectErr: %v, got err=%v", tc.expectErr, err)
} }
if tc.expectErr {
return
}
}) })
} }
} }

View File

@ -16,7 +16,11 @@ import (
) )
// coredns plugin-specific logger // coredns plugin-specific logger
var logger = clog.NewWithPlugin("wgsd") var logger = clog.NewWithPlugin(pluginName)
const (
pluginName = "wgsd"
)
// WGSD is a CoreDNS plugin that provides WireGuard peer information via DNS-SD // WGSD is a CoreDNS plugin that provides WireGuard peer information via DNS-SD
// semantics. WGSD implements the plugin.Handler interface. // semantics. WGSD implements the plugin.Handler interface.
@ -300,5 +304,5 @@ func soa(zone string) dns.RR {
} }
func (p *WGSD) Name() string { func (p *WGSD) Name() string {
return "wgsd" return pluginName
} }