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:
@@ -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
27
internal/vpn/cleanup.go
Normal 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())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,8 +34,9 @@ type Loop struct {
|
||||
statusManager loopstate.Manager
|
||||
state state.Manager
|
||||
// Fixed parameters
|
||||
buildInfo models.BuildInformation
|
||||
versionInfo bool
|
||||
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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user