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 {
|
for _, port := range allSettings.Firewall.InputPorts {
|
||||||
err = firewallConf.SetAllowedPort(ctx, port, defaultInterface)
|
err = firewallConf.SetAllowedPort(ctx, port, defaultInterface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -360,7 +352,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
|||||||
tickersGroupHandler.Add(pubIPTickerHandler)
|
tickersGroupHandler.Add(pubIPTickerHandler)
|
||||||
|
|
||||||
vpnLogger := logger.NewChild(logging.Settings{Prefix: "vpn: "})
|
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,
|
allServers, ovpnConf, netLinker, firewallConf, routingConf, portForwardLooper,
|
||||||
cmder, publicIPLooper, unboundLooper, vpnLogger, httpClient,
|
cmder, publicIPLooper, unboundLooper, vpnLogger, httpClient,
|
||||||
buildInfo, allSettings.VersionInformation)
|
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
|
statusManager loopstate.Manager
|
||||||
state state.Manager
|
state state.Manager
|
||||||
// Fixed parameters
|
// Fixed parameters
|
||||||
buildInfo models.BuildInformation
|
buildInfo models.BuildInformation
|
||||||
versionInfo bool
|
versionInfo bool
|
||||||
|
vpnInputPorts []uint16 // TODO make changeable through stateful firewall
|
||||||
// Configurators
|
// Configurators
|
||||||
openvpnConf openvpn.Interface
|
openvpnConf openvpn.Interface
|
||||||
netLinker netlink.NetLinker
|
netLinker netlink.NetLinker
|
||||||
@@ -67,7 +68,7 @@ const (
|
|||||||
defaultBackoffTime = 15 * time.Second
|
defaultBackoffTime = 15 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewLoop(vpnSettings configuration.VPN,
|
func NewLoop(vpnSettings configuration.VPN, vpnInputPorts []uint16,
|
||||||
allServers models.AllServers, openvpnConf openvpn.Interface,
|
allServers models.AllServers, openvpnConf openvpn.Interface,
|
||||||
netLinker netlink.NetLinker, fw firewallConfigurer, routing routing.VPNGetter,
|
netLinker netlink.NetLinker, fw firewallConfigurer, routing routing.VPNGetter,
|
||||||
portForward portforward.StartStopper, starter command.Starter,
|
portForward portforward.StartStopper, starter command.Starter,
|
||||||
@@ -87,6 +88,7 @@ func NewLoop(vpnSettings configuration.VPN,
|
|||||||
state: state,
|
state: state,
|
||||||
buildInfo: buildInfo,
|
buildInfo: buildInfo,
|
||||||
versionInfo: versionInfo,
|
versionInfo: versionInfo,
|
||||||
|
vpnInputPorts: vpnInputPorts,
|
||||||
openvpnConf: openvpnConf,
|
openvpnConf: openvpnConf,
|
||||||
netLinker: netLinker,
|
netLinker: netLinker,
|
||||||
fw: fw,
|
fw: fw,
|
||||||
|
|||||||
@@ -40,20 +40,14 @@ func (l *Loop) startPortForwarding(ctx context.Context, data tunnelUpData) (err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loop) stopPortForwarding(ctx context.Context, enabled bool,
|
func (l *Loop) stopPortForwarding(ctx context.Context,
|
||||||
timeout time.Duration) {
|
timeout time.Duration) (err error) {
|
||||||
if !enabled {
|
|
||||||
return // nothing to stop
|
|
||||||
}
|
|
||||||
|
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
ctx, cancel = context.WithTimeout(ctx, timeout)
|
ctx, cancel = context.WithTimeout(ctx, timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := l.portForward.Stop(ctx)
|
_, err = l.portForward.Stop(ctx)
|
||||||
if err != nil {
|
return err
|
||||||
l.logger.Error("cannot stop port forwarding: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants"
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
"github.com/qdm12/gluetun/internal/provider"
|
"github.com/qdm12/gluetun/internal/provider"
|
||||||
"github.com/qdm12/gluetun/internal/publicip/models"
|
|
||||||
"github.com/qdm12/golibs/logging"
|
"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)
|
providerConf := provider.New(settings.Provider.Name, allServers, time.Now)
|
||||||
|
|
||||||
|
portForwarding := settings.Provider.PortForwarding.Enabled
|
||||||
var vpnRunner vpnRunner
|
var vpnRunner vpnRunner
|
||||||
var serverName, vpnInterface string
|
var serverName, vpnInterface string
|
||||||
var err error
|
var err error
|
||||||
@@ -49,7 +49,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tunnelUpData := tunnelUpData{
|
tunnelUpData := tunnelUpData{
|
||||||
portForwarding: settings.Provider.PortForwarding.Enabled,
|
portForwarding: portForwarding,
|
||||||
serverName: serverName,
|
serverName: serverName,
|
||||||
portForwarder: providerConf,
|
portForwarder: providerConf,
|
||||||
vpnIntf: vpnInterface,
|
vpnIntf: vpnInterface,
|
||||||
@@ -76,9 +76,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
|
|||||||
case <-tunnelReady:
|
case <-tunnelReady:
|
||||||
go l.onTunnelUp(openvpnCtx, tunnelUpData)
|
go l.onTunnelUp(openvpnCtx, tunnelUpData)
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
const pfTimeout = 100 * time.Millisecond
|
l.cleanup(context.Background(), portForwarding)
|
||||||
l.stopPortForwarding(context.Background(),
|
|
||||||
settings.Provider.PortForwarding.Enabled, pfTimeout)
|
|
||||||
openvpnCancel()
|
openvpnCancel()
|
||||||
<-waitError
|
<-waitError
|
||||||
close(waitError)
|
close(waitError)
|
||||||
@@ -86,8 +84,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
|
|||||||
case <-l.stop:
|
case <-l.stop:
|
||||||
l.userTrigger = true
|
l.userTrigger = true
|
||||||
l.logger.Info("stopping")
|
l.logger.Info("stopping")
|
||||||
l.publicip.SetData(models.IPInfoData{}) // clear public IP address data
|
l.cleanup(context.Background(), portForwarding)
|
||||||
l.stopPortForwarding(ctx, settings.Provider.PortForwarding.Enabled, 0)
|
|
||||||
openvpnCancel()
|
openvpnCancel()
|
||||||
<-waitError
|
<-waitError
|
||||||
// do not close waitError or the 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.statusManager.Lock() // prevent SetStatus from running in parallel
|
||||||
|
|
||||||
l.stopPortForwarding(ctx, settings.Provider.PortForwarding.Enabled, 0)
|
l.cleanup(context.Background(), portForwarding)
|
||||||
openvpnCancel()
|
openvpnCancel()
|
||||||
l.statusManager.SetStatus(constants.Crashed)
|
l.statusManager.SetStatus(constants.Crashed)
|
||||||
l.logAndWait(ctx, err)
|
l.logAndWait(ctx, err)
|
||||||
|
|||||||
@@ -19,6 +19,13 @@ type tunnelUpData struct {
|
|||||||
func (l *Loop) onTunnelUp(ctx context.Context, data tunnelUpData) {
|
func (l *Loop) onTunnelUp(ctx context.Context, data tunnelUpData) {
|
||||||
l.client.CloseIdleConnections()
|
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 {
|
if l.dnsLooper.GetSettings().Enabled {
|
||||||
_, _ = l.dnsLooper.ApplyStatus(ctx, constants.Running)
|
_, _ = l.dnsLooper.ApplyStatus(ctx, constants.Running)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user