wireguard: adds wgN.conf parser
Signed-off-by: Alejandro Mery <amery@jpi.io>
This commit is contained in:
@@ -3,16 +3,17 @@ module git.jpi.io/amery/jpictl
|
|||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
darvaza.org/core v0.9.5
|
||||||
darvaza.org/resolver v0.5.2
|
darvaza.org/resolver v0.5.2
|
||||||
darvaza.org/sidecar v0.0.0-20230721122716-b9c54b8adbaf
|
darvaza.org/sidecar v0.0.0-20230721122716-b9c54b8adbaf
|
||||||
darvaza.org/slog v0.5.2
|
darvaza.org/slog v0.5.2
|
||||||
github.com/burntSushi/toml v0.3.1
|
github.com/burntSushi/toml v0.3.1
|
||||||
github.com/mgechev/revive v1.3.2
|
github.com/mgechev/revive v1.3.2
|
||||||
github.com/spf13/cobra v1.7.0
|
github.com/spf13/cobra v1.7.0
|
||||||
|
gopkg.in/gcfg.v1 v1.2.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
darvaza.org/core v0.9.5 // indirect
|
|
||||||
darvaza.org/slog/handlers/filter v0.4.4 // indirect
|
darvaza.org/slog/handlers/filter v0.4.4 // indirect
|
||||||
darvaza.org/slog/handlers/zerolog v0.4.4 // indirect
|
darvaza.org/slog/handlers/zerolog v0.4.4 // indirect
|
||||||
github.com/BurntSushi/toml v1.3.2 // 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/sys v0.11.0 // indirect
|
||||||
golang.org/x/text v0.12.0 // indirect
|
golang.org/x/text v0.12.0 // indirect
|
||||||
golang.org/x/tools v0.12.0 // indirect
|
golang.org/x/tools v0.12.0 // indirect
|
||||||
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
|
||||||
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
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/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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// Package wireguard deals with wireguard config
|
||||||
|
package wireguard
|
||||||
Reference in New Issue
Block a user