Browse Source

wireguard: adds wgN.conf parser

Signed-off-by: Alejandro Mery <amery@jpi.io>
pull/1/head
Alejandro Mery 1 year ago
parent
commit
5d946e4e93
  1. 4
      go.mod
  2. 4
      go.sum
  3. 201
      pkg/wireguard/config.go
  4. 2
      pkg/wireguard/wireguard.go

4
go.mod

@ -3,16 +3,17 @@ module git.jpi.io/amery/jpictl
go 1.19
require (
darvaza.org/core v0.9.5
darvaza.org/resolver v0.5.2
darvaza.org/sidecar v0.0.0-20230721122716-b9c54b8adbaf
darvaza.org/slog v0.5.2
github.com/burntSushi/toml v0.3.1
github.com/mgechev/revive v1.3.2
github.com/spf13/cobra v1.7.0
gopkg.in/gcfg.v1 v1.2.3
)
require (
darvaza.org/core v0.9.5 // indirect
darvaza.org/slog/handlers/filter v0.4.4 // indirect
darvaza.org/slog/handlers/zerolog v0.4.4 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
@ -36,4 +37,5 @@ require (
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/tools v0.12.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)

4
go.sum

@ -87,6 +87,10 @@ golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

201
pkg/wireguard/config.go

@ -0,0 +1,201 @@
package wireguard
import (
"encoding/base64"
"errors"
"io"
"net/netip"
"strconv"
"strings"
"darvaza.org/core"
"gopkg.in/gcfg.v1"
)
// Config represents a wgN.conf file
type Config struct {
Interface InterfaceConfig
Peer []PeerConfig
}
// GetAddress is a shortcut to the interface's address
func (f *Config) GetAddress() netip.Addr {
return f.Interface.Address
}
// Peers tells how many peers are described
func (f *Config) Peers() int {
return len(f.Peer)
}
// InterfaceConfig represents the [Interface] section
type InterfaceConfig struct {
Address netip.Addr
PrivateKey []byte
ListenPort uint16
}
// PeerConfig represents a [Peer] section
type PeerConfig struct {
PublicKey []byte
Endpoint EndpointAddress
AllowedIPs []netip.Prefix
}
// EndpointAddress is a host:port pair to reach the Peer
type EndpointAddress struct {
Name string
Port uint16
}
// FromString sets the EndpointAddress from a given "[host]:port"
func (ep *EndpointAddress) FromString(s string) error {
host, port, err := core.SplitHostPort(s)
if err != nil {
return err
}
ep.Name = host
switch {
case port != "":
n, _ := strconv.ParseUint(port, 10, 16)
ep.Port = uint16(n)
default:
ep.Port = 0
}
return nil
}
type intermediateConfig struct {
Interface interfaceConfig
Peer peersConfig
}
func (v *intermediateConfig) Export() (*Config, error) {
var out Config
var err error
// Interface
out.Interface, err = v.Interface.Export()
if err != nil {
return nil, err
}
// Peers
peers, ok := v.PeersCount()
if !ok {
return nil, errors.New("inconsistent Peer data")
}
for i := 0; i < peers; i++ {
p, err := v.ExportPeer(i)
if err != nil {
err = core.Wrapf(err, "Peer[%v]:", i)
return nil, err
}
out.Peer = append(out.Peer, p)
}
return &out, nil
}
type interfaceConfig struct {
Address netip.Addr
PrivateKey string
ListenPort uint16
}
func (p interfaceConfig) Export() (InterfaceConfig, error) {
out := InterfaceConfig{
Address: p.Address,
ListenPort: p.ListenPort,
}
b, err := base64.StdEncoding.DecodeString(p.PrivateKey)
if err != nil {
err = core.Wrap(err, "PrivateKey")
return InterfaceConfig{}, err
}
out.PrivateKey = b
return out, nil
}
type peersConfig struct {
PublicKey []string
Endpoint []string
AllowedIPs []string
}
func (v *intermediateConfig) ExportPeer(i int) (PeerConfig, error) {
var out PeerConfig
// Endpoint
s := v.Peer.Endpoint[i]
err := out.Endpoint.FromString(s)
if err != nil {
err = core.Wrap(err, "Endpoint")
return out, err
}
// PublicKey
s = v.Peer.PublicKey[i]
out.PublicKey, err = base64.StdEncoding.DecodeString(s)
if err != nil {
err = core.Wrap(err, "PublicKey")
return out, err
}
// AllowedIPs
s = v.Peer.AllowedIPs[i]
out.AllowedIPs, err = parseAllowedIPs(s)
if err != nil {
err = core.Wrap(err, "AllowedIPs")
return out, err
}
return out, nil
}
func parseAllowedIPs(data string) ([]netip.Prefix, error) {
var out []netip.Prefix
for _, s := range strings.Split(data, ",") {
s = strings.TrimSpace(s)
p, err := netip.ParsePrefix(s)
if err != nil {
return out, err
}
out = append(out, p)
}
return out, nil
}
func (v *intermediateConfig) PeersCount() (int, bool) {
c0 := len(v.Peer.Endpoint)
c1 := len(v.Peer.PublicKey)
c2 := len(v.Peer.AllowedIPs)
if c0 != c1 || c1 != c2 {
return 0, false
}
return c0, true
}
// NewConfigFromReader parses a wgN.conf file
func NewConfigFromReader(r io.Reader) (*Config, error) {
temp := &intermediateConfig{}
if err := gcfg.ReadInto(temp, r); err != nil {
return nil, err
}
return temp.Export()
}

2
pkg/wireguard/wireguard.go

@ -0,0 +1,2 @@
// Package wireguard deals with wireguard config
package wireguard
Loading…
Cancel
Save