Using struct for VPN connection settings

This commit is contained in:
Quentin McGaw (desktop)
2020-02-16 19:50:21 +00:00
parent f6b91bd74f
commit ce11745f6f
6 changed files with 63 additions and 40 deletions

View File

@@ -115,7 +115,9 @@ func main() {
e.FatalOnError(err) e.FatalOnError(err)
} }
VPNIPs, port, err := piaConf.BuildConf(allSettings.PIA.Region, allSettings.OpenVPN.NetworkProtocol, allSettings.PIA.Encryption, uid, gid) connections, err := piaConf.GetOpenVPNConnections(allSettings.PIA.Region, allSettings.OpenVPN.NetworkProtocol, allSettings.PIA.Encryption)
e.FatalOnError(err)
err = piaConf.BuildConf(connections, allSettings.PIA.Encryption, uid, gid)
e.FatalOnError(err) e.FatalOnError(err)
defaultInterface, defaultGateway, defaultSubnet, err := firewallConf.GetDefaultRoute() defaultInterface, defaultGateway, defaultSubnet, err := firewallConf.GetDefaultRoute()
@@ -128,7 +130,7 @@ func main() {
e.FatalOnError(err) e.FatalOnError(err)
err = firewallConf.CreateGeneralRules() err = firewallConf.CreateGeneralRules()
e.FatalOnError(err) e.FatalOnError(err)
err = firewallConf.CreateVPNRules(constants.TUN, VPNIPs, defaultInterface, port, allSettings.OpenVPN.NetworkProtocol) err = firewallConf.CreateVPNRules(constants.TUN, defaultInterface, connections)
e.FatalOnError(err) e.FatalOnError(err)
err = firewallConf.CreateLocalSubnetsRules(defaultSubnet, allSettings.Firewall.AllowedSubnets, defaultInterface) err = firewallConf.CreateLocalSubnetsRules(defaultSubnet, allSettings.Firewall.AllowedSubnets, defaultInterface)
e.FatalOnError(err) e.FatalOnError(err)

View File

@@ -18,8 +18,7 @@ type Configurator interface {
Clear() error Clear() error
BlockAll() error BlockAll() error
CreateGeneralRules() error CreateGeneralRules() error
CreateVPNRules(dev models.VPNDevice, serverIPs []net.IP, defaultInterface string, CreateVPNRules(dev models.VPNDevice, defaultInterface string, connections []models.OpenVPNConnection) error
port uint16, protocol models.NetworkProtocol) error
CreateLocalSubnetsRules(subnet net.IPNet, extraSubnets []net.IPNet, defaultInterface string) error CreateLocalSubnetsRules(subnet net.IPNet, extraSubnets []net.IPNet, defaultInterface string) error
AddRoutesVia(subnets []net.IPNet, defaultGateway net.IP, defaultInterface string) error AddRoutesVia(subnets []net.IPNet, defaultGateway net.IP, defaultInterface string) error
GetDefaultRoute() (defaultInterface string, defaultGateway net.IP, defaultSubnet net.IPNet, err error) GetDefaultRoute() (defaultInterface string, defaultGateway net.IP, defaultSubnet net.IPNet, err error)

View File

@@ -77,14 +77,13 @@ func (c *configurator) CreateGeneralRules() error {
}) })
} }
func (c *configurator) CreateVPNRules(dev models.VPNDevice, serverIPs []net.IP, func (c *configurator) CreateVPNRules(dev models.VPNDevice, defaultInterface string, connections []models.OpenVPNConnection) error {
defaultInterface string, port uint16, protocol models.NetworkProtocol) error { for _, connection := range connections {
for _, serverIP := range serverIPs {
c.logger.Info("%s: allowing output traffic to VPN server %s through %s on port %s %d", c.logger.Info("%s: allowing output traffic to VPN server %s through %s on port %s %d",
logPrefix, serverIP, defaultInterface, protocol, port) logPrefix, connection.IP, defaultInterface, connection.Protocol, connection.Port)
if err := c.runIptablesInstruction( if err := c.runIptablesInstruction(
fmt.Sprintf("-A OUTPUT -d %s -o %s -p %s -m %s --dport %d -j ACCEPT", fmt.Sprintf("-A OUTPUT -d %s -o %s -p %s -m %s --dport %d -j ACCEPT",
serverIP, defaultInterface, protocol, protocol, port)); err != nil { connection.IP, defaultInterface, connection.Protocol, connection.Protocol, connection.Port)); err != nil {
return err return err
} }
} }

View File

@@ -0,0 +1,9 @@
package models
import "net"
type OpenVPNConnection struct {
IP net.IP
Port uint16
Protocol NetworkProtocol
}

View File

@@ -2,45 +2,59 @@ package pia
import ( import (
"fmt" "fmt"
"net"
"github.com/qdm12/golibs/files" "github.com/qdm12/golibs/files"
"github.com/qdm12/private-internet-access-docker/internal/constants" "github.com/qdm12/private-internet-access-docker/internal/constants"
"github.com/qdm12/private-internet-access-docker/internal/models" "github.com/qdm12/private-internet-access-docker/internal/models"
) )
func (c *configurator) BuildConf(region models.PIARegion, protocol models.NetworkProtocol, func (c *configurator) GetOpenVPNConnections(region models.PIARegion, protocol models.NetworkProtocol, encryption models.PIAEncryption) (connections []models.OpenVPNConnection, err error) {
encryption models.PIAEncryption, uid, gid int) (IPs []net.IP, port uint16, err error) { subdomain, err := constants.PIAGeoToSubdomainMapping(region)
var X509CRL, certificate string // depends on encryption if err != nil {
var cipherAlgo, authAlgo string // depends on encryption return nil, err
}
IPs, err := c.lookupIP(subdomain + ".privateinternetaccess.com")
if err != nil {
return nil, err
}
var port uint16
switch protocol {
case constants.TCP:
switch encryption {
case constants.PIAEncryptionNormal:
port = 502
case constants.PIAEncryptionStrong:
port = 501
}
case constants.UDP:
switch encryption {
case constants.PIAEncryptionNormal:
port = 1198
case constants.PIAEncryptionStrong:
port = 1197
}
}
if port == 0 {
return nil, fmt.Errorf("combination of protocol %q and encryption %q does not yield any port number", protocol, encryption)
}
for _, IP := range IPs {
connections = append(connections, models.OpenVPNConnection{IP: IP, Port: port})
}
return connections, nil
}
func (c *configurator) BuildConf(connections []models.OpenVPNConnection, encryption models.PIAEncryption, uid, gid int) (err error) {
var X509CRL, certificate, cipherAlgo, authAlgo string
if encryption == constants.PIAEncryptionNormal { if encryption == constants.PIAEncryptionNormal {
cipherAlgo = "aes-128-cbc" cipherAlgo = "aes-128-cbc"
authAlgo = "sha1" authAlgo = "sha1"
X509CRL = constants.PIAX509CRL_NORMAL X509CRL = constants.PIAX509CRL_NORMAL
certificate = constants.PIACertificate_NORMAL certificate = constants.PIACertificate_NORMAL
if protocol == constants.UDP { } else { // strong encryption
port = 1198
} else {
port = 502
}
} else { // strong
cipherAlgo = "aes-256-cbc" cipherAlgo = "aes-256-cbc"
authAlgo = "sha256" authAlgo = "sha256"
X509CRL = constants.PIAX509CRL_STRONG X509CRL = constants.PIAX509CRL_STRONG
certificate = constants.PIACertificate_STRONG certificate = constants.PIACertificate_STRONG
if protocol == constants.UDP {
port = 1197
} else {
port = 501
}
}
subdomain, err := constants.PIAGeoToSubdomainMapping(region)
if err != nil {
return nil, 0, err
}
IPs, err = c.lookupIP(subdomain + ".privateinternetaccess.com")
if err != nil {
return nil, 0, err
} }
lines := []string{ lines := []string{
"client", "client",
@@ -63,12 +77,12 @@ func (c *configurator) BuildConf(region models.PIARegion, protocol models.Networ
// Modified variables // Modified variables
fmt.Sprintf("auth-user-pass %s", constants.OpenVPNAuthConf), fmt.Sprintf("auth-user-pass %s", constants.OpenVPNAuthConf),
fmt.Sprintf("proto %s", string(protocol)), fmt.Sprintf("proto %s", string(connections[0].Protocol)),
fmt.Sprintf("cipher %s", cipherAlgo), fmt.Sprintf("cipher %s", cipherAlgo),
fmt.Sprintf("auth %s", authAlgo), fmt.Sprintf("auth %s", authAlgo),
} }
for _, IP := range IPs { for _, connection := range connections {
lines = append(lines, fmt.Sprintf("remote %s %d", IP.String(), port)) lines = append(lines, fmt.Sprintf("remote %s %d", connection.IP.String(), connection.Port))
} }
lines = append(lines, []string{ lines = append(lines, []string{
"<crl-verify>", "<crl-verify>",
@@ -85,6 +99,5 @@ func (c *configurator) BuildConf(region models.PIARegion, protocol models.Networ
"</ca>", "</ca>",
"", "",
}...) }...)
err = c.fileManager.WriteLinesToFile(string(constants.OpenVPNConf), lines, files.Ownership(uid, gid), files.Permissions(0400)) return c.fileManager.WriteLinesToFile(string(constants.OpenVPNConf), lines, files.Ownership(uid, gid), files.Permissions(0400))
return IPs, port, err
} }

View File

@@ -16,8 +16,9 @@ const logPrefix = "PIA configurator"
// Configurator contains methods to download, read and modify the openvpn configuration to connect as a client // Configurator contains methods to download, read and modify the openvpn configuration to connect as a client
type Configurator interface { type Configurator interface {
BuildConf(region models.PIARegion, protocol models.NetworkProtocol, GetOpenVPNConnections(region models.PIARegion, protocol models.NetworkProtocol,
encryption models.PIAEncryption, uid, gid int) (IPs []net.IP, port uint16, err error) encryption models.PIAEncryption) (connections []models.OpenVPNConnection, err error)
BuildConf(connections []models.OpenVPNConnection, encryption models.PIAEncryption, uid, gid int) (err error)
GetPortForward() (port uint16, err error) GetPortForward() (port uint16, err error)
WritePortForward(filepath models.Filepath, port uint16) (err error) WritePortForward(filepath models.Filepath, port uint16) (err error)
AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error) AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error)