diff --git a/internal/configuration/purevpn.go b/internal/configuration/purevpn.go index 75d89792..3c80a28b 100644 --- a/internal/configuration/purevpn.go +++ b/internal/configuration/purevpn.go @@ -17,6 +17,10 @@ func (settings *Provider) purevpnLines() (lines []string) { lines = append(lines, lastIndent+"Cities: "+commaJoin(settings.ServerSelection.Cities)) } + if len(settings.ServerSelection.Hostnames) > 0 { + lines = append(lines, lastIndent+"Hostnames: "+commaJoin(settings.ServerSelection.Hostnames)) + } + return lines } @@ -48,5 +52,10 @@ func (settings *Provider) readPurevpn(r reader) (err error) { return err } + settings.ServerSelection.Hostnames, err = r.env.CSVInside("SERVER_HOSTNAME", constants.PurevpnHostnameChoices()) + if err != nil { + return err + } + return nil } diff --git a/internal/constants/purevpn.go b/internal/constants/purevpn.go index 21015bde..d7b8f864 100644 --- a/internal/constants/purevpn.go +++ b/internal/constants/purevpn.go @@ -41,48 +41,110 @@ func PurevpnCityChoices() (choices []string) { return makeUnique(choices) } +func PurevpnHostnameChoices() (choices []string) { + servers := PurevpnServers() + choices = make([]string, len(servers)) + for i := range servers { + choices[i] = servers[i].Hostname + } + return makeUnique(choices) +} + //nolint:lll // PurevpnServers returns a slice of all the server information for Purevpn. func PurevpnServers() []models.PurevpnServer { return []models.PurevpnServer{ - {Country: "Australia", Region: "New South Wales", City: "Sydney", IPs: []net.IP{{43, 245, 161, 81}, {43, 245, 161, 85}, {43, 245, 163, 82}, {46, 243, 245, 4}}}, - {Country: "Australia", Region: "Western Australia", City: "Perth", IPs: []net.IP{{43, 250, 205, 34}, {43, 250, 205, 52}, {43, 250, 205, 61}, {43, 250, 205, 63}, {43, 250, 205, 65}, {43, 250, 205, 50}, {43, 250, 205, 34}, {43, 250, 205, 61}, {43, 250, 205, 63}, {43, 250, 205, 50}, {43, 250, 205, 51}}}, - {Country: "Austria", Region: "Vienna", City: "Vienna", IPs: []net.IP{{37, 120, 212, 219}, {217, 64, 127, 251}, {217, 64, 127, 251}}}, - {Country: "Belgium", Region: "Flanders", City: "Zaventem", IPs: []net.IP{{217, 138, 211, 85}, {217, 138, 221, 114}, {217, 138, 211, 87}, {217, 138, 221, 120}, {217, 138, 221, 121}}}, - {Country: "Brazil", Region: "São Paulo", City: "São Paulo", IPs: []net.IP{{181, 41, 201, 84}, {181, 41, 201, 75}}}, - {Country: "Canada", Region: "British Columbia", City: "Vancouver", IPs: []net.IP{{66, 115, 147, 35}, {66, 115, 147, 36}, {66, 115, 147, 38}}}, - {Country: "Canada", Region: "Ontario", City: "Toronto", IPs: []net.IP{{104, 200, 138, 178}, {104, 200, 138, 216}, {104, 200, 138, 217}, {104, 200, 138, 213}}}, - {Country: "Czech Republic", Region: "Hlavní město Praha", City: "Prague", IPs: []net.IP{{185, 156, 174, 35}, {185, 156, 174, 35}, {185, 156, 174, 36}, {217, 138, 199, 251}}}, - {Country: "France", Region: "Île-de-France", City: "Paris", IPs: []net.IP{{45, 152, 181, 67}, {89, 40, 183, 149}, {45, 152, 181, 67}}}, - {Country: "Germany", Region: "Hesse", City: "Frankfurt am Main", IPs: []net.IP{{2, 57, 18, 26}, {5, 254, 88, 172}, {82, 102, 16, 110}, {172, 111, 203, 4}, {188, 72, 84, 4}, {5, 254, 82, 51}, {5, 254, 88, 171}, {5, 254, 88, 213}, {37, 120, 223, 51}}}, - {Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", IPs: []net.IP{{103, 109, 103, 60}, {172, 111, 168, 4}, {128, 1, 209, 52}, {128, 1, 209, 54}, {36, 255, 97, 3}, {103, 109, 103, 60}, {119, 81, 228, 109}}}, - {Country: "India", Region: "Karnataka", City: "Bengaluru", IPs: []net.IP{{169, 38, 69, 12}, {178, 170, 141, 4}, {169, 38, 69, 12}}}, - {Country: "Italy", Region: "Lombardy", City: "Milan", IPs: []net.IP{{172, 111, 173, 3}, {172, 111, 173, 3}}}, - {Country: "Japan", Region: "Okinawa", City: "Hirara", IPs: []net.IP{{128, 1, 155, 178}, {128, 1, 155, 178}}}, - {Country: "Japan", Region: "Tokyo", City: "Tokyo", IPs: []net.IP{{185, 242, 4, 59}}}, - {Country: "Korea", Region: "Seoul", City: "Seoul", IPs: []net.IP{{43, 226, 231, 4}, {43, 226, 231, 6}}}, - {Country: "Malaysia", Region: "Kuala Lumpur", City: "Kuala Lumpur", IPs: []net.IP{{103, 28, 90, 32}, {103, 55, 10, 133}, {103, 55, 10, 134}}}, - {Country: "Netherlands", Region: "North Holland", City: "Amsterdam", IPs: []net.IP{{104, 37, 6, 4}, {79, 142, 64, 51}, {92, 119, 179, 195}, {206, 123, 147, 4}, {5, 254, 73, 171}, {5, 254, 73, 172}, {79, 142, 64, 51}, {172, 83, 45, 114}, {104, 37, 6, 4}}}, - {Country: "Norway", Region: "Oslo", City: "Oslo", IPs: []net.IP{{82, 102, 22, 212}, {82, 102, 22, 212}}}, - {Country: "Poland", Region: "Mazovia", City: "Warsaw", IPs: []net.IP{{5, 253, 206, 251}}}, - {Country: "Portugal", Region: "Lisbon", City: "Lisbon", IPs: []net.IP{{5, 154, 174, 3}}}, - {Country: "Russian Federation", Region: "St.-Petersburg", City: "Saint Petersburg", IPs: []net.IP{{94, 242, 54, 23}, {206, 123, 139, 4}, {94, 242, 54, 23}, {206, 123, 139, 4}}}, - {Country: "Singapore", Region: "Singapore", City: "Singapore", IPs: []net.IP{{84, 247, 49, 181}, {192, 253, 249, 132}, {192, 253, 249, 132}, {37, 120, 208, 148}}}, - {Country: "South Africa", Region: "Gauteng", City: "Johannesburg", IPs: []net.IP{{102, 165, 3, 34}}}, - {Country: "Sweden", Region: "Stockholm", City: "Stockholm", IPs: []net.IP{{86, 106, 103, 183}, {86, 106, 103, 184}, {86, 106, 103, 187}, {86, 106, 103, 178}}}, - {Country: "Switzerland", Region: "Zurich", City: "Zürich", IPs: []net.IP{{45, 12, 222, 100}, {45, 12, 222, 103}, {45, 12, 222, 104}, {45, 12, 222, 107}, {45, 12, 222, 99}}}, - {Country: "United Kingdom", Region: "England", City: "London", IPs: []net.IP{{193, 9, 113, 67}, {193, 9, 113, 70}, {45, 74, 0, 4}, {45, 74, 0, 4}, {193, 9, 113, 67}, {193, 9, 113, 70}}}, - {Country: "United Kingdom", Region: "England", City: "Manchester", IPs: []net.IP{{188, 72, 89, 4}}}, - {Country: "United States", Region: "California", City: "Los Angeles", IPs: []net.IP{{104, 243, 243, 131}, {89, 45, 4, 2}, {104, 243, 243, 131}}}, - {Country: "United States", Region: "California", City: "Milpitas", IPs: []net.IP{{141, 101, 166, 4}}}, - {Country: "United States", Region: "Florida", City: "Miami", IPs: []net.IP{{5, 254, 79, 114}, {5, 254, 79, 115}, {5, 254, 79, 99}, {5, 254, 79, 116}, {5, 254, 79, 117}}}, - {Country: "United States", Region: "Georgia", City: "Atlanta", IPs: []net.IP{{141, 101, 168, 4}}}, - {Country: "United States", Region: "New Jersey", City: "Harrison", IPs: []net.IP{{172, 111, 149, 4}, {172, 111, 149, 4}}}, - {Country: "United States", Region: "New York", City: "New York City", IPs: []net.IP{{141, 101, 153, 4}, {172, 94, 72, 4}, {172, 94, 72, 4}}}, - {Country: "United States", Region: "Texas", City: "Allen", IPs: []net.IP{{172, 94, 108, 4}, {172, 94, 108, 4}}}, - {Country: "United States", Region: "Texas", City: "Dallas", IPs: []net.IP{{104, 217, 255, 179}, {104, 217, 255, 186}, {208, 84, 155, 100}, {172, 94, 1, 4}, {208, 84, 155, 100}, {208, 84, 155, 101}, {172, 94, 1, 4}, {172, 94, 72, 4}}}, - {Country: "United States", Region: "Utah", City: "Salt Lake City", IPs: []net.IP{{45, 74, 52, 4}, {46, 243, 249, 4}, {172, 94, 72, 4}, {45, 74, 52, 4}, {188, 72, 89, 4}, {45, 74, 52, 4}, {46, 243, 249, 4}, {172, 94, 26, 4}, {45, 74, 52, 4}, {141, 101, 168, 4}, {172, 94, 26, 4}, {172, 94, 72, 4}, {45, 74, 52, 4}, {172, 94, 1, 4}, {172, 94, 26, 4}}}, - {Country: "United States", Region: "Virginia", City: "Reston", IPs: []net.IP{{5, 254, 77, 26}, {5, 254, 77, 27}, {5, 254, 77, 28}, {5, 254, 77, 140}}}, - {Country: "United States", Region: "Washington, D.C.", City: "Washington", IPs: []net.IP{{46, 243, 249, 4}, {46, 243, 249, 4}, {46, 243, 249, 4}, {46, 243, 249, 4}, {46, 243, 249, 4}, {172, 94, 26, 4}, {172, 94, 72, 4}, {46, 243, 249, 4}, {172, 94, 72, 4}, {46, 243, 249, 4}}}, + {Country: "Australia", Region: "New South Wales", City: "Sydney", Hostname: "au-sd2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{43, 245, 163, 82}, {46, 243, 245, 4}}}, + {Country: "Australia", Region: "New South Wales", City: "Sydney", Hostname: "au-sd2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 245, 161, 80}, {43, 245, 161, 82}, {43, 245, 161, 84}}}, + {Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{43, 250, 205, 50}}}, + {Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 250, 205, 53}, {43, 250, 205, 65}}}, + {Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-pe-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{43, 250, 205, 50}}}, + {Country: "Australia", Region: "Western Australia", City: "Perth", Hostname: "au2-pe-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 250, 205, 52}, {43, 250, 205, 65}}}, + {Country: "Austria", Region: "Vienna", City: "Vienna", Hostname: "at2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{217, 64, 127, 251}, {217, 64, 127, 252}}}, + {Country: "Austria", Region: "Vienna", City: "Vienna", Hostname: "at2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{37, 120, 212, 218}, {37, 120, 212, 220}, {217, 64, 127, 251}}}, + {Country: "Belgium", Region: "Flanders", City: "Zaventem", Hostname: "vleu-be2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{217, 138, 211, 85}, {217, 138, 211, 86}, {217, 138, 211, 116}, {217, 138, 221, 114}}}, + {Country: "Belgium", Region: "Flanders", City: "Zaventem", Hostname: "vleu-be2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{217, 138, 211, 87}, {217, 138, 211, 88}, {217, 138, 211, 114}}}, + {Country: "Brazil", Region: "São Paulo", City: "São Paulo", Hostname: "br2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{181, 41, 201, 83}, {181, 41, 201, 84}}}, + {Country: "Brazil", Region: "São Paulo", City: "São Paulo", Hostname: "br2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{138, 99, 210, 4}, {181, 41, 201, 77}, {181, 41, 201, 83}}}, + {Country: "Canada", Region: "British Columbia", City: "Vancouver", Hostname: "cav2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{66, 115, 147, 34}, {66, 115, 147, 35}}}, + {Country: "Canada", Region: "British Columbia", City: "Vancouver", Hostname: "cav2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{66, 115, 147, 38}, {66, 115, 147, 39}, {66, 115, 147, 40}}}, + {Country: "Canada", Region: "Ontario", City: "Toronto", Hostname: "ca2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 200, 138, 212}, {104, 200, 138, 213}}}, + {Country: "Canada", Region: "Ontario", City: "Toronto", Hostname: "ca2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 200, 138, 178}, {104, 200, 138, 212}, {104, 200, 138, 218}, {104, 200, 138, 219}}}, + {Country: "Czech Republic", Region: "Hlavní město Praha", City: "Prague", Hostname: "cz2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{185, 156, 174, 35}, {185, 156, 174, 36}}}, + {Country: "Czech Republic", Region: "Hlavní město Praha", City: "Prague", Hostname: "cz2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{185, 156, 174, 36}, {217, 138, 199, 252}}}, + {Country: "France", Region: "Île-de-France", City: "Paris", Hostname: "fr2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{89, 40, 183, 148}}}, + {Country: "France", Region: "Île-de-France", City: "Paris", Hostname: "fr2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 152, 181, 69}, {45, 152, 181, 70}}}, + {Country: "Germany", Region: "Hesse", City: "Frankfurt am Main", Hostname: "de2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 88, 171}, {37, 120, 223, 50}}}, + {Country: "Germany", Region: "Hesse", City: "Frankfurt am Main", Hostname: "de2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{2, 57, 18, 22}, {217, 138, 194, 195}}}, + {Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "hk2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{103, 109, 103, 59}}}, + {Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "hk2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{103, 109, 103, 60}, {172, 111, 168, 4}}}, + {Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "vlap-ph2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{36, 255, 97, 3}, {129, 227, 119, 84}}}, + {Country: "Hong Kong", Region: "Central and Western", City: "Hong Kong", Hostname: "vlap-ph2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{128, 1, 209, 21}}}, + {Country: "India", Region: "Tamil Nadu", City: "Tinnanūr", Hostname: "in2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 250, 160, 132}, {178, 170, 141, 6}}}, + {Country: "Indonesia", Region: "Aceh", City: "Bireun", Hostname: "in2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{169, 38, 97, 242}, {169, 38, 129, 21}}}, + {Country: "Italy", Region: "Lombardy", City: "Milan", Hostname: "it2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 111, 173, 3}}}, + {Country: "Italy", Region: "Lombardy", City: "Milan", Hostname: "it2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 111, 173, 3}}}, + {Country: "Japan", Region: "Okinawa", City: "Hirara", Hostname: "tw2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{128, 1, 155, 178}}}, + {Country: "Japan", Region: "Okinawa", City: "Hirara", Hostname: "tw2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{128, 1, 155, 178}}}, + {Country: "Japan", Region: "Tokyo", City: "Tokyo", Hostname: "jp2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{185, 242, 4, 59}}}, + {Country: "Korea", Region: "Seoul", City: "Seoul", Hostname: "kr2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{43, 226, 231, 6}}}, + {Country: "Malaysia", Region: "Kuala Lumpur", City: "Kuala Lumpur", Hostname: "my2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{103, 28, 90, 32}, {103, 55, 10, 133}}}, + {Country: "Malaysia", Region: "Kuala Lumpur", City: "Kuala Lumpur", Hostname: "my2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{103, 55, 10, 4}, {103, 55, 10, 134}}}, + {Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "nl2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 73, 253}}}, + {Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "nl2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 73, 172}, {5, 254, 73, 203}}}, + {Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "vlap-th2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 37, 6, 4}}}, + {Country: "Netherlands", Region: "North Holland", City: "Amsterdam", Hostname: "vlap-th2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 37, 6, 4}}}, + {Country: "Norway", Region: "Oslo", City: "Oslo", Hostname: "vleu-no2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{82, 102, 22, 212}}}, + {Country: "Norway", Region: "Oslo", City: "Oslo", Hostname: "vleu-no2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{82, 102, 22, 212}}}, + {Country: "Poland", Region: "Mazovia", City: "Warsaw", Hostname: "pl2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 253, 206, 251}}}, + {Country: "Portugal", Region: "Lisbon", City: "Lisbon", Hostname: "Pt2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 154, 174, 3}}}, + {Country: "Russian Federation", Region: "St.-Petersburg", City: "Saint Petersburg", Hostname: "ru2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{94, 242, 54, 23}, {206, 123, 139, 4}}}, + {Country: "Russian Federation", Region: "St.-Petersburg", City: "Saint Petersburg", Hostname: "ru2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{94, 242, 54, 23}, {206, 123, 139, 4}}}, + {Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "sg2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{37, 120, 208, 148}, {84, 247, 49, 180}}}, + {Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "sg2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{37, 120, 208, 147}, {37, 120, 208, 148}}}, + {Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "vlap-vn2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{192, 253, 249, 132}}}, + {Country: "Singapore", Region: "Singapore", City: "Singapore", Hostname: "vlap-vn2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{192, 253, 249, 132}}}, + {Country: "South Africa", Region: "Gauteng", City: "Johannesburg", Hostname: "za2-ovpn.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{102, 165, 3, 34}}}, + {Country: "Sweden", Region: "Stockholm", City: "Stockholm", Hostname: "se2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 12, 220, 123}}}, + {Country: "Sweden", Region: "Stockholm", City: "Stockholm", Hostname: "se2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{86, 106, 103, 181}, {86, 106, 103, 185}}}, + {Country: "Switzerland", Region: "Zurich", City: "Zürich", Hostname: "ch2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 12, 222, 98}, {45, 12, 222, 99}}}, + {Country: "Switzerland", Region: "Zurich", City: "Zürich", Hostname: "ch2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 12, 222, 100}, {45, 12, 222, 101}, {45, 12, 222, 104}, {45, 12, 222, 107}}}, + {Country: "United Kingdom", Region: "England", City: "London", Hostname: "ukg2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 74, 0, 4}}}, + {Country: "United Kingdom", Region: "England", City: "London", Hostname: "ukg2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{193, 9, 113, 70}}}, + {Country: "United Kingdom", Region: "England", City: "London", Hostname: "ukl2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{45, 74, 0, 4}}}, + {Country: "United Kingdom", Region: "England", City: "London", Hostname: "ukl2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{89, 238, 165, 146}, {193, 9, 113, 70}}}, + {Country: "United Kingdom", Region: "England", City: "Manchester", Hostname: "ukm2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{188, 72, 89, 4}}}, + {Country: "United States", Region: "California", City: "Los Angeles", Hostname: "usla2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{89, 45, 4, 2}}}, + {Country: "United States", Region: "California", City: "Los Angeles", Hostname: "vlus-mx2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 243, 243, 131}}}, + {Country: "United States", Region: "California", City: "Los Angeles", Hostname: "vlus-mx2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 243, 243, 131}}}, + {Country: "United States", Region: "California", City: "Milpitas", Hostname: "usphx2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 166, 4}, {172, 94, 72, 4}}}, + {Country: "United States", Region: "California", City: "Milpitas", Hostname: "ussf2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{141, 101, 166, 4}}}, + {Country: "United States", Region: "California", City: "Milpitas", Hostname: "ussf2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{141, 101, 166, 4}}}, + {Country: "United States", Region: "Florida", City: "Miami", Hostname: "usfl2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 79, 117}}}, + {Country: "United States", Region: "Florida", City: "Miami", Hostname: "usfl2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 79, 114}, {5, 254, 79, 115}}}, + {Country: "United States", Region: "New Jersey", City: "Harrison", Hostname: "vlus-pa2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 111, 149, 4}}}, + {Country: "United States", Region: "New Jersey", City: "Harrison", Hostname: "vlus-pa2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 111, 149, 4}}}, + {Country: "United States", Region: "New York", City: "New York City", Hostname: "usnj2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 94, 72, 4}}}, + {Country: "United States", Region: "New York", City: "New York City", Hostname: "usnj2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 72, 4}}}, + {Country: "United States", Region: "New York", City: "New York City", Hostname: "usny2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{141, 101, 153, 4}}}, + {Country: "United States", Region: "New York", City: "New York City", Hostname: "usny2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 72, 4}}}, + {Country: "United States", Region: "Texas", City: "Allen", Hostname: "usga2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 94, 108, 4}}}, + {Country: "United States", Region: "Texas", City: "Allen", Hostname: "usil2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{172, 94, 108, 4}}}, + {Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ukm2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 1, 4}, {172, 94, 72, 4}, {172, 94, 123, 4}}}, + {Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ussa2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{172, 94, 1, 4}, {172, 94, 72, 4}}}, + {Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ustx2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{104, 217, 255, 178}, {208, 84, 155, 100}}}, + {Country: "United States", Region: "Texas", City: "Dallas", Hostname: "ustx2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{104, 217, 255, 179}, {104, 217, 255, 184}, {104, 217, 255, 185}}}, + {Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "us2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}}}, + {Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "usga2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}, {172, 94, 1, 4}}}, + {Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "usil2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}, {46, 243, 249, 4}, {172, 94, 72, 4}}}, + {Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "usla2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}, {141, 101, 166, 4}, {172, 94, 1, 4}}}, + {Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "usut2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}}}, + {Country: "United States", Region: "Utah", City: "Salt Lake City", Hostname: "uswdc2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{45, 74, 52, 4}, {141, 101, 166, 4}, {172, 94, 72, 4}}}, + {Country: "United States", Region: "Virginia", City: "Reston", Hostname: "usva2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{5, 254, 77, 26}, {5, 254, 77, 27}}}, + {Country: "United States", Region: "Virginia", City: "Reston", Hostname: "usva2-ovpn-udp.pointtoserver.com", TCP: false, UDP: true, IPs: []net.IP{{5, 254, 77, 26}, {5, 254, 77, 138}}}, + {Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "us2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{46, 243, 249, 4}}}, + {Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "ussa2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{46, 243, 249, 4}}}, + {Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "usut2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{46, 243, 249, 4}}}, + {Country: "United States", Region: "Washington, D.C.", City: "Washington", Hostname: "uswdc2-ovpn-tcp.pointtoserver.com", TCP: true, UDP: false, IPs: []net.IP{{46, 243, 249, 4}}}, } } diff --git a/internal/constants/servers.go b/internal/constants/servers.go index cb17645c..84fd1cb1 100644 --- a/internal/constants/servers.go +++ b/internal/constants/servers.go @@ -52,8 +52,8 @@ func GetAllServers() (allServers models.AllServers) { Servers: PIAServers(), }, Purevpn: models.PurevpnServers{ - Version: 1, - Timestamp: 1620435633, + Version: 2, + Timestamp: 1620606921, Servers: PurevpnServers(), }, Surfshark: models.SurfsharkServers{ diff --git a/internal/constants/servers_test.go b/internal/constants/servers_test.go index bb512c76..a9b083e4 100644 --- a/internal/constants/servers_test.go +++ b/internal/constants/servers_test.go @@ -82,7 +82,7 @@ func Test_versions(t *testing.T) { "Purevpn": { model: models.PurevpnServer{}, version: allServers.Purevpn.Version, - digest: "ada45379", + digest: "23f2d422", }, "Surfshark": { model: models.SurfsharkServer{}, @@ -188,7 +188,7 @@ func Test_timestamps(t *testing.T) { "Purevpn": { servers: allServers.Purevpn.Servers, timestamp: allServers.Purevpn.Timestamp, - digest: "8381d2b7", + digest: "e48aa76d", }, "Surfshark": { servers: allServers.Surfshark.Servers, diff --git a/internal/models/server.go b/internal/models/server.go index 088d21c4..7bc7a61e 100644 --- a/internal/models/server.go +++ b/internal/models/server.go @@ -133,15 +133,18 @@ func (s *ProtonvpnServer) String() string { } type PurevpnServer struct { - Country string `json:"country"` - Region string `json:"region"` - City string `json:"city"` - IPs []net.IP `json:"ips"` + Country string `json:"country"` + Region string `json:"region"` + City string `json:"city"` + Hostname string `json:"hostname"` + TCP bool `json:"tcp"` + UDP bool `json:"udp"` + IPs []net.IP `json:"ips"` } func (s *PurevpnServer) String() string { - return fmt.Sprintf("{Country: %q, Region: %q, City: %q, IPs: %s}", - s.Country, s.Region, s.City, goStringifyIPs(s.IPs)) + return fmt.Sprintf("{Country: %q, Region: %q, City: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}", + s.Country, s.Region, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs)) } type SurfsharkServer struct { diff --git a/internal/provider/purevpn.go b/internal/provider/purevpn.go index d90458d3..7aaccc85 100644 --- a/internal/provider/purevpn.go +++ b/internal/provider/purevpn.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "strconv" + "strings" "github.com/qdm12/gluetun/internal/configuration" "github.com/qdm12/gluetun/internal/constants" @@ -28,13 +29,17 @@ func newPurevpn(servers []models.PurevpnServer, timeNow timeNowFunc) *purevpn { } } -func (p *purevpn) filterServers(regions, countries, cities []string) (servers []models.PurevpnServer) { +func (p *purevpn) filterServers(regions, countries, cities, hostnames []string, + protocol string) (servers []models.PurevpnServer) { for _, server := range p.servers { switch { case filterByPossibilities(server.Region, regions), filterByPossibilities(server.Country, countries), - filterByPossibilities(server.City, cities): + filterByPossibilities(server.City, cities), + filterByPossibilities(server.Hostname, hostnames), + strings.EqualFold(protocol, "tcp") && !server.TCP, + strings.EqualFold(protocol, "udp") && !server.UDP: default: servers = append(servers, server) } @@ -58,7 +63,8 @@ func (p *purevpn) GetOpenVPNConnection(selection configuration.ServerSelection) return models.OpenVPNConnection{IP: selection.TargetIP, Port: port, Protocol: selection.Protocol}, nil } - servers := p.filterServers(selection.Regions, selection.Countries, selection.Cities) + servers := p.filterServers(selection.Regions, selection.Countries, + selection.Cities, selection.Hostnames, selection.Protocol) if len(servers) == 0 { return connection, fmt.Errorf("no server found for regions %s, countries %s and cities %s", commaJoin(selection.Regions), commaJoin(selection.Countries), commaJoin(selection.Cities)) diff --git a/internal/updater/openvpn/extract.go b/internal/updater/openvpn/extract.go index ba23e1a0..116f97d9 100644 --- a/internal/updater/openvpn/extract.go +++ b/internal/updater/openvpn/extract.go @@ -8,10 +8,35 @@ import ( ) var ( + ErrUnknownProto = errors.New("unknown protocol") ErrNoRemoteHost = errors.New("remote host not found") ErrNoRemoteIP = errors.New("remote IP not found") ) +func ExtractProto(b []byte) (tcp, udp bool, err error) { + lines := strings.Split(string(b), "\n") + const protoPrefix = "proto " + for _, line := range lines { + if !strings.HasPrefix(line, protoPrefix) { + continue + } + s := strings.TrimPrefix(line, protoPrefix) + s = strings.TrimSpace(s) + s = strings.ToLower(s) + switch s { + case "tcp": + return true, false, nil + case "udp": + return false, true, nil + default: + return false, false, fmt.Errorf("%w: %s", ErrUnknownProto, s) + } + } + + // default is UDP if unspecified in openvpn configuration + return false, true, nil +} + func ExtractHost(b []byte) (host, warning string, err error) { const ( rejectIP = true diff --git a/internal/updater/providers/purevpn/hosttoserver.go b/internal/updater/providers/purevpn/hosttoserver.go index 0ebd4c12..70c0f794 100644 --- a/internal/updater/providers/purevpn/hosttoserver.go +++ b/internal/updater/providers/purevpn/hosttoserver.go @@ -8,9 +8,18 @@ import ( type hostToServer map[string]models.PurevpnServer -func (hts hostToServer) add(host string) { - // TODO set TCP and UDP compatibility, set hostname - hts[host] = models.PurevpnServer{} +func (hts hostToServer) add(host string, tcp, udp bool) { + server, ok := hts[host] + if !ok { + server.Hostname = host + } + if tcp { + server.TCP = true + } + if udp { + server.UDP = true + } + hts[host] = server } func (hts hostToServer) toHostsSlice() (hosts []string) { diff --git a/internal/updater/providers/purevpn/locationtoserver.go b/internal/updater/providers/purevpn/locationtoserver.go deleted file mode 100644 index 4e34caf4..00000000 --- a/internal/updater/providers/purevpn/locationtoserver.go +++ /dev/null @@ -1,33 +0,0 @@ -package purevpn - -import ( - "net" - - "github.com/qdm12/gluetun/internal/models" -) - -type locationToServer map[string]models.PurevpnServer - -func locationKey(country, region, city string) string { - return country + region + city -} - -func (lts locationToServer) add(country, region, city string, ips []net.IP) { - key := locationKey(country, region, city) - server, ok := lts[key] - if !ok { - server.Country = country - server.Region = region - server.City = city - } - server.IPs = append(server.IPs, ips...) - lts[key] = server -} - -func (lts locationToServer) toServersSlice() (servers []models.PurevpnServer) { - servers = make([]models.PurevpnServer, 0, len(lts)) - for _, server := range lts { - servers = append(servers, server) - } - return servers -} diff --git a/internal/updater/providers/purevpn/servers.go b/internal/updater/providers/purevpn/servers.go index 4009f0cb..8d2c571a 100644 --- a/internal/updater/providers/purevpn/servers.go +++ b/internal/updater/providers/purevpn/servers.go @@ -38,6 +38,14 @@ func GetServers(ctx context.Context, client *http.Client, continue } + tcp, udp, err := openvpn.ExtractProto(content) + if err != nil { + // treat error as warning and go to next file + warning := err.Error() + " in " + fileName + warnings = append(warnings, warning) + continue + } + host, warning, err := openvpn.ExtractHost(content) if warning != "" { warnings = append(warnings, warning) @@ -50,7 +58,7 @@ func GetServers(ctx context.Context, client *http.Client, continue } - hts.add(host) + hts.add(host, tcp, udp) } if len(hts) < minServers { @@ -83,22 +91,12 @@ func GetServers(ctx context.Context, client *http.Client, if err != nil { return nil, warnings, err } - - // Dedup by location - lts := make(locationToServer) - for i, server := range servers { - // TODO split servers by host - ipInfo := ipsInfo[i] - lts.add(ipInfo.Country, ipInfo.Region, ipInfo.City, server.IPs) + for i := range servers { + servers[i].Country = ipsInfo[i].Country + servers[i].Region = ipsInfo[i].Region + servers[i].City = ipsInfo[i].City } - if len(servers) < minServers { - return nil, warnings, fmt.Errorf("%w: %d and expected at least %d", - ErrNotEnoughServers, len(servers), minServers) - } - - servers = lts.toServersSlice() - sortServers(servers) return servers, warnings, nil diff --git a/internal/updater/providers/purevpn/sort.go b/internal/updater/providers/purevpn/sort.go index 98e5e550..cfb3d3c1 100644 --- a/internal/updater/providers/purevpn/sort.go +++ b/internal/updater/providers/purevpn/sort.go @@ -10,6 +10,9 @@ func sortServers(servers []models.PurevpnServer) { sort.Slice(servers, func(i, j int) bool { if servers[i].Country == servers[j].Country { if servers[i].Region == servers[j].Region { + if servers[i].City == servers[j].City { + return servers[i].Hostname < servers[j].Hostname + } return servers[i].City < servers[j].City } return servers[i].Region < servers[j].Region