chore(settings): refactor settings processing (#756)
- Better settings tree structure logged using `qdm12/gotree` - Read settings from environment variables, then files, then secret files - Settings methods to default them, merge them and override them - `DNS_PLAINTEXT_ADDRESS` default changed to `127.0.0.1` to use DoT. Warning added if set to something else. - `HTTPPROXY_LISTENING_ADDRESS` instead of `HTTPPROXY_PORT` (with retro-compatibility)
This commit is contained in:
144
internal/configuration/settings/wireguardselection.go
Normal file
144
internal/configuration/settings/wireguardselection.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
|
||||
"github.com/qdm12/gluetun/internal/constants"
|
||||
"github.com/qdm12/gotree"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
)
|
||||
|
||||
type WireguardSelection struct {
|
||||
// EndpointIP is the server endpoint IP address.
|
||||
// It is only used with VPN providers generating Wireguard
|
||||
// configurations specific to each server and user.
|
||||
// To indicate it should not be used, it should be set
|
||||
// to the empty net.IP{} slice. It can never be nil
|
||||
// in the internal state.
|
||||
EndpointIP net.IP
|
||||
// EndpointPort is a the server port to use for the VPN server.
|
||||
// It is optional for VPN providers IVPN, Mullvad
|
||||
// and Windscribe, and compulsory for the others.
|
||||
// When optional, it can be set to 0 to indicate not use
|
||||
// a custom endpoint port. It cannot be nil in the internal
|
||||
// state.
|
||||
EndpointPort *uint16
|
||||
// PublicKey is the server public key.
|
||||
// It is only used with VPN providers generating Wireguard
|
||||
// configurations specific to each server and user.
|
||||
PublicKey string
|
||||
}
|
||||
|
||||
// Validate validates WireguardSelection settings.
|
||||
// It should only be ran if the VPN type chosen is Wireguard.
|
||||
func (w WireguardSelection) validate(vpnProvider string) (err error) {
|
||||
// Validate EndpointIP
|
||||
switch vpnProvider {
|
||||
case constants.Ivpn, constants.Mullvad, constants.Windscribe: // endpoint IP addresses are baked in
|
||||
case constants.Custom:
|
||||
if len(w.EndpointIP) == 0 {
|
||||
return ErrWireguardEndpointIPNotSet
|
||||
}
|
||||
default: // Providers not supporting Wireguard
|
||||
}
|
||||
|
||||
// Validate EndpointPort
|
||||
switch vpnProvider {
|
||||
// EndpointPort is required
|
||||
case constants.Custom:
|
||||
if *w.EndpointPort == 0 {
|
||||
return ErrWireguardEndpointPortNotSet
|
||||
}
|
||||
case constants.Ivpn, constants.Mullvad, constants.Windscribe:
|
||||
// EndpointPort is optional and can be 0
|
||||
if *w.EndpointPort == 0 {
|
||||
break // no custom endpoint port set
|
||||
}
|
||||
if vpnProvider == constants.Mullvad {
|
||||
break // no restriction on custom endpoint port value
|
||||
}
|
||||
var allowed []uint16
|
||||
switch vpnProvider {
|
||||
case constants.Ivpn:
|
||||
allowed = []uint16{2049, 2050, 53, 30587, 41893, 48574, 58237}
|
||||
case constants.Windscribe:
|
||||
allowed = []uint16{53, 80, 123, 443, 1194, 65142}
|
||||
}
|
||||
|
||||
if helpers.Uint16IsOneOf(*w.EndpointPort, allowed) {
|
||||
break
|
||||
}
|
||||
return fmt.Errorf("%w: %d for VPN service provider %s; %s",
|
||||
ErrWireguardEndpointPortNotAllowed, w.EndpointPort, vpnProvider,
|
||||
helpers.PortChoicesOrString(allowed))
|
||||
default: // Providers not supporting Wireguard
|
||||
}
|
||||
|
||||
// Validate PublicKey
|
||||
switch vpnProvider {
|
||||
case constants.Ivpn, constants.Mullvad, constants.Windscribe: // public keys are baked in
|
||||
case constants.Custom:
|
||||
if w.PublicKey == "" {
|
||||
return ErrWireguardPublicKeyNotSet
|
||||
}
|
||||
default: // Providers not supporting Wireguard
|
||||
}
|
||||
if w.PublicKey != "" {
|
||||
_, err := wgtypes.ParseKey(w.PublicKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %s: %s",
|
||||
ErrWireguardPublicKeyNotValid, w.PublicKey, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WireguardSelection) copy() (copied WireguardSelection) {
|
||||
return WireguardSelection{
|
||||
EndpointIP: helpers.CopyIP(w.EndpointIP),
|
||||
EndpointPort: helpers.CopyUint16Ptr(w.EndpointPort),
|
||||
PublicKey: w.PublicKey,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WireguardSelection) mergeWith(other WireguardSelection) {
|
||||
w.EndpointIP = helpers.MergeWithIP(w.EndpointIP, other.EndpointIP)
|
||||
w.EndpointPort = helpers.MergeWithUint16(w.EndpointPort, other.EndpointPort)
|
||||
w.PublicKey = helpers.MergeWithString(w.PublicKey, other.PublicKey)
|
||||
}
|
||||
|
||||
func (w *WireguardSelection) overrideWith(other WireguardSelection) {
|
||||
w.EndpointIP = helpers.OverrideWithIP(w.EndpointIP, other.EndpointIP)
|
||||
w.EndpointPort = helpers.OverrideWithUint16(w.EndpointPort, other.EndpointPort)
|
||||
w.PublicKey = helpers.OverrideWithString(w.PublicKey, other.PublicKey)
|
||||
}
|
||||
|
||||
func (w *WireguardSelection) setDefaults() {
|
||||
w.EndpointIP = helpers.DefaultIP(w.EndpointIP, net.IP{})
|
||||
w.EndpointPort = helpers.DefaultUint16(w.EndpointPort, 0)
|
||||
}
|
||||
|
||||
func (w WireguardSelection) String() string {
|
||||
return w.toLinesNode().String()
|
||||
}
|
||||
|
||||
func (w WireguardSelection) toLinesNode() (node *gotree.Node) {
|
||||
node = gotree.New("Wireguard selection settings:")
|
||||
|
||||
if len(w.EndpointIP) > 0 {
|
||||
node.Appendf("Endpoint IP address: %s", w.EndpointIP)
|
||||
}
|
||||
|
||||
if *w.EndpointPort != 0 {
|
||||
node.Appendf("Endpoint port: %d", *w.EndpointPort)
|
||||
}
|
||||
|
||||
if w.PublicKey != "" {
|
||||
node.Appendf("Server public key: %s", w.PublicKey)
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
Reference in New Issue
Block a user