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:
Quentin McGaw
2022-01-06 06:40:23 -05:00
committed by GitHub
parent 46738b2934
commit 7d824a5179
275 changed files with 7167 additions and 6328 deletions

View File

@@ -6,7 +6,7 @@ import (
"strconv"
"strings"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
)
@@ -16,13 +16,13 @@ func commaJoin(slice []string) string {
var ErrNoServerFound = errors.New("no server found")
func NoServerFoundError(selection configuration.ServerSelection) (err error) {
func NoServerFoundError(selection settings.ServerSelection) (err error) {
var messageParts []string
messageParts = append(messageParts, "VPN "+selection.VPN)
protocol := constants.UDP
if selection.OpenVPN.TCP {
if *selection.OpenVPN.TCP {
protocol = constants.TCP
}
messageParts = append(messageParts, "protocol "+protocol)
@@ -57,7 +57,7 @@ func NoServerFoundError(selection configuration.ServerSelection) (err error) {
messageParts = append(messageParts, part)
}
if selection.Owned {
if *selection.OwnedOnly {
messageParts = append(messageParts, "owned servers only")
}
@@ -105,12 +105,12 @@ func NoServerFoundError(selection configuration.ServerSelection) (err error) {
messageParts = append(messageParts, part)
}
if selection.OpenVPN.EncPreset != "" {
part := "encryption preset " + selection.OpenVPN.EncPreset
if *selection.OpenVPN.PIAEncPreset != "" {
part := "encryption preset " + *selection.OpenVPN.PIAEncPreset
messageParts = append(messageParts, part)
}
if selection.FreeOnly {
if *selection.FreeOnly {
messageParts = append(messageParts, "free tier only")
}

View File

@@ -6,7 +6,7 @@ import (
"math/rand"
"net"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/models"
)
@@ -17,15 +17,15 @@ import (
// Otherwise, it picks a random connection from the pool of connections
// and sets the target IP address as the IP if this one is set.
func PickConnection(connections []models.Connection,
selection configuration.ServerSelection, randSource rand.Source) (
selection settings.ServerSelection, randSource rand.Source) (
connection models.Connection, err error) {
if selection.TargetIP != nil && selection.VPN == constants.Wireguard {
if len(selection.TargetIP) > 0 && selection.VPN == constants.Wireguard {
// we need the right public key
return getTargetIPConnection(connections, selection.TargetIP)
}
connection = pickRandomConnection(connections, randSource)
if selection.TargetIP != nil {
if len(selection.TargetIP) > 0 {
connection.IP = selection.TargetIP
}

View File

@@ -1,25 +1,25 @@
package utils
import (
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
)
func GetPort(selection configuration.ServerSelection,
func GetPort(selection settings.ServerSelection,
defaultOpenVPNTCP, defaultOpenVPNUDP, defaultWireguard uint16) (port uint16) {
switch selection.VPN {
case constants.Wireguard:
customPort := selection.Wireguard.EndpointPort
customPort := *selection.Wireguard.EndpointPort
if customPort > 0 {
return customPort
}
return defaultWireguard
default: // OpenVPN
customPort := selection.OpenVPN.CustomPort
customPort := *selection.OpenVPN.CustomPort
if customPort > 0 {
return customPort
}
if selection.OpenVPN.TCP {
if *selection.OpenVPN.TCP {
return defaultOpenVPNTCP
}
return defaultOpenVPNUDP

View File

@@ -3,11 +3,14 @@ package utils
import (
"testing"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
"github.com/stretchr/testify/assert"
)
func boolPtr(b bool) *bool { return &b }
func uint16Ptr(n uint16) *uint16 { return &n }
func Test_GetPort(t *testing.T) {
t.Parallel()
@@ -18,47 +21,53 @@ func Test_GetPort(t *testing.T) {
)
testCases := map[string]struct {
selection configuration.ServerSelection
selection settings.ServerSelection
port uint16
}{
"default": {
port: defaultOpenVPNUDP,
selection: settings.ServerSelection{}.WithDefaults(""),
port: defaultOpenVPNUDP,
},
"OpenVPN UDP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: settings.OpenVPNSelection{
CustomPort: uint16Ptr(0),
TCP: boolPtr(false),
},
},
port: defaultOpenVPNUDP,
},
"OpenVPN TCP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
TCP: true,
OpenVPN: settings.OpenVPNSelection{
CustomPort: uint16Ptr(0),
TCP: boolPtr(true),
},
},
port: defaultOpenVPNTCP,
},
"OpenVPN custom port": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
CustomPort: 1234,
OpenVPN: settings.OpenVPNSelection{
CustomPort: uint16Ptr(1234),
},
},
port: 1234,
},
"Wireguard": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.Wireguard,
},
}.WithDefaults(""),
port: defaultWireguard,
},
"Wireguard custom port": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.Wireguard,
Wireguard: configuration.WireguardSelection{
EndpointPort: 1234,
Wireguard: settings.WireguardSelection{
EndpointPort: uint16Ptr(1234),
},
},
port: 1234,

View File

@@ -1,24 +1,24 @@
package utils
import (
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
)
func GetProtocol(selection configuration.ServerSelection) (protocol string) {
if selection.VPN == constants.OpenVPN && selection.OpenVPN.TCP {
func GetProtocol(selection settings.ServerSelection) (protocol string) {
if selection.VPN == constants.OpenVPN && *selection.OpenVPN.TCP {
return constants.TCP
}
return constants.UDP
}
func FilterByProtocol(selection configuration.ServerSelection,
func FilterByProtocol(selection settings.ServerSelection,
serverTCP, serverUDP bool) (filtered bool) {
switch selection.VPN {
case constants.Wireguard:
return !serverUDP
default: // OpenVPN
wantTCP := selection.OpenVPN.TCP
wantTCP := *selection.OpenVPN.TCP
wantUDP := !wantTCP
return (wantTCP && !serverTCP) || (wantUDP && !serverUDP)
}

View File

@@ -3,7 +3,7 @@ package utils
import (
"testing"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
"github.com/stretchr/testify/assert"
)
@@ -12,29 +12,32 @@ func Test_GetProtocol(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
selection configuration.ServerSelection
selection settings.ServerSelection
protocol string
}{
"default": {
protocol: constants.UDP,
},
"OpenVPN UDP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: settings.OpenVPNSelection{
TCP: boolPtr(false),
},
},
protocol: constants.UDP,
},
"OpenVPN TCP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
TCP: true,
OpenVPN: settings.OpenVPNSelection{
TCP: boolPtr(true),
},
},
protocol: constants.TCP,
},
"Wireguard": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.Wireguard,
},
protocol: constants.UDP,
@@ -57,60 +60,60 @@ func Test_FilterByProtocol(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
selection configuration.ServerSelection
selection settings.ServerSelection
serverTCP bool
serverUDP bool
filtered bool
}{
"Wireguard and server has UDP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.Wireguard,
},
serverUDP: true,
filtered: false,
},
"Wireguard and server has not UDP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.Wireguard,
},
serverUDP: false,
filtered: true,
},
"OpenVPN UDP and server has UDP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
TCP: false,
OpenVPN: settings.OpenVPNSelection{
TCP: boolPtr(false),
},
},
serverUDP: true,
filtered: false,
},
"OpenVPN UDP and server has not UDP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
TCP: false,
OpenVPN: settings.OpenVPNSelection{
TCP: boolPtr(false),
},
},
serverUDP: false,
filtered: true,
},
"OpenVPN TCP and server has TCP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
TCP: true,
OpenVPN: settings.OpenVPNSelection{
TCP: boolPtr(true),
},
},
serverTCP: true,
filtered: false,
},
"OpenVPN TCP and server has not TCP": {
selection: configuration.ServerSelection{
selection: settings.ServerSelection{
VPN: constants.OpenVPN,
OpenVPN: configuration.OpenVPNSelection{
TCP: true,
OpenVPN: settings.OpenVPNSelection{
TCP: boolPtr(true),
},
},
serverTCP: false,

View File

@@ -3,16 +3,16 @@ package utils
import (
"net"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/wireguard"
)
func BuildWireguardSettings(connection models.Connection,
userSettings configuration.Wireguard) (settings wireguard.Settings) {
settings.PrivateKey = userSettings.PrivateKey
userSettings settings.Wireguard) (settings wireguard.Settings) {
settings.PrivateKey = *userSettings.PrivateKey
settings.PublicKey = connection.PubKey
settings.PreSharedKey = userSettings.PreSharedKey
settings.PreSharedKey = *userSettings.PreSharedKey
settings.InterfaceName = userSettings.Interface
const rulePriority = 101 // 100 is to receive external connections

View File

@@ -4,18 +4,20 @@ import (
"net"
"testing"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/wireguard"
"github.com/stretchr/testify/assert"
)
func stringPtr(s string) *string { return &s }
func Test_BuildWireguardSettings(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
connection models.Connection
userSettings configuration.Wireguard
userSettings settings.Wireguard
settings wireguard.Settings
}{
"some settings": {
@@ -24,10 +26,10 @@ func Test_BuildWireguardSettings(t *testing.T) {
Port: 51821,
PubKey: "public",
},
userSettings: configuration.Wireguard{
PrivateKey: "private",
PreSharedKey: "pre-shared",
Addresses: []*net.IPNet{
userSettings: settings.Wireguard{
PrivateKey: stringPtr("private"),
PreSharedKey: stringPtr("pre-shared"),
Addresses: []net.IPNet{
{IP: net.IPv4(1, 1, 1, 1), Mask: net.IPv4Mask(255, 255, 255, 255)},
{IP: net.IPv4(2, 2, 2, 2), Mask: net.IPv4Mask(255, 255, 255, 255)},
},