diff --git a/cmd/main.go b/cmd/main.go index 5db8ab64..4934714e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -85,12 +85,7 @@ func main() { e.FatalOnError(err) } - lines, err := piaConf.DownloadOvpnConfig(allSettings.PIA.Encryption, allSettings.OpenVPN.NetworkProtocol, allSettings.PIA.Region) - e.FatalOnError(err) - VPNIPs, port, VPNDevice, err := piaConf.ParseConfig(lines) - e.FatalOnError(err) - lines = piaConf.ModifyLines(lines, VPNIPs, port) - fileManager.WriteLinesToFile(string(constants.OpenVPNConf), lines) + VPNIPs, port, err := piaConf.BuildConf(allSettings.PIA.Region, allSettings.OpenVPN.NetworkProtocol, allSettings.PIA.Encryption, uid, gid) e.FatalOnError(err) defaultInterface, defaultGateway, defaultSubnet, err := firewallConf.GetDefaultRoute() @@ -103,7 +98,7 @@ func main() { e.FatalOnError(err) err = firewallConf.CreateGeneralRules() e.FatalOnError(err) - err = firewallConf.CreateVPNRules(VPNDevice, VPNIPs, defaultInterface, port, allSettings.OpenVPN.NetworkProtocol) + err = firewallConf.CreateVPNRules(constants.TUN, VPNIPs, defaultInterface, port, allSettings.OpenVPN.NetworkProtocol) e.FatalOnError(err) err = firewallConf.CreateLocalSubnetsRules(defaultSubnet, allSettings.Firewall.AllowedSubnets, defaultInterface) e.FatalOnError(err) @@ -133,7 +128,7 @@ func main() { if err := piaConf.WritePortForward(allSettings.PIA.PortForwarding.Filepath, port); err != nil { logger.Error("port forwarding:", err) } - if err := piaConf.AllowPortForwardFirewall(VPNDevice, port); err != nil { + if err := piaConf.AllowPortForwardFirewall(constants.TUN, port); err != nil { logger.Error("port forwarding:", err) } }) diff --git a/internal/constants/pia.go b/internal/constants/pia.go index 7be742d3..a1bc1b92 100644 --- a/internal/constants/pia.go +++ b/internal/constants/pia.go @@ -11,6 +11,13 @@ const ( PIAEncryptionStrong models.PIAEncryption = "strong" ) +const ( + PIAX509CRL_NORMAL = "MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EWB4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Reze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqyMR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A==" + PIAX509CRL_STRONG = "MIIDWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZaMCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG9w0BAQ0FAAOCAgEAppFfEpGsasjB1QgJcosGpzbf2kfRhM84o2TlqY1ua+Gi5TMdKydA3LJcNTjlI9a0TYAJfeRX5IkpoglSUuHuJgXhP3nEvX10mjXDpcu/YvM8TdE5JV2+EGqZ80kFtBeOq94WcpiVKFTR4fO+VkOK9zwspFfb1cNs9rHvgJ1QMkRUF8PpLN6AkntHY0+6DnigtSaKqldqjKTDTv2OeH3nPoh80SGrt0oCOmYKfWTJGpggMGKvIdvU3vH9+EuILZKKIskt+1dwdfA5Bkz1GLmiQG7+9ZZBQUjBG9Dos4hfX/rwJ3eU8oUIm4WoTz9rb71SOEuUUjP5NPy9HNx2vx+cVvLsTF4ZDZaUztW9o9JmIURDtbeyqxuHN3prlPWB6aj73IIm2dsDQvs3XXwRIxs8NwLbJ6CyEuvEOVCskdM8rdADWx1J0lRNlOJ0Z8ieLLEmYAA834VN1SboB6wJIAPxQU3rcBhXqO9y8aa2oRMg8NxZ5gr+PnKVMqag1x0IxbIgLxtkXQvxXxQHEMSODzvcOfK/nBRBsqTj30P+R87sU8titOoxNeRnBDRNhdEy/QGAqGh62ShPpQUCJdnKRiRTjnil9hMQHevoSuFKeEMO30FQL7BZyo37GFU+q1WPCplVZgCP9hC8Rn5K2+f6KLFo5bhtowSmu+GY1yZtg+RTtsA=" + PIACertificate_NORMAL = "MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXDL1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzXlH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWpcdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RCOfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tLy8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZOsqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpMb3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2VzczEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5jb22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAna5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xUryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK37pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyCGohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUtYDQ8z9v+DMO6iwyIDRiU" + PIACertificate_STRONG = "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" +) + const ( AUMelbourne models.PIARegion = "AU Melbourne" AUPerth models.PIARegion = "AU Perth" @@ -65,6 +72,111 @@ const ( ) const ( - PIAOpenVPNURL models.URL = "https://www.privateinternetaccess.com/openvpn" + PIASubdomainAUMelbourne string = "au-melbourne" + PIASubdomainAUPerth string = "au-perth" + PIASubdomainAUSydney string = "au-sydney" + PIASubdomainAustria string = "austria" + PIASubdomainBelgium string = "belgium" + PIASubdomainCAMontreal string = "ca-montreal" + PIASubdomainCAToronto string = "ca-toronto" + PIASubdomainCAVancouver string = "ca-vancouver" + PIASubdomainCzechRepublic string = "czech" + PIASubdomainDEBerlin string = "de-berlin" + PIASubdomainDEFrankfurt string = "de-frankfurt" + PIASubdomainDenmark string = "denmark" + PIASubdomainFinland string = "fi" + PIASubdomainFrance string = "france" + PIASubdomainHongKong string = "hk" + PIASubdomainHungary string = "hungary" + PIASubdomainIndia string = "in" + PIASubdomainIreland string = "ireland" + PIASubdomainIsrael string = "israel" + PIASubdomainItaly string = "italy" + PIASubdomainJapan string = "japan" + PIASubdomainLuxembourg string = "lu" + PIASubdomainMexico string = "mexico" + PIASubdomainNetherlands string = "nl" + PIASubdomainNewZealand string = "nz" + PIASubdomainNorway string = "no" + PIASubdomainPoland string = "poland" + PIASubdomainRomania string = "ro" + PIASubdomainSingapore string = "sg" + PIASubdomainSpain string = "spain" + PIASubdomainSweden string = "sweden" + PIASubdomainSwitzerland string = "swiss" + PIASubdomainUAE string = "ae" + PIASubdomainUKLondon string = "uk-london" + PIASubdomainUKManchester string = "uk-manchester" + PIASubdomainUKSouthampton string = "uk-southampton" + PIASubdomainUSAtlanta string = "us-atlanta" + PIASubdomainUSCalifornia string = "us-california" + PIASubdomainUSChicago string = "us-chicago" + PIASubdomainUSDenver string = "us-denver" + PIASubdomainUSEast string = "us-east" + PIASubdomainUSFlorida string = "us-florida" + PIASubdomainUSHouston string = "us-houston" + PIASubdomainUSLasVegas string = "us-lasvegas" + PIASubdomainUSNewYorkCity string = "us-newyorkcity" + PIASubdomainUSSeattle string = "us-seattle" + PIASubdomainUSSiliconValley string = "us-siliconvalley" + PIASubdomainUSTexas string = "us-texas" + PIASubdomainUSWashingtonDC string = "us-washingtondc" + PIASubdomainUSWest string = "us-west" +) + +var PIARegionToSubdomainMapping = map[models.PIARegion]string{ + AUMelbourne: PIASubdomainAUMelbourne, + AUPerth: PIASubdomainAUPerth, + AUSydney: PIASubdomainAUSydney, + Austria: PIASubdomainAustria, + Belgium: PIASubdomainBelgium, + CAMontreal: PIASubdomainCAMontreal, + CAToronto: PIASubdomainCAToronto, + CAVancouver: PIASubdomainCAVancouver, + CzechRepublic: PIASubdomainCzechRepublic, + DEBerlin: PIASubdomainDEBerlin, + DEFrankfurt: PIASubdomainDEFrankfurt, + Denmark: PIASubdomainDenmark, + Finland: PIASubdomainFinland, + France: PIASubdomainFrance, + HongKong: PIASubdomainHongKong, + Hungary: PIASubdomainHungary, + India: PIASubdomainIndia, + Ireland: PIASubdomainIreland, + Israel: PIASubdomainIsrael, + Italy: PIASubdomainItaly, + Japan: PIASubdomainJapan, + Luxembourg: PIASubdomainLuxembourg, + Mexico: PIASubdomainMexico, + Netherlands: PIASubdomainNetherlands, + NewZealand: PIASubdomainNewZealand, + Norway: PIASubdomainNorway, + Poland: PIASubdomainPoland, + Romania: PIASubdomainRomania, + Singapore: PIASubdomainSingapore, + Spain: PIASubdomainSpain, + Sweden: PIASubdomainSweden, + Switzerland: PIASubdomainSwitzerland, + UAE: PIASubdomainUAE, + UKLondon: PIASubdomainUKLondon, + UKManchester: PIASubdomainUKManchester, + UKSouthampton: PIASubdomainUKSouthampton, + USAtlanta: PIASubdomainUSAtlanta, + USCalifornia: PIASubdomainUSCalifornia, + USChicago: PIASubdomainUSChicago, + USDenver: PIASubdomainUSDenver, + USEast: PIASubdomainUSEast, + USFlorida: PIASubdomainUSFlorida, + USHouston: PIASubdomainUSHouston, + USLasVegas: PIASubdomainUSLasVegas, + USNewYorkCity: PIASubdomainUSNewYorkCity, + USSeattle: PIASubdomainUSSeattle, + USSiliconValley: PIASubdomainUSSiliconValley, + USTexas: PIASubdomainUSTexas, + USWashingtonDC: PIASubdomainUSWashingtonDC, + USWest: PIASubdomainUSWest, +} + +const ( PIAPortForwardURL models.URL = "http://209.222.18.222:2000" ) diff --git a/internal/pia/conf.go b/internal/pia/conf.go new file mode 100644 index 00000000..28bc8358 --- /dev/null +++ b/internal/pia/conf.go @@ -0,0 +1,86 @@ +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 + 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 + cipherAlgo = "aes-256-cbc" + authAlgo = "sha256" + X509CRL = constants.PIAX509CRL_STRONG + certificate = constants.PIACertificate_STRONG + if protocol == constants.UDP { + port = 1197 + } else { + port = 501 + } + } + subdomain := constants.PIARegionToSubdomainMapping[region] + IPs, err = c.lookupIP(subdomain + ".privateinternetaccess.com") + if err != nil { + return nil, 0, err + } + lines := []string{ + "client", + "dev tun", + "nobind", + "persist-key", + "persist-tun", + "tls-client", + "remote-cert-tls server", + "compress", + "verb 1", // TODO env variable + "reneg-sec 0", + // Added constant values + "mute-replay-warnings", + "user nonrootuser", + "pull-filter ignore \"auth-token\"", // prevent auth failed loops + "auth-retry nointeract", + "disable-occ", + + // Modified variables + fmt.Sprintf("auth-user-pass %s", constants.OpenVPNAuthConf), + fmt.Sprintf("proto %s", string(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)) + } + lines = append(lines, []string{ + "", + "-----BEGIN X509 CRL-----", + X509CRL, + "-----END X509 CRL-----", + "", + }...) + lines = append(lines, []string{ + "", + "-----BEGIN CERTIFICATE-----", + certificate, + "-----END CERTIFICATE-----", + "", + "", + }...) + err = c.fileManager.WriteLinesToFile(string(constants.OpenVPNConf), lines, files.FileOwnership(uid, gid), files.FilePermissions(0400)) + return IPs, port, err +} diff --git a/internal/pia/download.go b/internal/pia/download.go deleted file mode 100644 index e9236d91..00000000 --- a/internal/pia/download.go +++ /dev/null @@ -1,61 +0,0 @@ -package pia - -import ( - "archive/zip" - "bytes" - "fmt" - "io/ioutil" - "strings" - - "github.com/qdm12/private-internet-access-docker/internal/constants" - "github.com/qdm12/private-internet-access-docker/internal/models" -) - -func (c *configurator) DownloadOvpnConfig(encryption models.PIAEncryption, - protocol models.NetworkProtocol, region models.PIARegion) (lines []string, err error) { - c.logger.Info("%s: downloading openvpn configuration files", logPrefix) - URL := buildZipURL(encryption, protocol) - content, status, err := c.client.GetContent(URL) - if err != nil { - return nil, err - } else if status != 200 { - return nil, fmt.Errorf("HTTP Get %s resulted in HTTP status code %d", URL, status) - } - filename := fmt.Sprintf("%s.ovpn", region) - fileContent, err := getFileInZip(content, filename) - if err != nil { - return nil, fmt.Errorf("%s: %w", URL, err) - } - lines = strings.Split(string(fileContent), "\n") - return lines, nil -} - -func buildZipURL(encryption models.PIAEncryption, protocol models.NetworkProtocol) (URL string) { - URL = string(constants.PIAOpenVPNURL) + "/openvpn" - if encryption == constants.PIAEncryptionStrong { - URL += "-strong" - } - if protocol == constants.TCP { - URL += "-tcp" - } - return URL + ".zip" -} - -func getFileInZip(zipContent []byte, filename string) (fileContent []byte, err error) { - contentLength := int64(len(zipContent)) - r, err := zip.NewReader(bytes.NewReader(zipContent), contentLength) - if err != nil { - return nil, err - } - for _, f := range r.File { - if f.Name == filename { - readCloser, err := f.Open() - if err != nil { - return nil, err - } - defer readCloser.Close() - return ioutil.ReadAll(readCloser) - } - } - return nil, fmt.Errorf("%s not found in zip archive file", filename) -} diff --git a/internal/pia/modify.go b/internal/pia/modify.go deleted file mode 100644 index ce6c9131..00000000 --- a/internal/pia/modify.go +++ /dev/null @@ -1,31 +0,0 @@ -package pia - -import ( - "fmt" - "net" - "strings" - - "github.com/qdm12/private-internet-access-docker/internal/constants" -) - -func (c *configurator) ModifyLines(lines []string, IPs []net.IP, port uint16) (modifiedLines []string) { - c.logger.Info("%s: adapting openvpn configuration for server IP addresses and port %d", logPrefix, port) - // Remove lines - for _, line := range lines { - if strings.Contains(line, "privateinternetaccess.com") || - strings.Contains(line, "resolv-retry") { - continue - } - modifiedLines = append(modifiedLines, line) - } - // Add lines - for _, IP := range IPs { - modifiedLines = append(modifiedLines, fmt.Sprintf("remote %s %d", IP.String(), port)) - } - modifiedLines = append(modifiedLines, "auth-user-pass "+string(constants.OpenVPNAuthConf)) - modifiedLines = append(modifiedLines, "auth-retry nointeract") - modifiedLines = append(modifiedLines, "pull-filter ignore \"auth-token\"") // prevent auth failed loops - modifiedLines = append(modifiedLines, "user nonrootuser") - modifiedLines = append(modifiedLines, "mute-replay-warnings") - return modifiedLines -} diff --git a/internal/pia/modify_test.go b/internal/pia/modify_test.go deleted file mode 100644 index 01c1e676..00000000 --- a/internal/pia/modify_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package pia - -import ( - "io/ioutil" - "net" - "strings" - "testing" - - loggingMocks "github.com/qdm12/golibs/logging/mocks" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_ModifyLines(t *testing.T) { - t.Parallel() - original, err := ioutil.ReadFile("testdata/ovpn.golden") - require.NoError(t, err) - originalLines := strings.Split(string(original), "\n") - expected, err := ioutil.ReadFile("testdata/ovpn.modified.golden") - require.NoError(t, err) - expectedLines := strings.Split(string(expected), "\n") - - var port uint16 = 3000 - IPs := []net.IP{net.IP{100, 10, 10, 10}, net.IP{100, 20, 20, 20}} - logger := &loggingMocks.Logger{} - logger.On("Info", "%s: adapting openvpn configuration for server IP addresses and port %d", logPrefix, port).Once() - c := &configurator{logger: logger} - modifiedLines := c.ModifyLines(originalLines, IPs, port) - assert.Equal(t, expectedLines, modifiedLines) - logger.AssertExpectations(t) -} diff --git a/internal/pia/parse.go b/internal/pia/parse.go deleted file mode 100644 index 9b5e8285..00000000 --- a/internal/pia/parse.go +++ /dev/null @@ -1,54 +0,0 @@ -package pia - -import ( - "fmt" - "net" - "strconv" - "strings" - - "github.com/qdm12/private-internet-access-docker/internal/constants" - "github.com/qdm12/private-internet-access-docker/internal/models" -) - -func (c *configurator) ParseConfig(lines []string) (IPs []net.IP, port uint16, device models.VPNDevice, err error) { - c.logger.Info("%s: parsing openvpn configuration", logPrefix) - remoteLineFound := false - deviceLineFound := false - for _, line := range lines { - if strings.HasPrefix(line, "remote ") { - remoteLineFound = true - words := strings.Fields(line) - if len(words) != 3 { - return nil, 0, "", fmt.Errorf("line %q misses information", line) - } - host := words[1] - if err := c.verifyPort(words[2]); err != nil { - return nil, 0, "", fmt.Errorf("line %q has an invalid port: %w", line, err) - } - portUint64, _ := strconv.ParseUint(words[2], 10, 16) - port = uint16(portUint64) - IPs, err = c.lookupIP(host) - if err != nil { - return nil, 0, "", err - } - } else if strings.HasPrefix(line, "dev ") { - deviceLineFound = true - fields := strings.Fields(line) - if len(fields) != 2 { - return nil, 0, "", fmt.Errorf("line %q misses information", line) - } - device = models.VPNDevice(fields[1] + "0") - if device != constants.TUN && device != constants.TAP { - return nil, 0, "", fmt.Errorf("device %q is not valid", device) - } - } - } - if remoteLineFound && deviceLineFound { - c.logger.Info("%s: Found %d PIA server IP addresses, port %d and device %s", logPrefix, len(IPs), port, device) - return IPs, port, device, nil - } else if !remoteLineFound { - return nil, 0, "", fmt.Errorf("remote line not found in Openvpn configuration") - } else { - return nil, 0, "", fmt.Errorf("device line not found in Openvpn configuration") - } -} diff --git a/internal/pia/parse_test.go b/internal/pia/parse_test.go deleted file mode 100644 index d0a2d0e9..00000000 --- a/internal/pia/parse_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package pia - -import ( - "fmt" - "io/ioutil" - "net" - "strings" - "testing" - - loggingMocks "github.com/qdm12/golibs/logging/mocks" - "github.com/qdm12/golibs/verification" - "github.com/qdm12/private-internet-access-docker/internal/constants" - "github.com/qdm12/private-internet-access-docker/internal/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_ParseConfig(t *testing.T) { - t.Parallel() - original, err := ioutil.ReadFile("testdata/ovpn.golden") - require.NoError(t, err) - exampleLines := strings.Split(string(original), "\n") - tests := map[string]struct { - lines []string - lookupIPs []net.IP - lookupIPErr error - IPs []net.IP - port uint16 - device models.VPNDevice - err error - }{ - "no data": { - err: fmt.Errorf("remote line not found in Openvpn configuration"), - }, - "bad remote line": { - lines: []string{"remote field2"}, - err: fmt.Errorf("line \"remote field2\" misses information"), - }, - "bad remote port": { - lines: []string{"remote field2 port"}, - err: fmt.Errorf("line \"remote field2 port\" has an invalid port: port \"port\" is not a valid integer"), - }, - "lookupIP error": { - lines: []string{"remote host 1000"}, - lookupIPErr: fmt.Errorf("lookup error"), - err: fmt.Errorf("lookup error"), - }, - "missing dev line": { - lines: []string{"remote host 1994"}, - err: fmt.Errorf("device line not found in Openvpn configuration"), - }, - "bad dev line": { - lines: []string{"dev field2 field3"}, - err: fmt.Errorf("line \"dev field2 field3\" misses information"), - }, - "bad device": { - lines: []string{"dev xx"}, - err: fmt.Errorf("device \"xx0\" is not valid"), - }, - "valid lines": { - lines: []string{"remote host 1194", "dev tap", "blabla"}, - port: 1194, - device: constants.TAP, - }, - "real data": { - lines: exampleLines, - lookupIPs: []net.IP{{100, 100, 100, 100}, {100, 100, 200, 200}}, - IPs: []net.IP{{100, 100, 100, 100}, {100, 100, 200, 200}}, - port: 1198, - device: constants.TUN, - }, - } - for name, tc := range tests { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - logger := &loggingMocks.Logger{} - logger.On("Info", "%s: parsing openvpn configuration", logPrefix).Once() - if tc.err == nil { - logger.On("Info", "%s: Found %d PIA server IP addresses, port %d and device %s", logPrefix, len(tc.IPs), tc.port, tc.device).Once() - } - lookupIP := func(host string) ([]net.IP, error) { - return tc.lookupIPs, tc.lookupIPErr - } - c := &configurator{logger: logger, verifyPort: verification.NewVerifier().VerifyPort, lookupIP: lookupIP} - IPs, port, device, err := c.ParseConfig(tc.lines) - if tc.err != nil { - require.Error(t, err) - assert.Equal(t, tc.err.Error(), err.Error()) - } else { - assert.NoError(t, err) - } - assert.Equal(t, tc.IPs, IPs) - assert.Equal(t, tc.port, port) - assert.Equal(t, tc.device, device) - logger.AssertExpectations(t) - }) - } -} diff --git a/internal/pia/pia.go b/internal/pia/pia.go index c0f96df5..880335b4 100644 --- a/internal/pia/pia.go +++ b/internal/pia/pia.go @@ -16,10 +16,8 @@ const logPrefix = "PIA configurator" // Configurator contains methods to download, read and modify the openvpn configuration to connect as a client type Configurator interface { - DownloadOvpnConfig(encryption models.PIAEncryption, - protocol models.NetworkProtocol, region models.PIARegion) (lines []string, err error) - ParseConfig(lines []string) (IPs []net.IP, port uint16, device models.VPNDevice, err error) - ModifyLines(lines []string, IPs []net.IP, port uint16) (modifiedLines []string) + BuildConf(region models.PIARegion, protocol models.NetworkProtocol, + encryption models.PIAEncryption, uid, gid int) (IPs []net.IP, port uint16, err error) GetPortForward() (port uint16, err error) WritePortForward(filepath models.Filepath, port uint16) (err error) AllowPortForwardFirewall(device models.VPNDevice, port uint16) (err error) diff --git a/internal/pia/testdata/ovpn.golden b/internal/pia/testdata/ovpn.golden deleted file mode 100644 index 2a80fd55..00000000 --- a/internal/pia/testdata/ovpn.golden +++ /dev/null @@ -1,72 +0,0 @@ -client -dev tun -proto udp -remote belgium.privateinternetaccess.com 1198 -resolv-retry infinite -nobind -persist-key -persist-tun -cipher aes-128-cbc -auth sha1 -tls-client -remote-cert-tls server - -auth-user-pass -compress -verb 1 -reneg-sec 0 - ------BEGIN X509 CRL----- -MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQI -EwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRl -cm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAw -HgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0 -ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRl -aW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZa -MCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG -9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5 -jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EW -B4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Re -ze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA -5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqy -MR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A== ------END X509 CRL----- - - - ------BEGIN CERTIFICATE----- -MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD -VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV -BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu -dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx -IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB -FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1 -MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex -EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg -QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE -AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50 -ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy -bmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXD -L1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzX -lH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWp -cdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/ -8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB -/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RC -OfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tL -y8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZO -sqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpM -b3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4G -A1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUg -SW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2Vz -czEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j -b22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAn -a5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xU -ryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK3 -7pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyC -GohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz -1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUt -YDQ8z9v+DMO6iwyIDRiU ------END CERTIFICATE----- - - -disable-occ diff --git a/internal/pia/testdata/ovpn.modified.golden b/internal/pia/testdata/ovpn.modified.golden deleted file mode 100644 index dfd10da6..00000000 --- a/internal/pia/testdata/ovpn.modified.golden +++ /dev/null @@ -1,78 +0,0 @@ -client -dev tun -proto udp -nobind -persist-key -persist-tun -cipher aes-128-cbc -auth sha1 -tls-client -remote-cert-tls server - -auth-user-pass -compress -verb 1 -reneg-sec 0 - ------BEGIN X509 CRL----- -MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQI -EwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRl -cm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAw -HgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0 -ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRl -aW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZa -MCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG -9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5 -jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EW -B4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Re -ze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA -5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqy -MR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A== ------END X509 CRL----- - - - ------BEGIN CERTIFICATE----- -MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD -VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV -BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu -dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx -IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB -FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1 -MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex -EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg -QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE -AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50 -ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy -bmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXD -L1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzX -lH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWp -cdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/ -8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB -/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RC -OfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tL -y8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZO -sqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpM -b3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4G -A1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUg -SW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2Vz -czEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j -b22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAn -a5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xU -ryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK3 -7pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyC -GohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz -1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUt -YDQ8z9v+DMO6iwyIDRiU ------END CERTIFICATE----- - - -disable-occ - -remote 100.10.10.10 3000 -remote 100.20.20.20 3000 -auth-user-pass /etc/openvpn/auth.conf -auth-retry nointeract -pull-filter ignore "auth-token" -user nonrootuser -mute-replay-warnings \ No newline at end of file