mirror of
https://github.com/qdm12/gluetun.git
synced 2026-08-01 01:43:22 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4c07472dfa |
@@ -85,13 +85,13 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v7
|
||||||
with:
|
with:
|
||||||
go-version-file: ./devrun/go.mod
|
go-version-file: ./devrun/go.mod
|
||||||
- run: go test ./...
|
- run: go test ./...
|
||||||
working-directory: ./devrun
|
working-directory: ./devrun
|
||||||
|
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v7
|
||||||
with:
|
with:
|
||||||
go-version-file: ./ci/go.mod
|
go-version-file: ./ci/go.mod
|
||||||
- run: go test ./...
|
- run: go test ./...
|
||||||
@@ -114,7 +114,7 @@ jobs:
|
|||||||
- run: docker build -t qmcgaw/gluetun .
|
- run: docker build -t qmcgaw/gluetun .
|
||||||
|
|
||||||
- name: Setup Go for CI utility
|
- name: Setup Go for CI utility
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v7
|
||||||
with:
|
with:
|
||||||
go-version-file: ci/go.mod
|
go-version-file: ci/go.mod
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ jobs:
|
|||||||
security-events: write
|
security-events: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v7
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
- uses: github/codeql-action/init@v4
|
- uses: github/codeql-action/init@v4
|
||||||
@@ -241,5 +241,3 @@ jobs:
|
|||||||
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
|
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
push: true
|
push: true
|
||||||
provenance: mode=max
|
|
||||||
sbom: true
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/healthcheck/dns"
|
"github.com/qdm12/gluetun/internal/healthcheck/dns"
|
||||||
@@ -23,6 +24,7 @@ type Checker struct {
|
|||||||
icmpTargetIPs []netip.Addr
|
icmpTargetIPs []netip.Addr
|
||||||
smallCheckType string
|
smallCheckType string
|
||||||
startupOnFail bool
|
startupOnFail bool
|
||||||
|
configMutex sync.Mutex
|
||||||
|
|
||||||
icmpNotPermitted *bool
|
icmpNotPermitted *bool
|
||||||
|
|
||||||
@@ -53,6 +55,8 @@ func NewChecker(logger Logger) *Checker {
|
|||||||
func (c *Checker) SetConfig(tlsDialAddrs []string, icmpTargets []netip.Addr,
|
func (c *Checker) SetConfig(tlsDialAddrs []string, icmpTargets []netip.Addr,
|
||||||
smallCheckType string, startupOnFail bool,
|
smallCheckType string, startupOnFail bool,
|
||||||
) {
|
) {
|
||||||
|
c.configMutex.Lock()
|
||||||
|
defer c.configMutex.Unlock()
|
||||||
c.tlsDialAddrs = tlsDialAddrs
|
c.tlsDialAddrs = tlsDialAddrs
|
||||||
c.icmpTargetIPs = icmpTargets
|
c.icmpTargetIPs = icmpTargets
|
||||||
c.smallCheckType = smallCheckType
|
c.smallCheckType = smallCheckType
|
||||||
@@ -162,8 +166,10 @@ func (c *Checker) Stop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checker) smallPeriodicCheck(ctx context.Context) error {
|
func (c *Checker) smallPeriodicCheck(ctx context.Context) error {
|
||||||
|
c.configMutex.Lock()
|
||||||
icmpTargetIPs := make([]netip.Addr, len(c.icmpTargetIPs))
|
icmpTargetIPs := make([]netip.Addr, len(c.icmpTargetIPs))
|
||||||
copy(icmpTargetIPs, c.icmpTargetIPs)
|
copy(icmpTargetIPs, c.icmpTargetIPs)
|
||||||
|
c.configMutex.Unlock()
|
||||||
tryTimeouts := []time.Duration{
|
tryTimeouts := []time.Duration{
|
||||||
5 * time.Second,
|
5 * time.Second,
|
||||||
5 * time.Second,
|
5 * time.Second,
|
||||||
|
|||||||
@@ -49,24 +49,3 @@ func portPairToString(internal, external uint16) string {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("%d (internal port %d)", external, internal)
|
return fmt.Sprintf("%d (internal port %d)", external, internal)
|
||||||
}
|
}
|
||||||
|
|
||||||
type loggerWithPrefix struct {
|
|
||||||
prefix string
|
|
||||||
logger Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *loggerWithPrefix) Debug(msg string) {
|
|
||||||
l.logger.Debug(l.prefix + msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *loggerWithPrefix) Info(msg string) {
|
|
||||||
l.logger.Info(l.prefix + msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *loggerWithPrefix) Warn(msg string) {
|
|
||||||
l.logger.Warn(l.prefix + msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *loggerWithPrefix) Error(msg string) {
|
|
||||||
l.logger.Error(l.prefix + msg)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -61,8 +60,7 @@ func (s *Service) SetPortsForwarded(ctx context.Context, ports []uint16) (err er
|
|||||||
s.portMutex.Lock()
|
s.portMutex.Lock()
|
||||||
defer s.portMutex.Unlock()
|
defer s.portMutex.Unlock()
|
||||||
|
|
||||||
hasPortForwardingCodeRunning := !strings.HasSuffix(s.settings.PortForwarder.Name(), "[not supported]")
|
if s.settings.PortForwarder != nil {
|
||||||
if hasPortForwardingCodeRunning {
|
|
||||||
return errors.New("setting port forwarded at runtime is not supported with internally running port forwarding code")
|
return errors.New("setting port forwarded at runtime is not supported with internally running port forwarding code")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,11 +133,7 @@ func (s *Service) onNewPorts(ctx context.Context, internalToExternalPorts map[ui
|
|||||||
copy(s.ports, externalPorts)
|
copy(s.ports, externalPorts)
|
||||||
|
|
||||||
if s.settings.UpCommand != "" {
|
if s.settings.UpCommand != "" {
|
||||||
logger := &loggerWithPrefix{
|
err = runCommand(ctx, s.cmder, s.logger, s.settings.UpCommand, externalPorts, s.settings.Interface)
|
||||||
prefix: "up command: ",
|
|
||||||
logger: s.logger,
|
|
||||||
}
|
|
||||||
err = runCommand(ctx, s.cmder, logger, s.settings.UpCommand, externalPorts, s.settings.Interface)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("running up command: %w", err)
|
err = fmt.Errorf("running up command: %w", err)
|
||||||
s.logger.Error(err.Error())
|
s.logger.Error(err.Error())
|
||||||
|
|||||||
@@ -32,11 +32,7 @@ func (s *Service) cleanup() (err error) {
|
|||||||
const downTimeout = 60 * time.Second
|
const downTimeout = 60 * time.Second
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), downTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), downTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
logger := &loggerWithPrefix{
|
err = runCommand(ctx, s.cmder, s.logger, s.settings.DownCommand, s.ports, s.settings.Interface)
|
||||||
prefix: "down command: ",
|
|
||||||
logger: s.logger,
|
|
||||||
}
|
|
||||||
err = runCommand(ctx, s.cmder, logger, s.settings.DownCommand, s.ports, s.settings.Interface)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("running down command: %w", err)
|
err = fmt.Errorf("running down command: %w", err)
|
||||||
s.logger.Error(err.Error())
|
s.logger.Error(err.Error())
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ type Loop struct {
|
|||||||
start <-chan struct{}
|
start <-chan struct{}
|
||||||
running chan<- models.LoopStatus
|
running chan<- models.LoopStatus
|
||||||
userTrigger bool
|
userTrigger bool
|
||||||
healthDone <-chan struct{}
|
|
||||||
// Internal constant values
|
// Internal constant values
|
||||||
backoffTime time.Duration
|
backoffTime time.Duration
|
||||||
}
|
}
|
||||||
@@ -71,11 +70,6 @@ func NewLoop(vpnSettings settings.VPN, ipv6SupportLevel netlink.IPv6SupportLevel
|
|||||||
statusManager := loopstate.New(constants.Stopped, start, running, stop, stopped)
|
statusManager := loopstate.New(constants.Stopped, start, running, stop, stopped)
|
||||||
state := state.New(statusManager, vpnSettings)
|
state := state.New(statusManager, vpnSettings)
|
||||||
|
|
||||||
// Initialize healthDone channel to a closed channel so that the first time
|
|
||||||
// we call <-l.healthDone it does not block
|
|
||||||
healthDone := make(chan struct{})
|
|
||||||
close(healthDone)
|
|
||||||
|
|
||||||
return &Loop{
|
return &Loop{
|
||||||
statusManager: statusManager,
|
statusManager: statusManager,
|
||||||
state: state,
|
state: state,
|
||||||
@@ -104,7 +98,6 @@ func NewLoop(vpnSettings settings.VPN, ipv6SupportLevel netlink.IPv6SupportLevel
|
|||||||
stop: stop,
|
stop: stop,
|
||||||
stopped: stopped,
|
stopped: stopped,
|
||||||
userTrigger: true,
|
userTrigger: true,
|
||||||
healthDone: healthDone,
|
|
||||||
backoffTime: defaultBackoffTime,
|
backoffTime: defaultBackoffTime,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func newNoPortForwarder(providerName string) *noPortForwarder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *noPortForwarder) Name() string {
|
func (n *noPortForwarder) Name() string {
|
||||||
return n.providerName + " [not supported]"
|
return n.providerName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *noPortForwarder) PortForward(context.Context, pfutils.PortForwardObjects) (
|
func (n *noPortForwarder) PortForward(context.Context, pfutils.PortForwardObjects) (
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ func (l *Loop) onTunnelUp(ctx, loopCtx context.Context, data tunnelUpData) {
|
|||||||
|
|
||||||
_, _ = l.dnsLooper.ApplyStatus(ctx, constants.Running)
|
_, _ = l.dnsLooper.ApplyStatus(ctx, constants.Running)
|
||||||
|
|
||||||
<-l.healthDone // make sure the health checker is stopped before restarting it
|
|
||||||
icmpTargetIPs := l.healthSettings.ICMPTargetIPs
|
icmpTargetIPs := l.healthSettings.ICMPTargetIPs
|
||||||
if len(icmpTargetIPs) == 1 && icmpTargetIPs[0].IsUnspecified() {
|
if len(icmpTargetIPs) == 1 && icmpTargetIPs[0].IsUnspecified() {
|
||||||
icmpTargetIPs = []netip.Addr{data.serverIP}
|
icmpTargetIPs = []netip.Addr{data.serverIP}
|
||||||
@@ -105,12 +104,7 @@ func (l *Loop) onTunnelUp(ctx, loopCtx context.Context, data tunnelUpData) {
|
|||||||
// Start collecting health errors asynchronously, since
|
// Start collecting health errors asynchronously, since
|
||||||
// we should not wait for the code below to complete
|
// we should not wait for the code below to complete
|
||||||
// to start monitoring health and auto-healing.
|
// to start monitoring health and auto-healing.
|
||||||
// We keep track of when this goroutine is done with the healthDone
|
go l.collectHealthErrors(ctx, loopCtx, healthErrCh)
|
||||||
// channel to avoid a race condition where the health checker is stopped
|
|
||||||
// after being reconfigured and restarted, instead of before.
|
|
||||||
healthDone := make(chan struct{})
|
|
||||||
l.healthDone = healthDone
|
|
||||||
go l.collectHealthErrors(ctx, loopCtx, healthDone, healthErrCh)
|
|
||||||
|
|
||||||
err = l.publicip.RunOnce(ctx)
|
err = l.publicip.RunOnce(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -146,10 +140,7 @@ func (l *Loop) onTunnelUp(ctx, loopCtx context.Context, data tunnelUpData) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loop) collectHealthErrors(ctx, loopCtx context.Context,
|
func (l *Loop) collectHealthErrors(ctx, loopCtx context.Context, healthErrCh <-chan error) {
|
||||||
done chan<- struct{}, healthErrCh <-chan error,
|
|
||||||
) {
|
|
||||||
defer close(done)
|
|
||||||
var previousHealthErr error
|
var previousHealthErr error
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
|||||||
Reference in New Issue
Block a user