mirror of
https://github.com/qdm12/gluetun.git
synced 2025-12-10 00:09:53 -06:00
154 lines
4.5 KiB
Go
154 lines
4.5 KiB
Go
package settings
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"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"
|
|
)
|
|
|
|
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, Surfshark
|
|
// 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 providers.Ivpn, providers.Mullvad,
|
|
providers.Surfshark, providers.Windscribe:
|
|
// endpoint IP addresses are baked in
|
|
case providers.Custom:
|
|
if len(w.EndpointIP) == 0 {
|
|
return ErrWireguardEndpointIPNotSet
|
|
}
|
|
default: // Providers not supporting Wireguard
|
|
}
|
|
|
|
// Validate EndpointPort
|
|
switch vpnProvider {
|
|
// EndpointPort is required
|
|
case providers.Custom:
|
|
if *w.EndpointPort == 0 {
|
|
return ErrWireguardEndpointPortNotSet
|
|
}
|
|
// EndpointPort cannot be set
|
|
case providers.Surfshark:
|
|
if *w.EndpointPort != 0 {
|
|
return ErrWireguardEndpointPortSet
|
|
}
|
|
case providers.Ivpn, providers.Mullvad, providers.Windscribe:
|
|
// EndpointPort is optional and can be 0
|
|
if *w.EndpointPort == 0 {
|
|
break // no custom endpoint port set
|
|
}
|
|
if vpnProvider == providers.Mullvad {
|
|
break // no restriction on custom endpoint port value
|
|
}
|
|
var allowed []uint16
|
|
switch vpnProvider {
|
|
case providers.Ivpn:
|
|
allowed = []uint16{2049, 2050, 53, 30587, 41893, 48574, 58237}
|
|
case providers.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 providers.Ivpn, providers.Mullvad,
|
|
providers.Surfshark, providers.Windscribe:
|
|
// public keys are baked in
|
|
case providers.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
|
|
}
|