chore!(amneziawg): refactor to be separate from wireguard

- amneziawg is now a VPN protocol and no longer a Wireguard implementation
- Use it with VPN_TYPE=amneziawg
- document AMNEZIAWG_* options in Dockerfile
- document amneziawg support in readme
- separate amneziawg settings and code from wireguard
- re-use code from wireguard whenever possible
This commit is contained in:
Quentin McGaw
2026-03-11 16:35:18 +00:00
parent efea169495
commit b04529c380
54 changed files with 1608 additions and 741 deletions
+67
View File
@@ -0,0 +1,67 @@
package vpn
import (
"context"
"fmt"
"github.com/qdm12/gluetun/internal/amneziawg"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/provider"
"github.com/qdm12/gluetun/internal/wireguard"
"github.com/qdm12/gosettings"
)
// setupAmneziaWg sets AmneziaWG up using the configurators and settings given.
func setupAmneziaWg(ctx context.Context, netlinker NetLinker,
fw Firewall, providerConf provider.Provider,
settings settings.VPN, ipv6Supported bool, logger wireguard.Logger) (
amneziawger *amneziawg.Amneziawg, connection models.Connection, err error,
) {
connection, err = providerConf.GetConnection(settings.Provider.ServerSelection, ipv6Supported)
if err != nil {
return nil, models.Connection{}, fmt.Errorf("finding a VPN server: %w", err)
}
amneziaWGSettings := buildAmneziaWgSettings(connection, settings.AmneziaWg, ipv6Supported)
logger.Debug("Amneziawg server public key: " + amneziaWGSettings.Wireguard.PublicKey)
logger.Debug("Amneziawg client private key: " + gosettings.ObfuscateKey(amneziaWGSettings.Wireguard.PrivateKey))
logger.Debug("Amneziawg pre-shared key: " + gosettings.ObfuscateKey(amneziaWGSettings.Wireguard.PreSharedKey))
amneziawger, err = amneziawg.New(amneziaWGSettings, netlinker, logger)
if err != nil {
return nil, models.Connection{}, fmt.Errorf("creating amneziawg: %w", err)
}
err = fw.SetVPNConnection(ctx, connection, settings.Wireguard.Interface)
if err != nil {
return nil, models.Connection{}, fmt.Errorf("setting firewall: %w", err)
}
return amneziawger, connection, nil
}
func buildAmneziaWgSettings(connection models.Connection,
userSettings settings.AmneziaWg, ipv6Supported bool,
) amneziawg.Settings {
return amneziawg.Settings{
Wireguard: buildWireguardSettings(connection, userSettings.Wireguard, ipv6Supported),
JunkPacketCount: *userSettings.JunkPacketCount,
JunkPacketMin: *userSettings.JunkPacketMin,
JunkPacketMax: *userSettings.JunkPacketMax,
PaddingS1: *userSettings.PaddingS1,
PaddingS2: *userSettings.PaddingS2,
PaddingS3: *userSettings.PaddingS3,
PaddingS4: *userSettings.PaddingS4,
HeaderH1: *userSettings.HeaderH1,
HeaderH2: *userSettings.HeaderH2,
HeaderH3: *userSettings.HeaderH3,
HeaderH4: *userSettings.HeaderH4,
InitPacketI1: *userSettings.InitPacketI1,
InitPacketI2: *userSettings.InitPacketI2,
InitPacketI3: *userSettings.InitPacketI3,
InitPacketI4: *userSettings.InitPacketI4,
InitPacketI5: *userSettings.InitPacketI5,
}
}
+9 -2
View File
@@ -33,14 +33,21 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
var connection models.Connection
var err error
subLogger := l.logger.New(log.SetComponent(settings.Type))
if settings.Type == vpn.OpenVPN {
switch settings.Type {
case vpn.AmneziaWg:
vpnInterface = settings.AmneziaWg.Wireguard.Interface
vpnRunner, connection, err = setupAmneziaWg(ctx, l.netLinker, l.fw,
providerConf, settings, l.ipv6Supported, subLogger)
case vpn.OpenVPN:
vpnInterface = settings.OpenVPN.Interface
vpnRunner, connection, err = setupOpenVPN(ctx, l.fw,
l.openvpnConf, providerConf, settings, l.ipv6Supported, l.cmder, subLogger)
} else { // Wireguard
case vpn.Wireguard:
vpnInterface = settings.Wireguard.Interface
vpnRunner, connection, err = setupWireguard(ctx, l.netLinker, l.fw,
providerConf, settings, l.ipv6Supported, subLogger)
default:
panic("vpn type not implemented: " + settings.Type)
}
if err != nil {
l.crashed(ctx, err)
+9
View File
@@ -8,6 +8,7 @@ import (
"time"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/constants/vpn"
"github.com/qdm12/gluetun/internal/netlink"
"github.com/qdm12/gluetun/internal/pmtud"
pconstants "github.com/qdm12/gluetun/internal/pmtud/constants"
@@ -48,6 +49,14 @@ type tunnelUpPMTUDData struct {
}
func (l *Loop) onTunnelUp(ctx, loopCtx context.Context, data tunnelUpData) {
switch vpnType := l.GetSettings().Type; vpnType {
case vpn.Wireguard, vpn.AmneziaWg:
l.logger.Infof("%s setup is complete. "+
"Note %s is a silent protocol and it may or may not work, without giving any error message. "+
"Typically i/o timeout errors indicate the %s connection is not working.",
vpnType, vpnType, vpnType)
}
l.client.CloseIdleConnections()
for _, vpnPort := range l.vpnInputPorts {
-22
View File
@@ -51,7 +51,6 @@ func buildWireguardSettings(connection models.Connection,
settings.PreSharedKey = *userSettings.PreSharedKey
settings.InterfaceName = userSettings.Interface
settings.Implementation = userSettings.Implementation
settings.AmneziaWG = buildAmneziaWgSettings(userSettings.AmneziaWG)
if *userSettings.MTU > 0 {
settings.MTU = *userSettings.MTU
} else {
@@ -91,24 +90,3 @@ func buildWireguardSettings(connection models.Connection,
return settings
}
func buildAmneziaWgSettings(s settings.AmneziaWg) wireguard.AmneziaSettings {
return wireguard.AmneziaSettings{
JunkPacketCount: *s.JunkPacketCount,
JunkPacketMin: *s.JunkPacketMin,
JunkPacketMax: *s.JunkPacketMax,
PaddingS1: *s.PaddingS1,
PaddingS2: *s.PaddingS2,
PaddingS3: *s.PaddingS3,
PaddingS4: *s.PaddingS4,
HeaderH1: *s.HeaderH1,
HeaderH2: *s.HeaderH2,
HeaderH3: *s.HeaderH3,
HeaderH4: *s.HeaderH4,
InitPacketI1: *s.InitPacketI1,
InitPacketI2: *s.InitPacketI2,
InitPacketI3: *s.InitPacketI3,
InitPacketI4: *s.InitPacketI4,
InitPacketI5: *s.InitPacketI5,
}
}
-22
View File
@@ -40,24 +40,6 @@ func Test_buildWireguardSettings(t *testing.T) {
PersistentKeepaliveInterval: ptrTo(time.Hour),
Interface: "wg1",
MTU: ptrTo(uint32(1000)),
AmneziaWG: settings.AmneziaWg{
JunkPacketCount: ptrTo(uint16(1)),
JunkPacketMin: ptrTo(uint16(0)),
JunkPacketMax: ptrTo(uint16(0)),
PaddingS1: ptrTo(uint16(0)),
PaddingS2: ptrTo(uint16(0)),
PaddingS3: ptrTo(uint16(0)),
PaddingS4: ptrTo(uint16(0)),
HeaderH1: ptrTo("x"),
HeaderH2: ptrTo(""),
HeaderH3: ptrTo(""),
HeaderH4: ptrTo(""),
InitPacketI1: ptrTo(""),
InitPacketI2: ptrTo(""),
InitPacketI3: ptrTo(""),
InitPacketI4: ptrTo(""),
InitPacketI5: ptrTo(""),
},
},
ipv6Supported: false,
settings: wireguard.Settings{
@@ -76,10 +58,6 @@ func Test_buildWireguardSettings(t *testing.T) {
RulePriority: 101,
IPv6: ptrTo(false),
MTU: 1000,
AmneziaWG: wireguard.AmneziaSettings{
JunkPacketCount: 1,
HeaderH1: "x",
},
},
},
}