Maint: refactor VPN configuration structure

- Paves the way for Wireguard
- VPN struct contains Type, Openvpn and Provider configurations
- OpenVPN specific options (e.g. client key) moved from Provider to Openvpn configuration struct
- Move Provider configuration from OpenVPN configuration to VPN
- HTTP control server returns only openvpn settings (not provider settings)
This commit is contained in:
Quentin McGaw (desktop)
2021-08-17 15:44:11 +00:00
parent a00de75f61
commit cc2235653a
39 changed files with 372 additions and 301 deletions

View File

@@ -68,7 +68,7 @@ func modifyCustomConfig(lines []string, username string,
len(settings.Cipher) > 0 && strings.HasPrefix(line, "data-ciphers"),
len(settings.Auth) > 0 && strings.HasPrefix(line, "auth "),
settings.MSSFix > 0 && strings.HasPrefix(line, "mssfix "),
!settings.Provider.ExtraConfigOptions.OpenVPNIPv6 && strings.HasPrefix(line, "tun-ipv6"):
!settings.IPv6 && strings.HasPrefix(line, "tun-ipv6"):
default:
modified = append(modified, line)
}
@@ -93,7 +93,7 @@ func modifyCustomConfig(lines []string, username string,
if settings.MSSFix > 0 {
modified = append(modified, "mssfix "+strconv.Itoa(int(settings.MSSFix)))
}
if !settings.Provider.ExtraConfigOptions.OpenVPNIPv6 {
if !settings.IPv6 {
modified = append(modified, `pull-filter ignore "route-ipv6"`)
modified = append(modified, `pull-filter ignore "ifconfig-ipv6"`)
}

View File

@@ -67,8 +67,10 @@ const (
defaultBackoffTime = 15 * time.Second
)
func NewLoop(settings configuration.OpenVPN, username string,
puid, pgid int, allServers models.AllServers, conf Configurator,
func NewLoop(openVPNSettings configuration.OpenVPN,
providerSettings configuration.Provider,
username string, puid, pgid int,
allServers models.AllServers, conf Configurator,
fw firewallConfigurer, routing routing.VPNGetter,
portForward portforward.StartStopper,
publicip publicip.Looper, dnsLooper dns.Looper,
@@ -80,7 +82,7 @@ func NewLoop(settings configuration.OpenVPN, username string,
stopped := make(chan struct{})
statusManager := loopstate.New(constants.Stopped, start, running, stop, stopped)
state := state.New(statusManager, settings, allServers)
state := state.New(statusManager, openVPNSettings, providerSettings, allServers)
return &Loop{
statusManager: statusManager,

View File

@@ -23,23 +23,23 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
}
for ctx.Err() == nil {
settings, allServers := l.state.GetSettingsAndServers()
openVPNSettings, providerSettings, allServers := l.state.GetSettingsAndServers()
providerConf := provider.New(settings.Provider.Name, allServers, time.Now)
providerConf := provider.New(providerSettings.Name, allServers, time.Now)
var connection models.OpenVPNConnection
var lines []string
var err error
if settings.Config == "" {
connection, err = providerConf.GetOpenVPNConnection(settings.Provider.ServerSelection)
if openVPNSettings.Config == "" {
connection, err = providerConf.GetOpenVPNConnection(providerSettings.ServerSelection)
if err != nil {
l.signalOrSetStatus(constants.Crashed)
l.logAndWait(ctx, err)
continue
}
lines = providerConf.BuildConf(connection, l.username, settings)
lines = providerConf.BuildConf(connection, l.username, openVPNSettings)
} else {
lines, connection, err = l.processCustomConfig(settings)
lines, connection, err = l.processCustomConfig(openVPNSettings)
if err != nil {
l.signalOrSetStatus(constants.Crashed)
l.logAndWait(ctx, err)
@@ -53,9 +53,9 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
continue
}
if settings.User != "" {
if openVPNSettings.User != "" {
err := l.conf.WriteAuthFile(
settings.User, settings.Password, l.puid, l.pgid)
openVPNSettings.User, openVPNSettings.Password, l.puid, l.pgid)
if err != nil {
l.signalOrSetStatus(constants.Crashed)
l.logAndWait(ctx, err)
@@ -72,7 +72,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
openvpnCtx, openvpnCancel := context.WithCancel(context.Background())
stdoutLines, stderrLines, waitError, err := l.conf.Start(
openvpnCtx, settings.Version, settings.Flags)
openvpnCtx, openVPNSettings.Version, openVPNSettings.Flags)
if err != nil {
openvpnCancel()
l.signalOrSetStatus(constants.Crashed)
@@ -96,12 +96,12 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
for stayHere {
select {
case <-l.startPFCh:
l.startPortForwarding(ctx, settings.Provider.PortForwarding.Enabled,
l.startPortForwarding(ctx, providerSettings.PortForwarding.Enabled,
providerConf, connection.Hostname)
case <-ctx.Done():
const pfTimeout = 100 * time.Millisecond
l.stopPortForwarding(context.Background(),
settings.Provider.PortForwarding.Enabled, pfTimeout)
providerSettings.PortForwarding.Enabled, pfTimeout)
openvpnCancel()
<-waitError
close(waitError)
@@ -110,7 +110,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
case <-l.stop:
l.userTrigger = true
l.logger.Info("stopping")
l.stopPortForwarding(ctx, settings.Provider.PortForwarding.Enabled, 0)
l.stopPortForwarding(ctx, providerSettings.PortForwarding.Enabled, 0)
openvpnCancel()
<-waitError
// do not close waitError or the waitError
@@ -127,7 +127,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
l.statusManager.Lock() // prevent SetStatus from running in parallel
l.stopPortForwarding(ctx, settings.Provider.PortForwarding.Enabled, 0)
l.stopPortForwarding(ctx, providerSettings.PortForwarding.Enabled, 0)
openvpnCancel()
l.statusManager.SetStatus(constants.Crashed)
l.logAndWait(ctx, err)

View File

@@ -9,11 +9,13 @@ import (
type SettingsGetSetter = state.SettingsGetSetter
func (l *Loop) GetSettings() (settings configuration.OpenVPN) {
func (l *Loop) GetSettings() (
openvpn configuration.OpenVPN, provider configuration.Provider) {
return l.state.GetSettings()
}
func (l *Loop) SetSettings(ctx context.Context, settings configuration.OpenVPN) (
func (l *Loop) SetSettings(ctx context.Context,
openvpn configuration.OpenVPN, provider configuration.Provider) (
outcome string) {
return l.state.SetSettings(ctx, settings)
return l.state.SetSettings(ctx, openvpn, provider)
}

View File

@@ -0,0 +1,43 @@
package state
import (
"context"
"reflect"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
)
type SettingsGetSetter interface {
GetSettings() (openvpn configuration.OpenVPN,
provider configuration.Provider)
SetSettings(ctx context.Context, openvpn configuration.OpenVPN,
provider configuration.Provider) (outcome string)
}
func (s *State) GetSettings() (openvpn configuration.OpenVPN,
provider configuration.Provider) {
s.settingsMu.RLock()
openvpn = s.openvpn
provider = s.provider
s.settingsMu.RUnlock()
return openvpn, provider
}
func (s *State) SetSettings(ctx context.Context,
openvpn configuration.OpenVPN, provider configuration.Provider) (
outcome string) {
s.settingsMu.Lock()
settingsUnchanged := reflect.DeepEqual(s.openvpn, openvpn) &&
reflect.DeepEqual(s.provider, provider)
if settingsUnchanged {
s.settingsMu.Unlock()
return "settings left unchanged"
}
s.openvpn = openvpn
s.provider = provider
s.settingsMu.Unlock()
_, _ = s.statusApplier.ApplyStatus(ctx, constants.Stopped)
outcome, _ = s.statusApplier.ApplyStatus(ctx, constants.Running)
return outcome
}

View File

@@ -1,36 +0,0 @@
package state
import (
"context"
"reflect"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/constants"
)
type SettingsGetSetter interface {
GetSettings() (settings configuration.OpenVPN)
SetSettings(ctx context.Context, settings configuration.OpenVPN) (
outcome string)
}
func (s *State) GetSettings() (settings configuration.OpenVPN) {
s.settingsMu.RLock()
defer s.settingsMu.RUnlock()
return s.settings
}
func (s *State) SetSettings(ctx context.Context, settings configuration.OpenVPN) (
outcome string) {
s.settingsMu.Lock()
settingsUnchanged := reflect.DeepEqual(s.settings, settings)
if settingsUnchanged {
s.settingsMu.Unlock()
return "settings left unchanged"
}
s.settings = settings
s.settingsMu.Unlock()
_, _ = s.statusApplier.ApplyStatus(ctx, constants.Stopped)
outcome, _ = s.statusApplier.ApplyStatus(ctx, constants.Running)
return outcome
}

View File

@@ -13,16 +13,17 @@ var _ Manager = (*State)(nil)
type Manager interface {
SettingsGetSetter
ServersGetterSetter
GetSettingsAndServers() (settings configuration.OpenVPN,
allServers models.AllServers)
GetSettingsAndServers() (openvpn configuration.OpenVPN,
provider configuration.Provider, allServers models.AllServers)
}
func New(statusApplier loopstate.Applier,
settings configuration.OpenVPN,
openvpn configuration.OpenVPN, provider configuration.Provider,
allServers models.AllServers) *State {
return &State{
statusApplier: statusApplier,
settings: settings,
openvpn: openvpn,
provider: provider,
allServers: allServers,
}
}
@@ -30,20 +31,22 @@ func New(statusApplier loopstate.Applier,
type State struct {
statusApplier loopstate.Applier
settings configuration.OpenVPN
openvpn configuration.OpenVPN
provider configuration.Provider
settingsMu sync.RWMutex
allServers models.AllServers
allServersMu sync.RWMutex
}
func (s *State) GetSettingsAndServers() (settings configuration.OpenVPN,
allServers models.AllServers) {
func (s *State) GetSettingsAndServers() (openvpn configuration.OpenVPN,
provider configuration.Provider, allServers models.AllServers) {
s.settingsMu.RLock()
s.allServersMu.RLock()
settings = s.settings
openvpn = s.openvpn
provider = s.provider
allServers = s.allServers
s.settingsMu.RUnlock()
s.allServersMu.RUnlock()
return settings, allServers
return openvpn, provider, allServers
}