Skip to content

Commit

Permalink
feat(settings): parse Wireguard settings from `/gluetun/wireguard/wg0…
Browse files Browse the repository at this point in the history
….conf` (#1120)
  • Loading branch information
qdm12 committed Jul 22, 2023
1 parent c5cc240 commit 0ebfe53
Show file tree
Hide file tree
Showing 11 changed files with 703 additions and 4 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
golang.org/x/text v0.11.0
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde
gopkg.in/ini.v1 v1.67.0
inet.af/netaddr v0.0.0-20220811202034-502d2d690317
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ github.com/qdm12/golibs v0.0.0-20210603202746-e5494e9c2ebb/go.mod h1:15RBzkun0i8
github.com/qdm12/golibs v0.0.0-20210723175634-a75ca7fd74c2/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6 h1:bge5AL7cjHJMPz+5IOz5yF01q/l8No6+lIEBieA8gMg=
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
github.com/qdm12/gosettings v0.3.0-rc13 h1:fag+/hFPBUcNk3a5ifUbwNS2VgXFpxindkl8mQNk76U=
github.com/qdm12/gosettings v0.3.0-rc13/go.mod h1:JRV3opOpHvnKlIA29lKQMdYw1WSMVMfHYLLHPHol5ME=
github.com/qdm12/gosettings v0.4.0-rc1 h1:UYA92yyeDPbmZysIuG65yrpZVPtdIoRmtEHft/AyI38=
github.com/qdm12/gosettings v0.4.0-rc1/go.mod h1:JRV3opOpHvnKlIA29lKQMdYw1WSMVMfHYLLHPHol5ME=
github.com/qdm12/goshutdown v0.3.0 h1:pqBpJkdwlZlfTEx4QHtS8u8CXx6pG0fVo6S1N0MpSEM=
Expand Down Expand Up @@ -228,6 +226,8 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde/go.mod h1:m
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
Expand Down
3 changes: 3 additions & 0 deletions internal/configuration/sources/files/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package files

func ptrTo[T any](x T) *T { return &x }
16 changes: 16 additions & 0 deletions internal/configuration/sources/files/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package files

import (
"fmt"

"github.com/qdm12/gluetun/internal/configuration/settings"
)

func (s *Source) readProvider() (provider settings.Provider, err error) {
provider.ServerSelection, err = s.readServerSelection()
if err != nil {
return provider, fmt.Errorf("server selection: %w", err)
}

return provider, nil
}
9 changes: 7 additions & 2 deletions internal/configuration/sources/files/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import (
"github.com/qdm12/gluetun/internal/configuration/settings"
)

type Source struct{}
type Source struct {
wireguardConfigPath string
}

func New() *Source {
return &Source{}
const wireguardConfigPath = "/gluetun/wireguard/wg0.conf"
return &Source{
wireguardConfigPath: wireguardConfigPath,
}
}

func (s *Source) String() string { return "files" }
Expand Down
16 changes: 16 additions & 0 deletions internal/configuration/sources/files/serverselection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package files

import (
"fmt"

"github.com/qdm12/gluetun/internal/configuration/settings"
)

func (s *Source) readServerSelection() (selection settings.ServerSelection, err error) {
selection.Wireguard, err = s.readWireguardSelection()
if err != nil {
return selection, fmt.Errorf("wireguard: %w", err)
}

return selection, nil
}
10 changes: 10 additions & 0 deletions internal/configuration/sources/files/vpn.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,20 @@ import (
)

func (s *Source) readVPN() (vpn settings.VPN, err error) {
vpn.Provider, err = s.readProvider()
if err != nil {
return vpn, fmt.Errorf("provider: %w", err)
}

vpn.OpenVPN, err = s.readOpenVPN()
if err != nil {
return vpn, fmt.Errorf("OpenVPN: %w", err)
}

vpn.Wireguard, err = s.readWireguard()
if err != nil {
return vpn, fmt.Errorf("wireguard: %w", err)
}

return vpn, nil
}
111 changes: 111 additions & 0 deletions internal/configuration/sources/files/wireguard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package files

import (
"fmt"
"net/netip"
"regexp"
"strings"

"github.com/qdm12/gluetun/internal/configuration/settings"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"gopkg.in/ini.v1"
)

var (
regexINISectionNotExist = regexp.MustCompile(`^section ".+" does not exist$`)
regexINIKeyNotExist = regexp.MustCompile(`key ".*" not exists$`)
)

func (s *Source) readWireguard() (wireguard settings.Wireguard, err error) {
fileStringPtr, err := ReadFromFile(s.wireguardConfigPath)
if err != nil {
return wireguard, fmt.Errorf("reading file: %w", err)
}

if fileStringPtr == nil {
return wireguard, nil
}

rawData := []byte(*fileStringPtr)
iniFile, err := ini.Load(rawData)
if err != nil {
return wireguard, fmt.Errorf("loading ini from reader: %w", err)
}

interfaceSection, err := iniFile.GetSection("Interface")
if err == nil {
err = parseWireguardInterfaceSection(interfaceSection, &wireguard)
if err != nil {
return wireguard, fmt.Errorf("parsing interface section: %w", err)
}
} else if !regexINISectionNotExist.MatchString(err.Error()) {
// can never happen
return wireguard, fmt.Errorf("getting interface section: %w", err)
}

return wireguard, nil
}

func parseWireguardInterfaceSection(interfaceSection *ini.Section,
wireguard *settings.Wireguard) (err error) {
wireguard.PrivateKey, err = parseINIWireguardKey(interfaceSection, "PrivateKey")
if err != nil {
return err // error is already wrapped correctly
}

wireguard.PreSharedKey, err = parseINIWireguardKey(interfaceSection, "PreSharedKey")
if err != nil {
return err // error is already wrapped correctly
}

wireguard.Addresses, err = parseINIWireguardAddress(interfaceSection)
if err != nil {
return err // error is already wrapped correctly
}

return nil
}

func parseINIWireguardKey(section *ini.Section, keyName string) (
key *string, err error) {
iniKey, err := section.GetKey(keyName)
if err != nil {
if regexINIKeyNotExist.MatchString(err.Error()) {
return nil, nil //nolint:nilnil
}
// can never happen
return nil, fmt.Errorf("getting %s key: %w", keyName, err)
}

key = new(string)
*key = iniKey.String()
_, err = wgtypes.ParseKey(*key)
if err != nil {
return nil, fmt.Errorf("parsing %s: %s: %w", keyName, *key, err)
}
return key, nil
}

func parseINIWireguardAddress(section *ini.Section) (
addresses []netip.Prefix, err error) {
addressKey, err := section.GetKey("Address")
if err != nil {
if regexINIKeyNotExist.MatchString(err.Error()) {
return nil, nil
}
// can never happen
return nil, fmt.Errorf("getting Address key: %w", err)
}

addressStrings := strings.Split(addressKey.String(), ",")
addresses = make([]netip.Prefix, len(addressStrings))
for i, addressString := range addressStrings {
addressString = strings.TrimSpace(addressString)
addresses[i], err = netip.ParsePrefix(addressString)
if err != nil {
return nil, fmt.Errorf("parsing address: %w", err)
}
}

return addresses, nil
}

0 comments on commit 0ebfe53

Please sign in to comment.