From ce11745f6ff7cbdb56aa12e382bd3b5b7efde220 Mon Sep 17 00:00:00 2001 From: "Quentin McGaw (desktop)" Date: Sun, 16 Feb 2020 19:50:21 +0000 Subject: [PATCH] Using struct for VPN connection settings --- cmd/main.go | 6 ++- internal/firewall/firewall.go | 3 +- internal/firewall/iptables.go | 9 ++--- internal/models/openvpn.go | 9 +++++ internal/pia/conf.go | 71 +++++++++++++++++++++-------------- internal/pia/pia.go | 5 ++- 6 files changed, 63 insertions(+), 40 deletions(-) create mode 100644 internal/models/openvpn.go diff --git a/cmd/main.go b/cmd/main.go index 2540c796..a7e0160c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -115,7 +115,9 @@ func main() { 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) defaultInterface, defaultGateway, defaultSubnet, err := firewallConf.GetDefaultRoute() @@ -128,7 +130,7 @@ func main() { e.FatalOnError(err) err = firewallConf.CreateGeneralRules() e.FatalOnError(err) - err = firewallConf.CreateVPNRules(constants.TUN, VPNIPs, defaultInterface, port, allSettings.OpenVPN.NetworkProtocol) + err = firewallConf.CreateVPNRules(constants.TUN, defaultInterface, connections) e.FatalOnError(err) err = firewallConf.CreateLocalSubnetsRules(defaultSubnet, allSettings.Firewall.AllowedSubnets, defaultInterface) e.FatalOnError(err) diff --git a/internal/firewall/firewall.go b/internal/firewall/firewall.go index 2c191036..fe101cfa 100644 --- a/internal/firewall/firewall.go +++ b/internal/firewall/firewall.go @@ -18,8 +18,7 @@ type Configurator interface { Clear() error BlockAll() error CreateGeneralRules() error - CreateVPNRules(dev models.VPNDevice, serverIPs []net.IP, defaultInterface string, - port uint16, protocol models.NetworkProtocol) error + CreateVPNRules(dev models.VPNDevice, defaultInterface string, connections []models.OpenVPNConnection) error CreateLocalSubnetsRules(subnet net.IPNet, extraSubnets []net.IPNet, defaultInterface string) error AddRoutesVia(subnets []net.IPNet, defaultGateway net.IP, defaultInterface string) error GetDefaultRoute() (defaultInterface string, defaultGateway net.IP, defaultSubnet net.IPNet, err error) diff --git a/internal/firewall/iptables.go b/internal/firewall/iptables.go index 7aa4d32a..f53c99cd 100644 --- a/internal/firewall/iptables.go +++ b/internal/firewall/iptables.go @@ -77,14 +77,13 @@ func (c *configurator) CreateGeneralRules() error { }) } -func (c *configurator) CreateVPNRules(dev models.VPNDevice, serverIPs []net.IP, - defaultInterface string, port uint16, protocol models.NetworkProtocol) error { - for _, serverIP := range serverIPs { +func (c *configurator) CreateVPNRules(dev models.VPNDevice, defaultInterface string, connections []models.OpenVPNConnection) error { + for _, connection := range connections { 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( 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 } } diff --git a/internal/models/openvpn.go b/internal/models/openvpn.go new file mode 100644 index 00000000..837f04fa --- /dev/null +++ b/internal/models/openvpn.go @@ -0,0 +1,9 @@ +package models + +import "net" + +type OpenVPNConnection struct { + IP net.IP + Port uint16 + Protocol NetworkProtocol +} diff --git a/internal/pia/conf.go b/internal/pia/conf.go index b9e858c9..a1533322 100644 --- a/internal/pia/conf.go +++ b/internal/pia/conf.go @@ -2,45 +2,59 @@ package pia import ( "fmt" - "net" "github.com/qdm12/golibs/files" "github.com/qdm12/private-internet-access-docker/internal/constants" "github.com/qdm12/private-internet-access-docker/internal/models" ) -func (c *configurator) BuildConf(region models.PIARegion, protocol models.NetworkProtocol, - encryption models.PIAEncryption, uid, gid int) (IPs []net.IP, port uint16, err error) { - var X509CRL, certificate string // depends on encryption - var cipherAlgo, authAlgo string // depends on encryption +func (c *configurator) GetOpenVPNConnections(region models.PIARegion, protocol models.NetworkProtocol, encryption models.PIAEncryption) (connections []models.OpenVPNConnection, err error) { + subdomain, err := constants.PIAGeoToSubdomainMapping(region) + if err != nil { + 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 { cipherAlgo = "aes-128-cbc" authAlgo = "sha1" X509CRL = constants.PIAX509CRL_NORMAL certificate = constants.PIACertificate_NORMAL - if protocol == constants.UDP { - port = 1198 - } else { - port = 502 - } - } else { // strong + } else { // strong encryption cipherAlgo = "aes-256-cbc" authAlgo = "sha256" X509CRL = constants.PIAX509CRL_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{ "client", @@ -63,12 +77,12 @@ func (c *configurator) BuildConf(region models.PIARegion, protocol models.Networ // Modified variables 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("auth %s", authAlgo), } - for _, IP := range IPs { - lines = append(lines, fmt.Sprintf("remote %s %d", IP.String(), port)) + for _, connection := range connections { + lines = append(lines, fmt.Sprintf("remote %s %d", connection.IP.String(), connection.Port)) } lines = append(lines, []string{ "", @@ -85,6 +99,5 @@ func (c *configurator) BuildConf(region models.PIARegion, protocol models.Networ "", "", }...) - err = c.fileManager.WriteLinesToFile(string(constants.OpenVPNConf), lines, files.Ownership(uid, gid), files.Permissions(0400)) - return IPs, port, err + return c.fileManager.WriteLinesToFile(string(constants.OpenVPNConf), lines, files.Ownership(uid, gid), files.Permissions(0400)) } diff --git a/internal/pia/pia.go b/internal/pia/pia.go index 880335b4..48283de1 100644 --- a/internal/pia/pia.go +++ b/internal/pia/pia.go @@ -16,8 +16,9 @@ const logPrefix = "PIA configurator" // Configurator contains methods to download, read and modify the openvpn configuration to connect as a client type Configurator interface { - BuildConf(region models.PIARegion, protocol models.NetworkProtocol, - encryption models.PIAEncryption, uid, gid int) (IPs []net.IP, port uint16, err error) + GetOpenVPNConnections(region models.PIARegion, protocol models.NetworkProtocol, + 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) WritePortForward(filepath models.Filepath, port uint16) (err error) AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error)