mirror of
https://github.com/qdm12/gluetun.git
synced 2025-12-10 00:09:53 -06:00
140 lines
4.0 KiB
Go
140 lines
4.0 KiB
Go
package settings
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"regexp"
|
|
|
|
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
|
"github.com/qdm12/gluetun/internal/constants/providers"
|
|
"github.com/qdm12/gotree"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
)
|
|
|
|
// Wireguard contains settings to configure the Wireguard client.
|
|
type Wireguard struct {
|
|
// PrivateKey is the Wireguard client peer private key.
|
|
// It cannot be nil in the internal state.
|
|
PrivateKey *string
|
|
// PreSharedKey is the Wireguard pre-shared key.
|
|
// It can be the empty string to indicate there
|
|
// is no pre-shared key.
|
|
// It cannot be nil in the internal state.
|
|
PreSharedKey *string
|
|
// Addresses are the Wireguard interface addresses.
|
|
Addresses []net.IPNet
|
|
// Interface is the name of the Wireguard interface
|
|
// to create. It cannot be the empty string in the
|
|
// internal state.
|
|
Interface string
|
|
}
|
|
|
|
var regexpInterfaceName = regexp.MustCompile(`^[a-zA-Z0-9_]+$`)
|
|
|
|
// Validate validates Wireguard settings.
|
|
// It should only be ran if the VPN type chosen is Wireguard.
|
|
func (w Wireguard) validate(vpnProvider string) (err error) {
|
|
if !helpers.IsOneOf(vpnProvider,
|
|
providers.Custom,
|
|
providers.Ivpn,
|
|
providers.Mullvad,
|
|
providers.Surfshark,
|
|
providers.Windscribe,
|
|
) {
|
|
// do not validate for VPN provider not supporting Wireguard
|
|
return nil
|
|
}
|
|
|
|
// Validate PrivateKey
|
|
if *w.PrivateKey == "" {
|
|
return ErrWireguardPrivateKeyNotSet
|
|
}
|
|
_, err = wgtypes.ParseKey(*w.PrivateKey)
|
|
if err != nil {
|
|
return fmt.Errorf("private key is not valid: %w", err)
|
|
}
|
|
|
|
// Validate PreSharedKey
|
|
if *w.PreSharedKey != "" { // Note: this is optional
|
|
_, err = wgtypes.ParseKey(*w.PreSharedKey)
|
|
if err != nil {
|
|
return fmt.Errorf("pre-shared key is not valid: %w", err)
|
|
}
|
|
}
|
|
|
|
// Validate Addresses
|
|
if len(w.Addresses) == 0 {
|
|
return ErrWireguardInterfaceAddressNotSet
|
|
}
|
|
for i, ipNet := range w.Addresses {
|
|
if ipNet.IP == nil || ipNet.Mask == nil {
|
|
return fmt.Errorf("%w: for address at index %d: %s",
|
|
ErrWireguardInterfaceAddressNotSet, i, ipNet.String())
|
|
}
|
|
}
|
|
|
|
// Validate interface
|
|
if !regexpInterfaceName.MatchString(w.Interface) {
|
|
return fmt.Errorf("%w: '%s' does not match regex '%s'",
|
|
ErrWireguardInterfaceNotValid, w.Interface, regexpInterfaceName)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *Wireguard) copy() (copied Wireguard) {
|
|
return Wireguard{
|
|
PrivateKey: helpers.CopyStringPtr(w.PrivateKey),
|
|
PreSharedKey: helpers.CopyStringPtr(w.PreSharedKey),
|
|
Addresses: helpers.CopyIPNetSlice(w.Addresses),
|
|
Interface: w.Interface,
|
|
}
|
|
}
|
|
|
|
func (w *Wireguard) mergeWith(other Wireguard) {
|
|
w.PrivateKey = helpers.MergeWithStringPtr(w.PrivateKey, other.PrivateKey)
|
|
w.PreSharedKey = helpers.MergeWithStringPtr(w.PreSharedKey, other.PreSharedKey)
|
|
w.Addresses = helpers.MergeIPNetsSlices(w.Addresses, other.Addresses)
|
|
w.Interface = helpers.MergeWithString(w.Interface, other.Interface)
|
|
}
|
|
|
|
func (w *Wireguard) overrideWith(other Wireguard) {
|
|
w.PrivateKey = helpers.OverrideWithStringPtr(w.PrivateKey, other.PrivateKey)
|
|
w.PreSharedKey = helpers.OverrideWithStringPtr(w.PreSharedKey, other.PreSharedKey)
|
|
w.Addresses = helpers.OverrideWithIPNetsSlice(w.Addresses, other.Addresses)
|
|
w.Interface = helpers.OverrideWithString(w.Interface, other.Interface)
|
|
}
|
|
|
|
func (w *Wireguard) setDefaults() {
|
|
w.PrivateKey = helpers.DefaultStringPtr(w.PrivateKey, "")
|
|
w.PreSharedKey = helpers.DefaultStringPtr(w.PreSharedKey, "")
|
|
w.Interface = helpers.DefaultString(w.Interface, "wg0")
|
|
}
|
|
|
|
func (w Wireguard) String() string {
|
|
return w.toLinesNode().String()
|
|
}
|
|
|
|
func (w Wireguard) toLinesNode() (node *gotree.Node) {
|
|
node = gotree.New("Wireguard settings:")
|
|
|
|
if *w.PrivateKey != "" {
|
|
s := helpers.ObfuscateWireguardKey(*w.PrivateKey)
|
|
node.Appendf("Private key: %s", s)
|
|
}
|
|
|
|
if *w.PreSharedKey != "" {
|
|
s := helpers.ObfuscateWireguardKey(*w.PreSharedKey)
|
|
node.Appendf("Pre-shared key: %s", s)
|
|
}
|
|
|
|
addressesNode := node.Appendf("Interface addresses:")
|
|
for _, address := range w.Addresses {
|
|
addressesNode.Appendf(address.String())
|
|
}
|
|
|
|
node.Appendf("Network interface: %s", w.Interface)
|
|
|
|
return node
|
|
}
|