Wireguard support for Mullvad and Windscribe (#565)

- `internal/wireguard` client package with unit tests
- Implementation works with kernel space or user space if unavailable
- `WIREGUARD_PRIVATE_KEY`
- `WIREGUARD_ADDRESS`
- `WIREGUARD_PRESHARED_KEY`
- `WIREGUARD_PORT`
- `internal/netlink` package used by `internal/wireguard`
This commit is contained in:
Quentin McGaw
2021-08-22 14:58:39 -07:00
committed by GitHub
parent 0bfd58a3f5
commit 614eb10d67
70 changed files with 13595 additions and 148 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/qdm12/gluetun/internal/firewall"
"github.com/qdm12/gluetun/internal/loopstate"
"github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/netlink"
"github.com/qdm12/gluetun/internal/openvpn"
"github.com/qdm12/gluetun/internal/portforward"
"github.com/qdm12/gluetun/internal/publicip"
@@ -37,6 +38,7 @@ type Loop struct {
versionInfo bool
// Configurators
openvpnConf openvpn.Interface
netLinker netlink.NetLinker
fw firewallConfigurer
routing routing.VPNGetter
portForward portforward.StartStopper
@@ -67,7 +69,7 @@ const (
func NewLoop(vpnSettings configuration.VPN,
allServers models.AllServers, openvpnConf openvpn.Interface,
fw firewallConfigurer, routing routing.VPNGetter,
netLinker netlink.NetLinker, fw firewallConfigurer, routing routing.VPNGetter,
portForward portforward.StartStopper, starter command.Starter,
publicip publicip.Looper, dnsLooper dns.Looper,
logger logging.Logger, client *http.Client,
@@ -86,6 +88,7 @@ func NewLoop(vpnSettings configuration.VPN,
buildInfo: buildInfo,
versionInfo: versionInfo,
openvpnConf: openvpnConf,
netLinker: netLinker,
fw: fw,
routing: routing,
portForward: portForward,

View File

@@ -30,8 +30,17 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
providerConf := provider.New(settings.Provider.Name, allServers, time.Now)
vpnRunner, serverName, err := setupOpenVPN(ctx, l.fw,
l.openvpnConf, providerConf, settings, l.starter, l.logger)
var vpnRunner vpnRunner
var serverName, vpnInterface string
var err error
if settings.Type == constants.OpenVPN {
vpnInterface = settings.OpenVPN.Interface
vpnRunner, serverName, err = setupOpenVPN(ctx, l.fw,
l.openvpnConf, providerConf, settings, l.starter, l.logger)
} else { // Wireguard
vpnInterface = settings.Wireguard.Interface
vpnRunner, serverName, err = setupWireguard(ctx, l.netLinker, l.fw, providerConf, settings, l.logger)
}
if err != nil {
l.crashed(ctx, err)
continue
@@ -40,7 +49,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
portForwarding: settings.Provider.PortForwarding.Enabled,
serverName: serverName,
portForwarder: providerConf,
vpnIntf: settings.OpenVPN.Interface,
vpnIntf: vpnInterface,
}
openvpnCtx, openvpnCancel := context.WithCancel(context.Background())

View File

@@ -17,13 +17,6 @@ type tunnelUpData struct {
}
func (l *Loop) onTunnelUp(ctx context.Context, data tunnelUpData) {
vpnDestination, err := l.routing.VPNDestinationIP()
if err != nil {
l.logger.Warn(err.Error())
} else {
l.logger.Info("VPN routing IP address: " + vpnDestination.String())
}
if l.dnsLooper.GetSettings().Enabled {
_, _ = l.dnsLooper.ApplyStatus(ctx, constants.Running)
}
@@ -40,7 +33,7 @@ func (l *Loop) onTunnelUp(ctx context.Context, data tunnelUpData) {
}
}
err = l.startPortForwarding(ctx, data)
err := l.startPortForwarding(ctx, data)
if err != nil {
l.logger.Error(err.Error())
}

45
internal/vpn/wireguard.go Normal file
View File

@@ -0,0 +1,45 @@
package vpn
import (
"context"
"errors"
"fmt"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/firewall"
"github.com/qdm12/gluetun/internal/netlink"
"github.com/qdm12/gluetun/internal/provider"
"github.com/qdm12/gluetun/internal/provider/utils"
"github.com/qdm12/gluetun/internal/wireguard"
)
var (
errGetServer = errors.New("failed finding a VPN server")
errCreateWireguard = errors.New("failed creating Wireguard")
)
// setupWireguard sets Wireguard up using the configurators and settings given.
// It returns a serverName for port forwarding (PIA) and an error if it fails.
func setupWireguard(ctx context.Context, netlinker netlink.NetLinker,
fw firewall.VPNConnectionSetter, providerConf provider.Provider,
settings configuration.VPN, logger wireguard.Logger) (
wireguarder wireguard.Wireguarder, serverName string, err error) {
connection, err := providerConf.GetConnection(settings.Provider.ServerSelection)
if err != nil {
return nil, "", fmt.Errorf("%w: %s", errGetServer, err)
}
wireguardSettings := utils.BuildWireguardSettings(connection, settings.Wireguard)
wireguarder, err = wireguard.New(wireguardSettings, netlinker, logger)
if err != nil {
return nil, "", fmt.Errorf("%w: %s", errCreateWireguard, err)
}
err = fw.SetVPNConnection(ctx, connection, settings.Wireguard.Interface)
if err != nil {
return nil, "", fmt.Errorf("%w: %s", errFirewall, err)
}
return wireguarder, connection.Hostname, nil
}