Maint: dynamically set allowed VPN input ports

- Feat: allow to change VPN type at runtime
- Feat: allow to change interface name at runtime
- Maint: Add cleanup method to cleanup VPN loop on a vpn shutdown
- Change: allow VPN inputs ports only when tunnel is up
This commit is contained in:
Quentin McGaw (desktop)
2021-09-13 00:50:20 +00:00
parent 19bf62c21f
commit 40342619e7
6 changed files with 49 additions and 30 deletions

View File

@@ -292,14 +292,6 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
}
}
for _, vpnPort := range allSettings.Firewall.VPNInputPorts {
vpnIntf := allSettings.VPN.VPNInterface()
err = firewallConf.SetAllowedPort(ctx, vpnPort, vpnIntf)
if err != nil {
return err
}
}
for _, port := range allSettings.Firewall.InputPorts {
err = firewallConf.SetAllowedPort(ctx, port, defaultInterface)
if err != nil {
@@ -360,7 +352,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
tickersGroupHandler.Add(pubIPTickerHandler)
vpnLogger := logger.NewChild(logging.Settings{Prefix: "vpn: "})
vpnLooper := vpn.NewLoop(allSettings.VPN,
vpnLooper := vpn.NewLoop(allSettings.VPN, allSettings.Firewall.VPNInputPorts,
allServers, ovpnConf, netLinker, firewallConf, routingConf, portForwardLooper,
cmder, publicIPLooper, unboundLooper, vpnLogger, httpClient,
buildInfo, allSettings.VersionInformation)

27
internal/vpn/cleanup.go Normal file
View File

@@ -0,0 +1,27 @@
package vpn
import (
"context"
"time"
"github.com/qdm12/gluetun/internal/publicip/models"
)
func (l *Loop) cleanup(ctx context.Context, pfEnabled bool) {
for _, vpnPort := range l.vpnInputPorts {
err := l.fw.RemoveAllowedPort(ctx, vpnPort)
if err != nil {
l.logger.Error("cannot remove allowed input port from firewall: " + err.Error())
}
}
l.publicip.SetData(models.IPInfoData{}) // clear public IP address data
if pfEnabled {
const pfTimeout = 100 * time.Millisecond
err := l.stopPortForwarding(ctx, pfTimeout)
if err != nil {
l.logger.Error("cannot stop port forwarding: " + err.Error())
}
}
}

View File

@@ -36,6 +36,7 @@ type Loop struct {
// Fixed parameters
buildInfo models.BuildInformation
versionInfo bool
vpnInputPorts []uint16 // TODO make changeable through stateful firewall
// Configurators
openvpnConf openvpn.Interface
netLinker netlink.NetLinker
@@ -67,7 +68,7 @@ const (
defaultBackoffTime = 15 * time.Second
)
func NewLoop(vpnSettings configuration.VPN,
func NewLoop(vpnSettings configuration.VPN, vpnInputPorts []uint16,
allServers models.AllServers, openvpnConf openvpn.Interface,
netLinker netlink.NetLinker, fw firewallConfigurer, routing routing.VPNGetter,
portForward portforward.StartStopper, starter command.Starter,
@@ -87,6 +88,7 @@ func NewLoop(vpnSettings configuration.VPN,
state: state,
buildInfo: buildInfo,
versionInfo: versionInfo,
vpnInputPorts: vpnInputPorts,
openvpnConf: openvpnConf,
netLinker: netLinker,
fw: fw,

View File

@@ -40,20 +40,14 @@ func (l *Loop) startPortForwarding(ctx context.Context, data tunnelUpData) (err
return nil
}
func (l *Loop) stopPortForwarding(ctx context.Context, enabled bool,
timeout time.Duration) {
if !enabled {
return // nothing to stop
}
func (l *Loop) stopPortForwarding(ctx context.Context,
timeout time.Duration) (err error) {
if timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
_, err := l.portForward.Stop(ctx)
if err != nil {
l.logger.Error("cannot stop port forwarding: " + err.Error())
}
_, err = l.portForward.Stop(ctx)
return err
}

View File

@@ -6,7 +6,6 @@ import (
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/provider"
"github.com/qdm12/gluetun/internal/publicip/models"
"github.com/qdm12/golibs/logging"
)
@@ -32,6 +31,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
providerConf := provider.New(settings.Provider.Name, allServers, time.Now)
portForwarding := settings.Provider.PortForwarding.Enabled
var vpnRunner vpnRunner
var serverName, vpnInterface string
var err error
@@ -49,7 +49,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
continue
}
tunnelUpData := tunnelUpData{
portForwarding: settings.Provider.PortForwarding.Enabled,
portForwarding: portForwarding,
serverName: serverName,
portForwarder: providerConf,
vpnIntf: vpnInterface,
@@ -76,9 +76,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
case <-tunnelReady:
go l.onTunnelUp(openvpnCtx, tunnelUpData)
case <-ctx.Done():
const pfTimeout = 100 * time.Millisecond
l.stopPortForwarding(context.Background(),
settings.Provider.PortForwarding.Enabled, pfTimeout)
l.cleanup(context.Background(), portForwarding)
openvpnCancel()
<-waitError
close(waitError)
@@ -86,8 +84,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
case <-l.stop:
l.userTrigger = true
l.logger.Info("stopping")
l.publicip.SetData(models.IPInfoData{}) // clear public IP address data
l.stopPortForwarding(ctx, settings.Provider.PortForwarding.Enabled, 0)
l.cleanup(context.Background(), portForwarding)
openvpnCancel()
<-waitError
// do not close waitError or the waitError
@@ -102,7 +99,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.cleanup(context.Background(), portForwarding)
openvpnCancel()
l.statusManager.SetStatus(constants.Crashed)
l.logAndWait(ctx, err)

View File

@@ -19,6 +19,13 @@ type tunnelUpData struct {
func (l *Loop) onTunnelUp(ctx context.Context, data tunnelUpData) {
l.client.CloseIdleConnections()
for _, vpnPort := range l.vpnInputPorts {
err := l.fw.SetAllowedPort(ctx, vpnPort, data.vpnIntf)
if err != nil {
l.logger.Error("cannot allow input port through firewall: " + err.Error())
}
}
if l.dnsLooper.GetSettings().Enabled {
_, _ = l.dnsLooper.ApplyStatus(ctx, constants.Running)
}