diff --git a/Dockerfile b/Dockerfile index da330849..561b0b9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,7 +58,10 @@ ENV VPNSP=pia \ PORT_FORWARDING_STATUS_FILE="/tmp/gluetun/forwarded_port" \ # Mullvad and PureVPN only COUNTRY= \ + # Mullvad, PureVPN, Windscribe only CITY= \ + # Windscribe only + HOSTNAME= \ # Mullvad only ISP= \ OWNED=no \ diff --git a/README.md b/README.md index 4c78a382..4d5772d9 100644 --- a/README.md +++ b/README.md @@ -134,13 +134,15 @@ docker run --rm --network=container:gluetun alpine:3.12 wget -qO- https://ipinfo For **port forwarding**, obtain a port from [here](https://mullvad.net/en/account/#/ports) and add it to `FIREWALL_VPN_INPUT_PORTS` -- Windscribe +- Windscribe (see [this](https://github.com/qdm12/gluetun/blob/master/internal/constants/windscribe.go#L43) for the choices of regions, cities and hostnames) | Variable | Default | Choices | Description | | --- | --- | --- | --- | | 🏁 `USER` | | | Your username | | 🏁 `PASSWORD` | | | Your password | - | `REGION` | | One of the [Windscribe regions](https://windscribe.com/status) | VPN server region | + | `REGION` | | | Comma separated list of regions to choose the VPN server | + | `CITY` | | | Comma separated list of cities to choose the VPN server | + | `HOSTNAME` | | | Comma separated list of hostnames to choose the VPN server | | `PORT` | | One from the [this list of ports](https://windscribe.com/getconfig/openvpn) | Custom VPN port to use | - Surfshark diff --git a/internal/constants/servers.go b/internal/constants/servers.go index 656ad991..c2c71cf5 100644 --- a/internal/constants/servers.go +++ b/internal/constants/servers.go @@ -47,8 +47,8 @@ func GetAllServers() (allServers models.AllServers) { Servers: VyprvpnServers(), }, Windscribe: models.WindscribeServers{ - Version: 1, - Timestamp: 1599323261, + Version: 2, + Timestamp: 1604019438, Servers: WindscribeServers(), }, } diff --git a/internal/constants/servers_test.go b/internal/constants/servers_test.go index ccc3548c..088360f5 100644 --- a/internal/constants/servers_test.go +++ b/internal/constants/servers_test.go @@ -77,7 +77,7 @@ func Test_versions(t *testing.T) { "Windscribe": { model: models.WindscribeServer{}, version: allServers.Windscribe.Version, - digest: "042bef64", + digest: "6e3ca639", }, } for name, testCase := range testCases { @@ -158,7 +158,7 @@ func Test_timestamps(t *testing.T) { "Windscribe": { servers: allServers.Windscribe.Servers, timestamp: allServers.Windscribe.Timestamp, - digest: "eacad593", + digest: "fd87502e", }, } for name, testCase := range testCases { diff --git a/internal/constants/windscribe.go b/internal/constants/windscribe.go index d4ed96b3..d5d9b242 100644 --- a/internal/constants/windscribe.go +++ b/internal/constants/windscribe.go @@ -21,79 +21,319 @@ func WindscribeRegionChoices() (choices []string) { return choices } +func WindscribeCityChoices() (choices []string) { + servers := WindscribeServers() + choices = make([]string, len(servers)) + for i := range servers { + choices[i] = servers[i].City + } + return choices +} + +func WindscribeHostnameChoices() (choices []string) { + servers := WindscribeServers() + choices = make([]string, len(servers)) + for i := range servers { + choices[i] = servers[i].Hostname + } + return choices +} + //nolint:lll func WindscribeServers() []models.WindscribeServer { return []models.WindscribeServer{ - {Region: "Albania", IPs: []net.IP{{31, 171, 152, 179}}}, - {Region: "Argentina", IPs: []net.IP{{167, 250, 6, 121}, {190, 105, 236, 19}, {190, 105, 236, 32}, {190, 105, 236, 50}}}, - {Region: "Australia", IPs: []net.IP{{45, 121, 208, 160}, {45, 121, 209, 160}, {45, 121, 210, 208}, {103, 62, 50, 208}, {103, 77, 233, 67}, {103, 77, 234, 211}, {116, 90, 72, 243}, {116, 206, 228, 67}}}, - {Region: "Austria", IPs: []net.IP{{89, 187, 168, 66}, {217, 64, 127, 11}}}, - {Region: "Azerbaijan", IPs: []net.IP{{85, 132, 61, 123}}}, - {Region: "Belgium", IPs: []net.IP{{185, 232, 21, 131}, {194, 187, 251, 147}}}, - {Region: "Bosnia", IPs: []net.IP{{185, 99, 3, 24}}}, - {Region: "Brazil", IPs: []net.IP{{177, 54, 144, 68}, {177, 67, 80, 59}, {189, 1, 172, 12}}}, - {Region: "Bulgaria", IPs: []net.IP{{185, 94, 192, 35}}}, - {Region: "Canada East", IPs: []net.IP{{23, 154, 160, 177}, {66, 70, 148, 80}, {104, 227, 235, 129}, {104, 254, 92, 11}, {104, 254, 92, 91}, {144, 168, 163, 160}, {144, 168, 163, 193}, {184, 75, 212, 91}, {192, 190, 19, 65}, {192, 190, 19, 97}, {198, 8, 85, 195}, {198, 8, 85, 210}, {199, 204, 208, 158}}}, - {Region: "Canada West", IPs: []net.IP{{104, 218, 61, 1}, {104, 218, 61, 33}, {162, 221, 207, 95}, {208, 78, 41, 1}, {208, 78, 41, 131}, {208, 78, 41, 163}}}, - {Region: "Colombia", IPs: []net.IP{{138, 121, 203, 203}, {138, 186, 141, 155}}}, - {Region: "Croatia", IPs: []net.IP{{85, 10, 56, 252}}}, - {Region: "Cyprus", IPs: []net.IP{{157, 97, 132, 43}}}, - {Region: "Czech republic", IPs: []net.IP{{185, 156, 174, 11}, {185, 246, 210, 2}}}, - {Region: "Denmark", IPs: []net.IP{{134, 90, 149, 147}, {185, 206, 224, 195}}}, - {Region: "Estonia", IPs: []net.IP{{46, 22, 211, 251}, {196, 196, 216, 131}}}, - {Region: "Fake antarctica", IPs: []net.IP{{23, 154, 160, 212}, {23, 154, 160, 222}}}, - {Region: "Finland", IPs: []net.IP{{185, 112, 82, 227}, {194, 34, 133, 82}}}, - {Region: "France", IPs: []net.IP{{45, 89, 174, 35}, {82, 102, 18, 35}, {84, 17, 42, 2}, {84, 17, 42, 34}, {185, 156, 173, 187}}}, - {Region: "Germany", IPs: []net.IP{{45, 87, 212, 51}, {89, 249, 65, 19}, {185, 130, 184, 195}, {195, 181, 170, 66}, {195, 181, 175, 98}, {217, 138, 194, 115}}}, - {Region: "Greece", IPs: []net.IP{{78, 108, 38, 155}, {185, 226, 64, 111}, {188, 123, 126, 146}}}, - {Region: "Guinea-Bissau", IPs: []net.IP{{149, 56, 10, 82}}}, - {Region: "Hong kong", IPs: []net.IP{{84, 17, 57, 114}, {103, 10, 197, 99}}}, - {Region: "Hungary", IPs: []net.IP{{185, 104, 187, 43}}}, - {Region: "Iceland", IPs: []net.IP{{82, 221, 139, 38}, {185, 165, 170, 2}}}, - {Region: "India", IPs: []net.IP{{103, 205, 140, 227}, {169, 38, 68, 188}, {169, 38, 72, 12}, {169, 38, 72, 14}}}, - {Region: "Indonesia", IPs: []net.IP{{45, 127, 134, 91}}}, - {Region: "Ireland", IPs: []net.IP{{185, 24, 232, 146}, {185, 104, 219, 2}}}, - {Region: "Israel", IPs: []net.IP{{160, 116, 0, 27}, {185, 191, 205, 139}}}, - {Region: "Italy", IPs: []net.IP{{37, 120, 135, 83}, {37, 120, 207, 19}, {84, 17, 59, 66}, {87, 101, 94, 195}, {89, 40, 182, 3}}}, - {Region: "Japan", IPs: []net.IP{{89, 187, 161, 114}, {193, 148, 16, 243}}}, - {Region: "Latvia", IPs: []net.IP{{85, 254, 72, 23}, {89, 111, 33, 220}}}, - {Region: "Lithuania", IPs: []net.IP{{85, 206, 163, 225}}}, - {Region: "Macedonia", IPs: []net.IP{{185, 225, 28, 51}}}, - {Region: "Madagascar", IPs: []net.IP{{104, 20, 26, 217}, {104, 20, 27, 217}, {172, 67, 17, 175}}}, - {Region: "Malaysia", IPs: []net.IP{{103, 106, 250, 31}, {103, 212, 69, 232}}}, - {Region: "Mexico", IPs: []net.IP{{143, 255, 57, 67}, {190, 103, 179, 211}, {190, 103, 179, 217}, {201, 131, 125, 107}}}, - {Region: "Moldova", IPs: []net.IP{{178, 175, 144, 123}}}, - {Region: "Netherlands", IPs: []net.IP{{37, 120, 192, 19}, {46, 166, 143, 98}, {72, 11, 157, 35}, {72, 11, 157, 67}, {84, 17, 46, 2}, {185, 212, 171, 131}, {185, 253, 96, 3}}}, - {Region: "New zealand", IPs: []net.IP{{103, 62, 49, 113}}}, - {Region: "Norway", IPs: []net.IP{{37, 120, 203, 67}, {185, 206, 225, 131}}}, - {Region: "Panama", IPs: []net.IP{{138, 186, 142, 203}}}, - {Region: "Peru", IPs: []net.IP{{190, 120, 229, 139}}}, - {Region: "Philippines", IPs: []net.IP{{103, 103, 0, 118}, {141, 98, 215, 211}}}, - {Region: "Poland", IPs: []net.IP{{5, 133, 11, 116}, {84, 17, 55, 98}, {185, 244, 214, 35}}}, - {Region: "Portugal", IPs: []net.IP{{94, 46, 13, 215}, {185, 15, 21, 66}}}, - {Region: "Romania", IPs: []net.IP{{89, 46, 103, 147}, {91, 207, 102, 147}}}, - {Region: "Russia", IPs: []net.IP{{94, 242, 62, 19}, {94, 242, 62, 67}, {95, 213, 193, 195}, {95, 213, 193, 227}, {185, 22, 175, 132}, {188, 124, 42, 99}, {188, 124, 42, 115}}}, - {Region: "Serbia", IPs: []net.IP{{141, 98, 103, 19}}}, - {Region: "Singapore", IPs: []net.IP{{82, 102, 25, 131}, {103, 62, 48, 224}, {156, 146, 56, 98}, {156, 146, 56, 111}, {185, 200, 117, 163}}}, - {Region: "Slovakia", IPs: []net.IP{{185, 245, 85, 3}}}, - {Region: "South Africa", IPs: []net.IP{{129, 232, 167, 211}, {165, 73, 248, 91}, {197, 242, 157, 235}}}, - {Region: "South Korea", IPs: []net.IP{{27, 255, 92, 52}, {103, 212, 223, 3}, {218, 232, 76, 179}}}, - {Region: "Spain", IPs: []net.IP{{37, 120, 142, 227}, {89, 238, 178, 43}, {185, 253, 99, 131}, {217, 138, 218, 99}}}, - {Region: "Sweden", IPs: []net.IP{{31, 13, 191, 67}, {79, 142, 76, 198}, {195, 181, 166, 129}}}, - {Region: "Switzerland", IPs: []net.IP{{31, 7, 57, 242}, {37, 120, 213, 163}, {84, 17, 53, 2}, {89, 187, 165, 98}, {185, 156, 175, 179}}}, - {Region: "Taiwan", IPs: []net.IP{{103, 4, 29, 77}, {185, 189, 160, 12}, {185, 189, 160, 27}, {185, 189, 160, 32}}}, - {Region: "Thailand", IPs: []net.IP{{27, 254, 130, 221}, {202, 129, 16, 147}, {202, 129, 16, 155}}}, - {Region: "Tunisia", IPs: []net.IP{{41, 231, 5, 23}}}, - {Region: "Turkey", IPs: []net.IP{{45, 123, 118, 156}, {45, 123, 119, 11}, {79, 98, 131, 43}, {176, 53, 113, 163}, {185, 125, 33, 227}}}, - {Region: "US Central", IPs: []net.IP{{67, 212, 238, 196}, {69, 12, 94, 67}, {104, 129, 18, 3}, {104, 129, 18, 131}, {104, 223, 92, 163}, {107, 150, 31, 3}, {107, 150, 31, 67}, {107, 150, 31, 131}, {107, 161, 86, 131}, {107, 182, 234, 240}, {161, 129, 70, 195}, {162, 222, 198, 67}, {172, 241, 26, 78}, {172, 241, 131, 129}, {198, 12, 76, 211}, {198, 54, 128, 116}, {198, 55, 125, 195}, {199, 115, 96, 83}, {204, 44, 112, 67}, {204, 44, 112, 131}, {206, 217, 139, 19}, {206, 217, 139, 195}, {206, 217, 143, 131}}}, - {Region: "US West", IPs: []net.IP{{23, 83, 130, 166}, {23, 83, 131, 187}, {23, 94, 74, 99}, {37, 120, 147, 163}, {64, 120, 2, 174}, {66, 115, 176, 3}, {82, 102, 30, 67}, {89, 187, 185, 34}, {89, 187, 187, 98}, {104, 129, 3, 67}, {104, 129, 3, 163}, {104, 129, 56, 67}, {104, 129, 56, 131}, {104, 152, 222, 33}, {167, 88, 60, 227}, {167, 88, 60, 243}, {172, 241, 214, 202}, {172, 241, 250, 131}, {172, 255, 125, 141}, {185, 236, 200, 35}, {192, 3, 20, 51}, {198, 12, 116, 195}, {198, 23, 242, 147}, {209, 58, 129, 121}, {212, 103, 49, 67}, {216, 45, 53, 131}, {217, 138, 217, 51}, {217, 138, 217, 211}}}, - {Region: "Ukraine", IPs: []net.IP{{45, 141, 156, 11}, {45, 141, 156, 50}}}, - {Region: "United Arab Emirates", IPs: []net.IP{{45, 9, 249, 43}}}, - {Region: "United Kingdom", IPs: []net.IP{{2, 58, 29, 17}, {2, 58, 29, 145}, {81, 92, 207, 69}, {84, 17, 50, 130}, {89, 44, 201, 99}, {89, 238, 135, 133}, {89, 238, 150, 229}, {185, 212, 168, 133}, {212, 102, 63, 32}, {212, 102, 63, 62}, {217, 138, 254, 51}}}, - {Region: "Vietnam", IPs: []net.IP{{103, 9, 76, 197}, {103, 9, 79, 186}, {103, 9, 79, 219}}}, - {Region: "Windflix CA", IPs: []net.IP{{104, 218, 60, 111}, {104, 254, 92, 99}}}, - {Region: "Windflix JP", IPs: []net.IP{{5, 181, 235, 67}}}, - {Region: "Windflix UK", IPs: []net.IP{{45, 9, 248, 3}, {81, 92, 200, 85}, {89, 47, 62, 83}}}, - {Region: "Windflix US", IPs: []net.IP{{38, 132, 101, 211}, {38, 132, 122, 131}, {38, 132, 122, 195}, {77, 81, 136, 99}, {185, 232, 22, 131}, {217, 138, 206, 211}}}, + {Region: "Albania", City: "Tirana", Hostname: "al-002.whiskergalaxy.com", IP: net.IP{31, 171, 152, 179}}, + {Region: "Argentina", City: "Buenos Aires", Hostname: "ar-001.whiskergalaxy.com", IP: net.IP{200, 85, 152, 110}}, + {Region: "Argentina", City: "Buenos Aires", Hostname: "ar-003.whiskergalaxy.com", IP: net.IP{167, 250, 6, 121}}, + {Region: "Argentina", City: "Buenos Aires", Hostname: "ar-004.whiskergalaxy.com", IP: net.IP{190, 105, 236, 50}}, + {Region: "Argentina", City: "Buenos Aires", Hostname: "ar-005.whiskergalaxy.com", IP: net.IP{190, 105, 236, 32}}, + {Region: "Argentina", City: "Buenos Aires", Hostname: "ar-006.whiskergalaxy.com", IP: net.IP{190, 105, 236, 19}}, + {Region: "Australia", City: "Adelaide ", Hostname: "au-011.whiskergalaxy.com", IP: net.IP{103, 108, 92, 83}}, + {Region: "Australia", City: "Adelaide", Hostname: "au-008.whiskergalaxy.com", IP: net.IP{116, 90, 72, 243}}, + {Region: "Australia", City: "Brisbane", Hostname: "au-007.whiskergalaxy.com", IP: net.IP{103, 62, 50, 208}}, + {Region: "Australia", City: "Brisbane", Hostname: "au-014.whiskergalaxy.com", IP: net.IP{43, 245, 160, 35}}, + {Region: "Australia", City: "Canberra", Hostname: "au-010.whiskergalaxy.com", IP: net.IP{116, 206, 229, 131}}, + {Region: "Australia", City: "Melbourne ", Hostname: "au-005.whiskergalaxy.com", IP: net.IP{45, 121, 209, 160}}, + {Region: "Australia", City: "Melbourne ", Hostname: "au-013.whiskergalaxy.com", IP: net.IP{116, 206, 228, 67}}, + {Region: "Australia", City: "Perth", Hostname: "au-004.whiskergalaxy.com", IP: net.IP{45, 121, 208, 160}}, + {Region: "Australia", City: "Perth", Hostname: "au-012.whiskergalaxy.com", IP: net.IP{103, 77, 234, 211}}, + {Region: "Australia", City: "Sydney", Hostname: "au-009.whiskergalaxy.com", IP: net.IP{103, 77, 233, 67}}, + {Region: "Australia", City: "Sydney", Hostname: "au-015.whiskergalaxy.com", IP: net.IP{103, 1, 213, 211}}, + {Region: "Austria", City: "Vienna", Hostname: "at-001.whiskergalaxy.com", IP: net.IP{217, 64, 127, 11}}, + {Region: "Austria", City: "Vienna", Hostname: "at-002.whiskergalaxy.com", IP: net.IP{89, 187, 168, 66}}, + {Region: "Belgium", City: "Brussels", Hostname: "be-001.whiskergalaxy.com", IP: net.IP{194, 187, 251, 147}}, + {Region: "Belgium", City: "Brussels", Hostname: "be-002.whiskergalaxy.com", IP: net.IP{185, 232, 21, 131}}, + {Region: "Brazil", City: "Sao Paulo", Hostname: "br-004.whiskergalaxy.com", IP: net.IP{177, 67, 80, 59}}, + {Region: "Brazil", City: "Sao Paulo", Hostname: "br-005.whiskergalaxy.com", IP: net.IP{177, 54, 157, 178}}, + {Region: "Brazil", City: "Sao Paulo", Hostname: "br-006.whiskergalaxy.com", IP: net.IP{177, 54, 148, 247}}, + {Region: "Bulgaria", City: "Sofia", Hostname: "bg-001.whiskergalaxy.com", IP: net.IP{185, 94, 192, 35}}, + {Region: "Canada East", City: "Halifax", Hostname: "ca-029.whiskergalaxy.com", IP: net.IP{199, 204, 208, 158}}, + {Region: "Canada East", City: "Montreal", Hostname: "ca-004.whiskergalaxy.com", IP: net.IP{66, 70, 148, 80}}, + {Region: "Canada East", City: "Montreal", Hostname: "ca-027.whiskergalaxy.com", IP: net.IP{144, 168, 163, 160}}, + {Region: "Canada East", City: "Montreal", Hostname: "ca-028.whiskergalaxy.com", IP: net.IP{144, 168, 163, 193}}, + {Region: "Canada East", City: "Montreal", Hostname: "ca-032.whiskergalaxy.com", IP: net.IP{104, 227, 235, 129}}, + {Region: "Canada East", City: "Montreal", Hostname: "ca-033.whiskergalaxy.com", IP: net.IP{198, 8, 85, 195}}, + {Region: "Canada East", City: "Montreal", Hostname: "ca-034.whiskergalaxy.com", IP: net.IP{198, 8, 85, 210}}, + {Region: "Canada East", City: "Toronto", Hostname: "ca-002.whiskergalaxy.com", IP: net.IP{104, 254, 92, 11}}, + {Region: "Canada East", City: "Toronto", Hostname: "ca-009.whiskergalaxy.com", IP: net.IP{104, 254, 92, 91}}, + {Region: "Canada East", City: "Toronto", Hostname: "ca-017.whiskergalaxy.com", IP: net.IP{184, 75, 212, 91}}, + {Region: "Canada East", City: "Toronto", Hostname: "ca-025.whiskergalaxy.com", IP: net.IP{192, 190, 19, 65}}, + {Region: "Canada East", City: "Toronto", Hostname: "ca-026.whiskergalaxy.com", IP: net.IP{192, 190, 19, 97}}, + {Region: "Canada East", City: "Toronto", Hostname: "ca-030.whiskergalaxy.com", IP: net.IP{23, 154, 160, 177}}, + {Region: "Canada West", City: "Vancouver", Hostname: "ca-west-005.whiskergalaxy.com", IP: net.IP{162, 221, 207, 95}}, + {Region: "Canada West", City: "Vancouver", Hostname: "ca-west-011.whiskergalaxy.com", IP: net.IP{104, 218, 61, 1}}, + {Region: "Canada West", City: "Vancouver", Hostname: "ca-west-012.whiskergalaxy.com", IP: net.IP{104, 218, 61, 33}}, + {Region: "Canada West", City: "Vancouver", Hostname: "ca-west-016.whiskergalaxy.com", IP: net.IP{208, 78, 41, 1}}, + {Region: "Canada West", City: "Vancouver", Hostname: "ca-west-017.whiskergalaxy.com", IP: net.IP{208, 78, 41, 131}}, + {Region: "Canada West", City: "Vancouver", Hostname: "ca-west-019.whiskergalaxy.com", IP: net.IP{208, 78, 41, 163}}, + {Region: "Colombia", City: "Bogota", Hostname: "co-001.whiskergalaxy.com", IP: net.IP{138, 121, 203, 203}}, + {Region: "Colombia", City: "Bogota", Hostname: "co-002.whiskergalaxy.com", IP: net.IP{138, 186, 141, 155}}, + {Region: "Croatia", City: "Zagreb", Hostname: "hr-002.whiskergalaxy.com", IP: net.IP{85, 10, 56, 129}}, + {Region: "Cyprus", City: "Nicosia", Hostname: "cy-001.whiskergalaxy.com", IP: net.IP{157, 97, 132, 43}}, + {Region: "Czech Republic", City: "Prague ", Hostname: "cz-002.whiskergalaxy.com", IP: net.IP{185, 246, 210, 2}}, + {Region: "Czech Republic", City: "Prague", Hostname: "cz-001.whiskergalaxy.com", IP: net.IP{185, 156, 174, 11}}, + {Region: "Denmark", City: "Copenhagen", Hostname: "dk-001.whiskergalaxy.com", IP: net.IP{185, 206, 224, 195}}, + {Region: "Denmark", City: "Copenhagen", Hostname: "dk-002.whiskergalaxy.com", IP: net.IP{134, 90, 149, 147}}, + {Region: "Estonia", City: "Tallinn", Hostname: "ee-001.whiskergalaxy.com", IP: net.IP{46, 22, 211, 251}}, + {Region: "Estonia", City: "Tallinn", Hostname: "ee-002.whiskergalaxy.com", IP: net.IP{196, 196, 216, 131}}, + {Region: "Fake Antarctica", City: "Troll", Hostname: "aq-001.whiskergalaxy.com", IP: net.IP{23, 154, 160, 212}}, + {Region: "Fake Antarctica", City: "Troll", Hostname: "aq-002.whiskergalaxy.com", IP: net.IP{23, 154, 160, 222}}, + {Region: "Finland", City: "Helsinki", Hostname: "fi-002.whiskergalaxy.com", IP: net.IP{185, 112, 82, 227}}, + {Region: "Finland", City: "Helsinki", Hostname: "fi-003.whiskergalaxy.com", IP: net.IP{194, 34, 133, 82}}, + {Region: "Finland", City: "Helsinki", Hostname: "fi-004.whiskergalaxy.com", IP: net.IP{196, 244, 192, 51}}, + {Region: "France", City: "Paris", Hostname: "fr-004.whiskergalaxy.com", IP: net.IP{185, 156, 173, 187}}, + {Region: "France", City: "Paris", Hostname: "fr-005.whiskergalaxy.com", IP: net.IP{82, 102, 18, 35}}, + {Region: "France", City: "Paris", Hostname: "fr-008.whiskergalaxy.com", IP: net.IP{84, 17, 42, 34}}, + {Region: "France", City: "Paris", Hostname: "fr-009.whiskergalaxy.com", IP: net.IP{84, 17, 42, 2}}, + {Region: "France", City: "Paris", Hostname: "fr-011.whiskergalaxy.com", IP: net.IP{45, 89, 174, 35}}, + {Region: "Germany", City: "Frankfurt", Hostname: "de-003.whiskergalaxy.com", IP: net.IP{89, 249, 65, 19}}, + {Region: "Germany", City: "Frankfurt", Hostname: "de-006.whiskergalaxy.com", IP: net.IP{185, 130, 184, 195}}, + {Region: "Germany", City: "Frankfurt", Hostname: "de-009.whiskergalaxy.com", IP: net.IP{195, 181, 170, 66}}, + {Region: "Germany", City: "Frankfurt", Hostname: "de-010.whiskergalaxy.com", IP: net.IP{195, 181, 175, 98}}, + {Region: "Germany", City: "Frankfurt", Hostname: "de-011.whiskergalaxy.com", IP: net.IP{217, 138, 194, 115}}, + {Region: "Germany", City: "Frankfurt", Hostname: "de-012.whiskergalaxy.com", IP: net.IP{45, 87, 212, 51}}, + {Region: "Greece", City: "Athens", Hostname: "gr-002.whiskergalaxy.com", IP: net.IP{78, 108, 38, 155}}, + {Region: "Greece", City: "Athens", Hostname: "gr-004.whiskergalaxy.com", IP: net.IP{185, 226, 64, 111}}, + {Region: "Greece", City: "Athens", Hostname: "gr-005.whiskergalaxy.com", IP: net.IP{188, 123, 126, 146}}, + {Region: "Hong Kong", City: "Hong Kong", Hostname: "hk-005.whiskergalaxy.com", IP: net.IP{103, 10, 197, 99}}, + {Region: "Hong Kong", City: "Hong Kong", Hostname: "hk-006.whiskergalaxy.com", IP: net.IP{84, 17, 57, 114}}, + {Region: "Hungary", City: "Budapest", Hostname: "hu-001.whiskergalaxy.com", IP: net.IP{185, 104, 187, 43}}, + {Region: "Iceland", City: "Reykjavik", Hostname: "is-001.whiskergalaxy.com", IP: net.IP{82, 221, 139, 38}}, + {Region: "Iceland", City: "Reykjavik", Hostname: "is-002.whiskergalaxy.com", IP: net.IP{185, 165, 170, 2}}, + {Region: "India", City: "Chennai", Hostname: "in-005.whiskergalaxy.com", IP: net.IP{169, 38, 68, 188}}, + {Region: "India", City: "Chennai", Hostname: "in-006.whiskergalaxy.com", IP: net.IP{169, 38, 72, 14}}, + {Region: "India", City: "Chennai", Hostname: "in-007.whiskergalaxy.com", IP: net.IP{169, 38, 72, 12}}, + {Region: "India", City: "Mumbai", Hostname: "in-009.whiskergalaxy.com", IP: net.IP{165, 231, 253, 211}}, + {Region: "India", City: "New Delhi", Hostname: "in-008.whiskergalaxy.com", IP: net.IP{103, 205, 140, 227}}, + {Region: "Indonesia", City: "Jakarta", Hostname: "id-002.whiskergalaxy.com", IP: net.IP{45, 127, 134, 91}}, + {Region: "Ireland", City: "Dublin", Hostname: "ie-001.whiskergalaxy.com", IP: net.IP{185, 24, 232, 146}}, + {Region: "Ireland", City: "Dublin", Hostname: "ie-002.whiskergalaxy.com", IP: net.IP{185, 104, 219, 2}}, + {Region: "Ireland", City: "Dublin", Hostname: "ie-003.whiskergalaxy.com", IP: net.IP{23, 92, 127, 35}}, + {Region: "Israel", City: "Ashdod", Hostname: "il-002.whiskergalaxy.com", IP: net.IP{185, 191, 205, 139}}, + {Region: "Israel", City: "Jerusalem", Hostname: "il-001.whiskergalaxy.com", IP: net.IP{160, 116, 0, 27}}, + {Region: "Italy", City: "Milan", Hostname: "it-001.whiskergalaxy.com", IP: net.IP{37, 120, 135, 83}}, + {Region: "Italy", City: "Milan", Hostname: "it-004.whiskergalaxy.com", IP: net.IP{84, 17, 59, 66}}, + {Region: "Italy", City: "Milan", Hostname: "it-005.whiskergalaxy.com", IP: net.IP{89, 40, 182, 3}}, + {Region: "Italy", City: "Rome", Hostname: "it-003.whiskergalaxy.com", IP: net.IP{87, 101, 94, 195}}, + {Region: "Italy", City: "Rome", Hostname: "it-006.whiskergalaxy.com", IP: net.IP{37, 120, 207, 19}}, + {Region: "Japan", City: "Tokyo", Hostname: "jp-004.whiskergalaxy.com", IP: net.IP{193, 148, 16, 243}}, + {Region: "Japan", City: "Tokyo", Hostname: "jp-005.whiskergalaxy.com", IP: net.IP{89, 187, 161, 114}}, + {Region: "Latvia", City: "Riga", Hostname: "lv-003.whiskergalaxy.com", IP: net.IP{85, 254, 72, 23}}, + {Region: "Latvia", City: "Riga", Hostname: "lv-004.whiskergalaxy.com", IP: net.IP{89, 111, 33, 220}}, + {Region: "Lithuania", City: "Siauliai", Hostname: "lt-003.whiskergalaxy.com", IP: net.IP{85, 206, 163, 225}}, + {Region: "Malaysia", City: "Kuala Lumpur", Hostname: "my-001.whiskergalaxy.com", IP: net.IP{103, 106, 250, 31}}, + {Region: "Malaysia", City: "Kuala Lumpur", Hostname: "my-003.whiskergalaxy.com", IP: net.IP{103, 212, 69, 232}}, + {Region: "Mexico", City: "Guadalajara", Hostname: "mx-007.whiskergalaxy.com", IP: net.IP{201, 131, 125, 107}}, + {Region: "Mexico", City: "Guadalajara", Hostname: "mx-008.whiskergalaxy.com", IP: net.IP{143, 255, 57, 67}}, + {Region: "Mexico", City: "Mexico City", Hostname: "mx-009.whiskergalaxy.com", IP: net.IP{190, 103, 179, 211}}, + {Region: "Mexico", City: "Mexico City", Hostname: "mx-010.whiskergalaxy.com", IP: net.IP{190, 103, 179, 217}}, + {Region: "Moldova", City: "Chisinau", Hostname: "md-002.whiskergalaxy.com", IP: net.IP{178, 175, 144, 123}}, + {Region: "Netherlands", City: "Amsterdam", Hostname: "nl-001.whiskergalaxy.com", IP: net.IP{46, 166, 143, 98}}, + {Region: "Netherlands", City: "Amsterdam", Hostname: "nl-005.whiskergalaxy.com", IP: net.IP{185, 212, 171, 131}}, + {Region: "Netherlands", City: "Amsterdam", Hostname: "nl-008.whiskergalaxy.com", IP: net.IP{185, 253, 96, 3}}, + {Region: "Netherlands", City: "Amsterdam", Hostname: "nl-011.whiskergalaxy.com", IP: net.IP{84, 17, 46, 2}}, + {Region: "Netherlands", City: "Amsterdam", Hostname: "nl-012.whiskergalaxy.com", IP: net.IP{37, 120, 192, 19}}, + {Region: "Netherlands", City: "Amsterdam", Hostname: "nl-013.whiskergalaxy.com", IP: net.IP{72, 11, 157, 67}}, + {Region: "Netherlands", City: "Amsterdam", Hostname: "nl-014.whiskergalaxy.com", IP: net.IP{72, 11, 157, 35}}, + {Region: "Netherlands", City: "Amsterdam", Hostname: "nl-015.whiskergalaxy.com", IP: net.IP{109, 201, 130, 2}}, + {Region: "New Zealand", City: "Auckland ", Hostname: "nz-003.whiskergalaxy.com", IP: net.IP{103, 108, 94, 163}}, + {Region: "New Zealand", City: "Auckland", Hostname: "nz-002.whiskergalaxy.com", IP: net.IP{103, 62, 49, 113}}, + {Region: "North Macedonia", City: "Skopje", Hostname: "mk-001.whiskergalaxy.com", IP: net.IP{185, 225, 28, 51}}, + {Region: "Norway", City: "Oslo", Hostname: "no-003.whiskergalaxy.com", IP: net.IP{185, 206, 225, 131}}, + {Region: "Norway", City: "Oslo", Hostname: "no-006.whiskergalaxy.com", IP: net.IP{37, 120, 203, 67}}, + {Region: "Panama", City: "Panama City", Hostname: "pa-001.whiskergalaxy.com", IP: net.IP{138, 186, 142, 203}}, + {Region: "Peru", City: "Lima", Hostname: "pe-002.whiskergalaxy.com", IP: net.IP{190, 120, 229, 139}}, + {Region: "Philippines", City: "Manila", Hostname: "ph-003.whiskergalaxy.com", IP: net.IP{141, 98, 215, 211}}, + {Region: "Philippines", City: "San Antonio", Hostname: "ph-002.whiskergalaxy.com", IP: net.IP{103, 103, 0, 118}}, + {Region: "Poland", City: "Warsaw", Hostname: "pl-002.whiskergalaxy.com", IP: net.IP{185, 244, 214, 35}}, + {Region: "Poland", City: "Warsaw", Hostname: "pl-004.whiskergalaxy.com", IP: net.IP{84, 17, 55, 98}}, + {Region: "Poland", City: "Warsaw", Hostname: "pl-005.whiskergalaxy.com", IP: net.IP{5, 133, 11, 116}}, + {Region: "Portugal", City: "Lisbon", Hostname: "pt-002.whiskergalaxy.com", IP: net.IP{94, 46, 13, 215}}, + {Region: "Portugal", City: "Lisbon", Hostname: "pt-003.whiskergalaxy.com", IP: net.IP{185, 15, 21, 66}}, + {Region: "Romania", City: "Bucharest", Hostname: "ro-006.whiskergalaxy.com", IP: net.IP{89, 46, 103, 147}}, + {Region: "Romania", City: "Bucharest", Hostname: "ro-008.whiskergalaxy.com", IP: net.IP{91, 207, 102, 147}}, + {Region: "Russia", City: "Moscow", Hostname: "ru-010.whiskergalaxy.com", IP: net.IP{95, 213, 193, 227}}, + {Region: "Russia", City: "Moscow", Hostname: "ru-011.whiskergalaxy.com", IP: net.IP{95, 213, 193, 195}}, + {Region: "Russia", City: "Saint Petersburg", Hostname: "ru-008.whiskergalaxy.com", IP: net.IP{94, 242, 62, 19}}, + {Region: "Russia", City: "Saint Petersburg", Hostname: "ru-009.whiskergalaxy.com", IP: net.IP{94, 242, 62, 67}}, + {Region: "Russia", City: "Saint Petersburg", Hostname: "ru-012.whiskergalaxy.com", IP: net.IP{188, 124, 42, 115}}, + {Region: "Russia", City: "Saint Petersburg", Hostname: "ru-013.whiskergalaxy.com", IP: net.IP{188, 124, 42, 99}}, + {Region: "Serbia", City: "Belgrade", Hostname: "rs-003.whiskergalaxy.com", IP: net.IP{141, 98, 103, 19}}, + {Region: "Singapore", City: "Singapore", Hostname: "sg-003.whiskergalaxy.com", IP: net.IP{185, 200, 117, 163}}, + {Region: "Singapore", City: "Singapore", Hostname: "sg-004.whiskergalaxy.com", IP: net.IP{82, 102, 25, 131}}, + {Region: "Singapore", City: "Singapore", Hostname: "sg-005.whiskergalaxy.com", IP: net.IP{103, 62, 48, 224}}, + {Region: "Singapore", City: "Singapore", Hostname: "sg-006.whiskergalaxy.com", IP: net.IP{156, 146, 56, 98}}, + {Region: "Singapore", City: "Singapore", Hostname: "sg-007.whiskergalaxy.com", IP: net.IP{156, 146, 56, 111}}, + {Region: "Slovakia", City: "Bratislava", Hostname: "sk-001.whiskergalaxy.com", IP: net.IP{185, 245, 85, 3}}, + {Region: "South Africa", City: "Johannesburg", Hostname: "za-001.whiskergalaxy.com", IP: net.IP{197, 242, 157, 235}}, + {Region: "South Africa", City: "Johannesburg", Hostname: "za-002.whiskergalaxy.com", IP: net.IP{129, 232, 167, 211}}, + {Region: "South Africa", City: "Johannesburg", Hostname: "za-003.whiskergalaxy.com", IP: net.IP{197, 242, 156, 53}}, + {Region: "South Africa", City: "Johannesburg", Hostname: "za-004.whiskergalaxy.com", IP: net.IP{165, 73, 248, 91}}, + {Region: "South Korea", City: "Seoul", Hostname: "kr-001.whiskergalaxy.com", IP: net.IP{103, 212, 223, 3}}, + {Region: "South Korea", City: "Seoul", Hostname: "kr-002.whiskergalaxy.com", IP: net.IP{218, 232, 76, 179}}, + {Region: "South Korea", City: "Seoul", Hostname: "kr-005.whiskergalaxy.com", IP: net.IP{45, 133, 194, 235}}, + {Region: "Spain", City: "Barcelona", Hostname: "es-004.whiskergalaxy.com", IP: net.IP{37, 120, 142, 227}}, + {Region: "Spain", City: "Madrid", Hostname: "es-002.whiskergalaxy.com", IP: net.IP{89, 238, 178, 43}}, + {Region: "Spain", City: "Madrid", Hostname: "es-003.whiskergalaxy.com", IP: net.IP{217, 138, 218, 99}}, + {Region: "Sweden", City: "Stockholm", Hostname: "se-001.whiskergalaxy.com", IP: net.IP{31, 13, 191, 67}}, + {Region: "Sweden", City: "Stockholm", Hostname: "se-002.whiskergalaxy.com", IP: net.IP{79, 142, 76, 198}}, + {Region: "Sweden", City: "Stockholm", Hostname: "se-003.whiskergalaxy.com", IP: net.IP{195, 181, 166, 129}}, + {Region: "Switzerland", City: "Zurich", Hostname: "ch-001.whiskergalaxy.com", IP: net.IP{31, 7, 57, 242}}, + {Region: "Switzerland", City: "Zurich", Hostname: "ch-003.whiskergalaxy.com", IP: net.IP{185, 156, 175, 179}}, + {Region: "Switzerland", City: "Zurich", Hostname: "ch-005.whiskergalaxy.com", IP: net.IP{89, 187, 165, 98}}, + {Region: "Switzerland", City: "Zurich", Hostname: "ch-006.whiskergalaxy.com", IP: net.IP{84, 17, 53, 2}}, + {Region: "Switzerland", City: "Zurich", Hostname: "ch-008.whiskergalaxy.com", IP: net.IP{37, 120, 213, 163}}, + {Region: "Taiwan", City: "Taipei", Hostname: "tw-008.whiskergalaxy.com", IP: net.IP{103, 4, 29, 77}}, + {Region: "Taiwan", City: "Taipei", Hostname: "tw-009.whiskergalaxy.com", IP: net.IP{185, 189, 160, 12}}, + {Region: "Taiwan", City: "Taipei", Hostname: "tw-010.whiskergalaxy.com", IP: net.IP{185, 189, 160, 27}}, + {Region: "Taiwan", City: "Taipei", Hostname: "tw-011.whiskergalaxy.com", IP: net.IP{185, 189, 160, 32}}, + {Region: "Thailand", City: "Bangkok", Hostname: "th-003.whiskergalaxy.com", IP: net.IP{27, 254, 130, 221}}, + {Region: "Thailand", City: "Bangkok", Hostname: "th-005.whiskergalaxy.com", IP: net.IP{202, 129, 16, 147}}, + {Region: "Thailand", City: "Bangkok", Hostname: "th-006.whiskergalaxy.com", IP: net.IP{202, 129, 16, 155}}, + {Region: "Tunisia", City: "Tunis", Hostname: "tn-001.whiskergalaxy.com", IP: net.IP{41, 231, 5, 23}}, + {Region: "Turkey", City: "Bursa", Hostname: "tr-001.whiskergalaxy.com", IP: net.IP{45, 123, 118, 156}}, + {Region: "Turkey", City: "Istanbul", Hostname: "tr-004.whiskergalaxy.com", IP: net.IP{45, 123, 119, 11}}, + {Region: "Turkey", City: "Istanbul", Hostname: "tr-006.whiskergalaxy.com", IP: net.IP{185, 125, 33, 227}}, + {Region: "Turkey", City: "Istanbul", Hostname: "tr-009.whiskergalaxy.com", IP: net.IP{79, 98, 131, 43}}, + {Region: "Turkey", City: "Istanbul", Hostname: "tr-011.whiskergalaxy.com", IP: net.IP{176, 53, 113, 163}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-016.whiskergalaxy.com", IP: net.IP{104, 129, 18, 3}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-020.whiskergalaxy.com", IP: net.IP{104, 129, 18, 131}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-034.whiskergalaxy.com", IP: net.IP{161, 129, 70, 195}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-046.whiskergalaxy.com", IP: net.IP{198, 12, 76, 211}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-049.whiskergalaxy.com", IP: net.IP{107, 150, 31, 3}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-050.whiskergalaxy.com", IP: net.IP{107, 150, 31, 67}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-051.whiskergalaxy.com", IP: net.IP{162, 222, 198, 67}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-054.whiskergalaxy.com", IP: net.IP{104, 223, 92, 163}}, + {Region: "US Central", City: "Atlanta", Hostname: "us-central-056.whiskergalaxy.com", IP: net.IP{206, 217, 143, 131}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-014.whiskergalaxy.com", IP: net.IP{69, 12, 94, 67}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-029.whiskergalaxy.com", IP: net.IP{198, 55, 125, 195}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-036.whiskergalaxy.com", IP: net.IP{204, 44, 112, 67}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-037.whiskergalaxy.com", IP: net.IP{204, 44, 112, 131}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-044.whiskergalaxy.com", IP: net.IP{206, 217, 139, 195}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-045.whiskergalaxy.com", IP: net.IP{172, 241, 131, 129}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-055.whiskergalaxy.com", IP: net.IP{206, 217, 139, 19}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-057.whiskergalaxy.com", IP: net.IP{172, 241, 26, 78}}, + {Region: "US Central", City: "Dallas", Hostname: "us-central-060.whiskergalaxy.com", IP: net.IP{198, 55, 126, 131}}, + {Region: "US Central", City: "Denver", Hostname: "us-central-043.whiskergalaxy.com", IP: net.IP{199, 115, 96, 83}}, + {Region: "US Central", City: "Denver", Hostname: "us-central-058.whiskergalaxy.com", IP: net.IP{198, 54, 128, 116}}, + {Region: "US Central", City: "Denver", Hostname: "us-central-062.whiskergalaxy.com", IP: net.IP{174, 128, 251, 147}}, + {Region: "US Central", City: "Kansas City", Hostname: "us-central-063.whiskergalaxy.com", IP: net.IP{38, 146, 5, 51}}, + {Region: "US Central", City: "Salt Lake City", Hostname: "us-central-047.whiskergalaxy.com", IP: net.IP{107, 182, 234, 240}}, + {Region: "US Central", City: "Salt Lake City", Hostname: "us-central-052.whiskergalaxy.com", IP: net.IP{67, 212, 238, 196}}, + {Region: "US East", City: "Boston", Hostname: "us-east-039.whiskergalaxy.com", IP: net.IP{199, 217, 104, 227}}, + {Region: "US East", City: "Boston", Hostname: "us-east-051.whiskergalaxy.com", IP: net.IP{199, 217, 105, 227}}, + {Region: "US East", City: "Buffalo", Hostname: "us-east-045.whiskergalaxy.com", IP: net.IP{104, 168, 34, 147}}, + {Region: "US East", City: "Buffalo", Hostname: "us-east-065.whiskergalaxy.com", IP: net.IP{198, 12, 64, 35}}, + {Region: "US East", City: "Charlotte", Hostname: "us-east-040.whiskergalaxy.com", IP: net.IP{67, 21, 32, 145}}, + {Region: "US East", City: "Chicago", Hostname: "us-east-015.whiskergalaxy.com", IP: net.IP{68, 235, 50, 227}}, + {Region: "US East", City: "Chicago", Hostname: "us-east-019.whiskergalaxy.com", IP: net.IP{23, 226, 141, 195}}, + {Region: "US East", City: "Chicago", Hostname: "us-east-022.whiskergalaxy.com", IP: net.IP{167, 160, 172, 3}}, + {Region: "US East", City: "Chicago", Hostname: "us-east-047.whiskergalaxy.com", IP: net.IP{23, 83, 91, 170}}, + {Region: "US East", City: "Chicago", Hostname: "us-east-053.whiskergalaxy.com", IP: net.IP{107, 150, 29, 131}}, + {Region: "US East", City: "Chicago", Hostname: "us-east-069.whiskergalaxy.com", IP: net.IP{68, 235, 35, 172}}, + {Region: "US East", City: "Chicago", Hostname: "us-east-071.whiskergalaxy.com", IP: net.IP{68, 235, 35, 12}}, + {Region: "US East", City: "Chicago", Hostname: "us-east-077.whiskergalaxy.com", IP: net.IP{68, 235, 43, 204}}, + {Region: "US East", City: "Cleveland", Hostname: "us-east-078.whiskergalaxy.com", IP: net.IP{38, 101, 74, 19}}, + {Region: "US East", City: "Columbus", Hostname: "us-east-059.whiskergalaxy.com", IP: net.IP{67, 219, 146, 67}}, + {Region: "US East", City: "Detroit", Hostname: "us-east-079.whiskergalaxy.com", IP: net.IP{104, 244, 210, 51}}, + {Region: "US East", City: "Miami", Hostname: "us-east-006.whiskergalaxy.com", IP: net.IP{173, 44, 36, 67}}, + {Region: "US East", City: "Miami", Hostname: "us-east-012.whiskergalaxy.com", IP: net.IP{45, 87, 214, 35}}, + {Region: "US East", City: "Miami", Hostname: "us-east-028.whiskergalaxy.com", IP: net.IP{104, 223, 127, 195}}, + {Region: "US East", City: "Miami", Hostname: "us-east-049.whiskergalaxy.com", IP: net.IP{23, 82, 136, 93}}, + {Region: "US East", City: "Miami", Hostname: "us-east-067.whiskergalaxy.com", IP: net.IP{86, 106, 87, 83}}, + {Region: "US East", City: "New Jersey", Hostname: "us-east-020.whiskergalaxy.com", IP: net.IP{162, 222, 195, 67}}, + {Region: "US East", City: "New Jersey", Hostname: "us-east-054.whiskergalaxy.com", IP: net.IP{167, 160, 167, 195}}, + {Region: "US East", City: "New York", Hostname: "us-east-013.whiskergalaxy.com", IP: net.IP{185, 232, 22, 195}}, + {Region: "US East", City: "New York", Hostname: "us-east-046.whiskergalaxy.com", IP: net.IP{206, 217, 129, 227}}, + {Region: "US East", City: "New York", Hostname: "us-east-050.whiskergalaxy.com", IP: net.IP{173, 208, 45, 33}}, + {Region: "US East", City: "New York", Hostname: "us-east-064.whiskergalaxy.com", IP: net.IP{206, 217, 128, 3}}, + {Region: "US East", City: "New York", Hostname: "us-east-068.whiskergalaxy.com", IP: net.IP{142, 234, 200, 176}}, + {Region: "US East", City: "New York", Hostname: "us-east-073.whiskergalaxy.com", IP: net.IP{217, 138, 255, 163}}, + {Region: "US East", City: "New York", Hostname: "us-east-074.whiskergalaxy.com", IP: net.IP{217, 138, 255, 179}}, + {Region: "US East", City: "Orlando", Hostname: "us-east-052.whiskergalaxy.com", IP: net.IP{198, 147, 22, 225}}, + {Region: "US East", City: "Philadelphia", Hostname: "us-east-060.whiskergalaxy.com", IP: net.IP{76, 72, 175, 99}}, + {Region: "US East", City: "Philadelphia", Hostname: "us-east-061.whiskergalaxy.com", IP: net.IP{156, 96, 59, 102}}, + {Region: "US East", City: "Washington DC", Hostname: "us-east-048.whiskergalaxy.com", IP: net.IP{23, 82, 8, 143}}, + {Region: "US East", City: "Washington DC", Hostname: "us-east-055.whiskergalaxy.com", IP: net.IP{23, 105, 170, 139}}, + {Region: "US East", City: "Washington DC", Hostname: "us-east-057.whiskergalaxy.com", IP: net.IP{23, 105, 170, 130}}, + {Region: "US East", City: "Washington DC", Hostname: "us-east-058.whiskergalaxy.com", IP: net.IP{23, 105, 170, 151}}, + {Region: "US West", City: "Bend", Hostname: "us-west-038.whiskergalaxy.com", IP: net.IP{104, 152, 222, 33}}, + {Region: "US West", City: "Las Vegas", Hostname: "us-west-018.whiskergalaxy.com", IP: net.IP{82, 102, 30, 67}}, + {Region: "US West", City: "Las Vegas", Hostname: "us-west-030.whiskergalaxy.com", IP: net.IP{37, 120, 147, 163}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-004.whiskergalaxy.com", IP: net.IP{185, 236, 200, 35}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-015.whiskergalaxy.com", IP: net.IP{216, 45, 53, 131}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-027.whiskergalaxy.com", IP: net.IP{212, 103, 49, 67}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-040.whiskergalaxy.com", IP: net.IP{89, 187, 185, 34}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-044.whiskergalaxy.com", IP: net.IP{192, 3, 20, 51}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-047.whiskergalaxy.com", IP: net.IP{172, 241, 214, 202}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-055.whiskergalaxy.com", IP: net.IP{104, 129, 3, 67}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-059.whiskergalaxy.com", IP: net.IP{104, 129, 3, 163}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-060.whiskergalaxy.com", IP: net.IP{217, 138, 217, 51}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-063.whiskergalaxy.com", IP: net.IP{198, 23, 242, 147}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-065.whiskergalaxy.com", IP: net.IP{217, 138, 217, 211}}, + {Region: "US West", City: "Los Angeles", Hostname: "us-west-066.whiskergalaxy.com", IP: net.IP{89, 187, 187, 98}}, + {Region: "US West", City: "Phoenix", Hostname: "us-west-046.whiskergalaxy.com", IP: net.IP{23, 83, 130, 166}}, + {Region: "US West", City: "Phoenix", Hostname: "us-west-061.whiskergalaxy.com", IP: net.IP{23, 83, 131, 187}}, + {Region: "US West", City: "San Francisco", Hostname: "us-west-048.whiskergalaxy.com", IP: net.IP{172, 241, 250, 131}}, + {Region: "US West", City: "San Francisco", Hostname: "us-west-053.whiskergalaxy.com", IP: net.IP{209, 58, 129, 121}}, + {Region: "US West", City: "San Francisco", Hostname: "us-west-054.whiskergalaxy.com", IP: net.IP{172, 255, 125, 141}}, + {Region: "US West", City: "San Jose", Hostname: "us-west-052.whiskergalaxy.com", IP: net.IP{66, 115, 176, 3}}, + {Region: "US West", City: "Santa Clara", Hostname: "us-west-050.whiskergalaxy.com", IP: net.IP{167, 88, 60, 227}}, + {Region: "US West", City: "Santa Clara", Hostname: "us-west-051.whiskergalaxy.com", IP: net.IP{167, 88, 60, 243}}, + {Region: "US West", City: "Seattle", Hostname: "us-west-043.whiskergalaxy.com", IP: net.IP{23, 94, 74, 99}}, + {Region: "US West", City: "Seattle", Hostname: "us-west-045.whiskergalaxy.com", IP: net.IP{64, 120, 2, 174}}, + {Region: "US West", City: "Seattle", Hostname: "us-west-056.whiskergalaxy.com", IP: net.IP{104, 129, 56, 67}}, + {Region: "US West", City: "Seattle", Hostname: "us-west-057.whiskergalaxy.com", IP: net.IP{104, 129, 56, 131}}, + {Region: "US West", City: "Seattle", Hostname: "us-west-062.whiskergalaxy.com", IP: net.IP{198, 12, 116, 195}}, + {Region: "Ukraine", City: "Kyiv", Hostname: "ua-006.whiskergalaxy.com", IP: net.IP{45, 141, 156, 11}}, + {Region: "Ukraine", City: "Kyiv", Hostname: "ua-007.whiskergalaxy.com", IP: net.IP{45, 141, 156, 50}}, + {Region: "United Arab Emirates", City: "Dubai", Hostname: "ae-001.whiskergalaxy.com", IP: net.IP{45, 9, 249, 43}}, + {Region: "United Kingdom", City: "Edinburgh", Hostname: "uk-026.whiskergalaxy.com", IP: net.IP{193, 36, 118, 243}}, + {Region: "United Kingdom", City: "London", Hostname: "uk-007.whiskergalaxy.com", IP: net.IP{185, 212, 168, 133}}, + {Region: "United Kingdom", City: "London", Hostname: "uk-013.whiskergalaxy.com", IP: net.IP{89, 238, 150, 229}}, + {Region: "United Kingdom", City: "London", Hostname: "uk-014.whiskergalaxy.com", IP: net.IP{2, 58, 29, 145}}, + {Region: "United Kingdom", City: "London", Hostname: "uk-015.whiskergalaxy.com", IP: net.IP{2, 58, 29, 17}}, + {Region: "United Kingdom", City: "London", Hostname: "uk-017.whiskergalaxy.com", IP: net.IP{84, 17, 50, 130}}, + {Region: "United Kingdom", City: "London", Hostname: "uk-021.whiskergalaxy.com", IP: net.IP{212, 102, 63, 32}}, + {Region: "United Kingdom", City: "London", Hostname: "uk-022.whiskergalaxy.com", IP: net.IP{212, 102, 63, 62}}, + {Region: "United Kingdom", City: "London", Hostname: "uk-024.whiskergalaxy.com", IP: net.IP{217, 138, 254, 51}}, + {Region: "United Kingdom", City: "Manchester", Hostname: "uk-008.whiskergalaxy.com", IP: net.IP{81, 92, 207, 69}}, + {Region: "United Kingdom", City: "Manchester", Hostname: "uk-010.whiskergalaxy.com", IP: net.IP{89, 238, 135, 133}}, + {Region: "United Kingdom", City: "Manchester", Hostname: "uk-025.whiskergalaxy.com", IP: net.IP{89, 44, 201, 99}}, + {Region: "Vietnam", City: "Hanoi", Hostname: "vn-001.whiskergalaxy.com", IP: net.IP{103, 9, 76, 197}}, + {Region: "Vietnam", City: "Hanoi", Hostname: "vn-002.whiskergalaxy.com", IP: net.IP{103, 9, 79, 186}}, + {Region: "Vietnam", City: "Hanoi", Hostname: "vn-003.whiskergalaxy.com", IP: net.IP{103, 9, 79, 219}}, + {Region: "WINDFLIX CA", City: "Toronto", Hostname: "wf-ca-003.whiskergalaxy.com", IP: net.IP{104, 218, 60, 111}}, + {Region: "WINDFLIX CA", City: "Toronto", Hostname: "wf-ca-004.whiskergalaxy.com", IP: net.IP{104, 254, 92, 99}}, + {Region: "WINDFLIX JP", City: "Tokyo", Hostname: "wf-jp-002.whiskergalaxy.com", IP: net.IP{5, 181, 235, 67}}, + {Region: "WINDFLIX UK", City: "London", Hostname: "wf-uk-001.whiskergalaxy.com", IP: net.IP{45, 9, 248, 3}}, + {Region: "WINDFLIX UK", City: "London", Hostname: "wf-uk-006.whiskergalaxy.com", IP: net.IP{81, 92, 200, 85}}, + {Region: "WINDFLIX UK", City: "London", Hostname: "wf-uk-007.whiskergalaxy.com", IP: net.IP{89, 47, 62, 83}}, + {Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-010.whiskergalaxy.com", IP: net.IP{38, 132, 122, 195}}, + {Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-011.whiskergalaxy.com", IP: net.IP{38, 132, 122, 131}}, + {Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-012.whiskergalaxy.com", IP: net.IP{185, 232, 22, 131}}, + {Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-013.whiskergalaxy.com", IP: net.IP{217, 138, 206, 211}}, + {Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-014.whiskergalaxy.com", IP: net.IP{77, 81, 136, 99}}, + {Region: "WINDFLIX US", City: "New York", Hostname: "wf-us-015.whiskergalaxy.com", IP: net.IP{38, 132, 101, 211}}, } } diff --git a/internal/models/selection.go b/internal/models/selection.go index d9d6c2b2..1df6ca1d 100644 --- a/internal/models/selection.go +++ b/internal/models/selection.go @@ -25,9 +25,9 @@ type ServerSelection struct { // Cyberghost Group string `json:"group"` - // Mullvad, PureVPN - Countries []string `json:"countries"` - Cities []string `json:"cities"` + Countries []string `json:"countries"` // Mullvad, PureVPN + Cities []string `json:"cities"` // Mullvad, PureVPN, Windscribe + Hostnames []string `json:"hostnames"` // Windscribe // Mullvad ISPs []string `json:"isps"` diff --git a/internal/models/server.go b/internal/models/server.go index 1f550438..8fc5abf4 100644 --- a/internal/models/server.go +++ b/internal/models/server.go @@ -52,12 +52,15 @@ func (s *MullvadServer) String() string { } type WindscribeServer struct { - Region string `json:"region"` - IPs []net.IP `json:"ips"` + Region string `json:"region"` + City string `json:"city"` + Hostname string `json:"hostname"` + IP net.IP `json:"ip"` } func (s *WindscribeServer) String() string { - return fmt.Sprintf("{Region: %q, IPs: %s}", s.Region, goStringifyIPs(s.IPs)) + return fmt.Sprintf("{Region: %q, City: %q, Hostname: %q, IP: %s}", + s.Region, s.City, s.Hostname, goStringifyIP(s.IP)) } type SurfsharkServer struct { diff --git a/internal/params/params.go b/internal/params/params.go index 0021b67f..33a1b855 100644 --- a/internal/params/params.go +++ b/internal/params/params.go @@ -73,6 +73,8 @@ type Reader interface { // Windscribe getters GetWindscribeRegions() (countries []string, err error) + GetWindscribeCities() (cities []string, err error) + GetWindscribeHostnames() (hostnames []string, err error) GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error) // Surfshark getters diff --git a/internal/params/windscribe.go b/internal/params/windscribe.go index 5c072655..db6a6e5d 100644 --- a/internal/params/windscribe.go +++ b/internal/params/windscribe.go @@ -14,7 +14,19 @@ func (r *reader) GetWindscribeRegions() (regions []string, err error) { return r.envParams.GetCSVInPossibilities("REGION", constants.WindscribeRegionChoices()) } -// GetMullvadPort obtains the port to reach the Mullvad server on from the +// GetWindscribeCities obtains the cities for the Windscribe servers from the +// environment variable CITY. +func (r *reader) GetWindscribeCities() (cities []string, err error) { + return r.envParams.GetCSVInPossibilities("CITY", constants.WindscribeCityChoices()) +} + +// GetWindscribeHostnames obtains the hostnames for the Windscribe servers from the +// environment variable HOSTNAME. +func (r *reader) GetWindscribeHostnames() (hostnames []string, err error) { + return r.envParams.GetCSVInPossibilities("HOSTNAME", constants.WindscribeHostnameChoices()) +} + +// GetWindscribePort obtains the port to reach the Windscribe server on from the // environment variable PORT. //nolint:gomnd func (r *reader) GetWindscribePort(protocol models.NetworkProtocol) (port uint16, err error) { diff --git a/internal/provider/windscribe.go b/internal/provider/windscribe.go index 78f759fa..c2a80a57 100644 --- a/internal/provider/windscribe.go +++ b/internal/provider/windscribe.go @@ -27,11 +27,13 @@ func newWindscribe(servers []models.WindscribeServer, timeNow timeNowFunc) *wind } } -func (w *windscribe) filterServers(regions []string) (servers []models.WindscribeServer) { +func (w *windscribe) filterServers(regions, cities, hostnames []string) (servers []models.WindscribeServer) { for _, server := range w.servers { switch { case - filterByPossibilities(server.Region, regions): + filterByPossibilities(server.Region, regions), + filterByPossibilities(server.City, cities), + filterByPossibilities(server.Hostname, hostnames): default: servers = append(servers, server) } @@ -57,16 +59,14 @@ func (w *windscribe) GetOpenVPNConnection(selection models.ServerSelection) (con return models.OpenVPNConnection{IP: selection.TargetIP, Port: port, Protocol: selection.Protocol}, nil } - servers := w.filterServers(selection.Regions) + servers := w.filterServers(selection.Regions, selection.Cities, selection.Hostnames) if len(servers) == 0 { return connection, fmt.Errorf("no server found for region %s", commaJoin(selection.Regions)) } - var connections []models.OpenVPNConnection + connections := make([]models.OpenVPNConnection, len(servers)) for _, server := range servers { - for _, IP := range server.IPs { - connections = append(connections, models.OpenVPNConnection{IP: IP, Port: port, Protocol: selection.Protocol}) - } + connections = append(connections, models.OpenVPNConnection{IP: server.IP, Port: port, Protocol: selection.Protocol}) } return pickRandomConnection(connections, w.randSource), nil diff --git a/internal/settings/openvpn_test.go b/internal/settings/openvpn_test.go index d5170458..7489b1cc 100644 --- a/internal/settings/openvpn_test.go +++ b/internal/settings/openvpn_test.go @@ -20,7 +20,7 @@ func Test_OpenVPN_JSON(t *testing.T) { data, err := json.Marshal(in) require.NoError(t, err) //nolint:lll - assert.Equal(t, `{"user":"","verbosity":0,"runAsRoot":true,"cipher":"","auth":"","provider":{"name":"name","serverSelection":{"networkProtocol":"","regions":null,"group":"","countries":null,"cities":null,"isps":null,"owned":false,"customPort":0,"numbers":null,"encryptionPreset":""},"extraConfig":{"encryptionPreset":"","openvpnIPv6":false},"portForwarding":{"enabled":false,"filepath":""}}}`, string(data)) + assert.Equal(t, `{"user":"","verbosity":0,"runAsRoot":true,"cipher":"","auth":"","provider":{"name":"name","serverSelection":{"networkProtocol":"","regions":null,"group":"","countries":null,"cities":null,"hostnames":null,"isps":null,"owned":false,"customPort":0,"numbers":null,"encryptionPreset":""},"extraConfig":{"encryptionPreset":"","openvpnIPv6":false},"portForwarding":{"enabled":false,"filepath":""}}}`, string(data)) var out OpenVPN err = json.Unmarshal(data, &out) require.NoError(t, err) diff --git a/internal/settings/providers.go b/internal/settings/providers.go index a79aaaea..b73ed083 100644 --- a/internal/settings/providers.go +++ b/internal/settings/providers.go @@ -118,6 +118,14 @@ func GetWindscribeSettings(paramsReader params.Reader) (settings models.Provider if err != nil { return settings, err } + settings.ServerSelection.Cities, err = paramsReader.GetWindscribeCities() + if err != nil { + return settings, err + } + settings.ServerSelection.Hostnames, err = paramsReader.GetWindscribeHostnames() + if err != nil { + return settings, err + } settings.ServerSelection.CustomPort, err = paramsReader.GetWindscribePort(settings.ServerSelection.Protocol) if err != nil { return settings, err diff --git a/internal/storage/merge.go b/internal/storage/merge.go index 3acf9d07..98307722 100644 --- a/internal/storage/merge.go +++ b/internal/storage/merge.go @@ -73,9 +73,14 @@ func (s *storage) mergeServers(hardcoded, persistent models.AllServers) (merged } merged.Windscribe = hardcoded.Windscribe if persistent.Windscribe.Timestamp > hardcoded.Windscribe.Timestamp { - s.logger.Info("Using Windscribe servers from file (%s more recent)", - getUnixTimeDifference(persistent.Windscribe.Timestamp, hardcoded.Windscribe.Timestamp)) - merged.Windscribe = persistent.Windscribe + if hardcoded.Windscribe.Version == 2 && persistent.Windscribe.Version == 1 { + s.logger.Info("Windscribe servers from file discarded because they are one version behind") + merged.Windscribe = hardcoded.Windscribe + } else { + s.logger.Info("Using Windscribe servers from file (%s more recent)", + getUnixTimeDifference(persistent.Windscribe.Timestamp, hardcoded.Windscribe.Timestamp)) + merged.Windscribe = persistent.Windscribe + } } return merged } diff --git a/internal/updater/cyberghost.go b/internal/updater/cyberghost.go index 85fa0621..f58602d9 100644 --- a/internal/updater/cyberghost.go +++ b/internal/updater/cyberghost.go @@ -101,6 +101,20 @@ func getCyberghostGroups() map[string]string { } } +func mergeCountryCodes(base, extend map[string]string) (merged map[string]string) { + merged = make(map[string]string, len(base)) + for countryCode, region := range base { + merged[countryCode] = region + } + for countryCode := range base { + delete(extend, countryCode) + } + for countryCode, region := range extend { + merged[countryCode] = region + } + return merged +} + func getCyberghostSubdomainToRegion() map[string]string { //nolint:dupl return map[string]string{ "af": "Afghanistan", diff --git a/internal/updater/windscribe.go b/internal/updater/windscribe.go index 639ad3a1..b7dba9bd 100644 --- a/internal/updater/windscribe.go +++ b/internal/updater/windscribe.go @@ -2,14 +2,19 @@ package updater import ( "context" + "encoding/json" "fmt" + "net" + "net/http" "sort" + "time" "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/golibs/network" ) func (u *updater) updateWindscribe(ctx context.Context) (err error) { - servers, err := findWindscribeServers(ctx, u.lookupIP) + servers, err := findWindscribeServers(ctx, u.client) if err != nil { return fmt.Errorf("cannot update Windscribe servers: %w", err) } @@ -21,46 +26,53 @@ func (u *updater) updateWindscribe(ctx context.Context) (err error) { return nil } -func findWindscribeServers(ctx context.Context, lookupIP lookupIPFunc) (servers []models.WindscribeServer, err error) { - allCountryCodes := getCountryCodes() - windscribeCountryCodes := getWindscribeSubdomainToRegion() - possibleCountryCodes := mergeCountryCodes(windscribeCountryCodes, allCountryCodes) - const domain = "windscribe.com" - for countryCode, region := range possibleCountryCodes { - if err := ctx.Err(); err != nil { - return nil, err +func findWindscribeServers(ctx context.Context, client network.Client) (servers []models.WindscribeServer, err error) { + const baseURL = "https://assets.windscribe.com/serverlist/mob-v2/1/" + cacheBreaker := time.Now().Unix() + url := fmt.Sprintf("%s%d", baseURL, cacheBreaker) + content, status, err := client.Get(ctx, url) + if err != nil { + return nil, err + } else if status != http.StatusOK { + return nil, fmt.Errorf(http.StatusText(status)) + } + var jsonData struct { + Data []struct { + Region string `json:"name"` + Groups []struct { + City string `json:"city"` + Nodes []struct { + Hostname string `json:"hostname"` + OpenvpnIP net.IP `json:"ip2"` + } `json:"nodes"` + } `json:"groups"` + } `json:"data"` + } + if err := json.Unmarshal(content, &jsonData); err != nil { + return nil, err + } + for _, regionBlock := range jsonData.Data { + region := regionBlock.Region + for _, group := range regionBlock.Groups { + city := group.City + for _, node := range group.Nodes { + server := models.WindscribeServer{ + Region: region, + City: city, + Hostname: node.Hostname, + IP: node.OpenvpnIP, + } + servers = append(servers, server) + } } - host := countryCode + "." + domain - const repetitions = 5 - ips, err := resolveRepeat(ctx, lookupIP, host, repetitions) - if err != nil || len(ips) == 0 { - continue - } - servers = append(servers, models.WindscribeServer{ - Region: region, - IPs: ips, - }) } sort.Slice(servers, func(i, j int) bool { - return servers[i].Region < servers[j].Region + return servers[i].Region+servers[i].City+servers[i].Hostname < + servers[j].Region+servers[j].City+servers[j].Hostname }) return servers, nil } -func mergeCountryCodes(base, extend map[string]string) (merged map[string]string) { - merged = make(map[string]string, len(base)) - for countryCode, region := range base { - merged[countryCode] = region - } - for countryCode := range base { - delete(extend, countryCode) - } - for countryCode, region := range extend { - merged[countryCode] = region - } - return merged -} - func stringifyWindscribeServers(servers []models.WindscribeServer) (s string) { s = "func WindscribeServers() []models.WindscribeServer {\n" s += " return []models.WindscribeServer{\n" @@ -71,77 +83,3 @@ func stringifyWindscribeServers(servers []models.WindscribeServer) (s string) { s += "}" return s } - -func getWindscribeSubdomainToRegion() map[string]string { - return map[string]string{ - "al": "Albania", - "ar": "Argentina", - "au": "Australia", - "at": "Austria", - "az": "Azerbaijan", - "be": "Belgium", - "ba": "Bosnia", - "br": "Brazil", - "bg": "Bulgaria", - "ca": "Canada East", - "ca-west": "Canada West", - "co": "Colombia", - "hr": "Croatia", - "cy": "Cyprus", - "cz": "Czech republic", - "dk": "Denmark", - "ee": "Estonia", - "aq": "Fake antarctica", - "fi": "Finland", - "fr": "France", - "ge": "Georgia", - "de": "Germany", - "gr": "Greece", - "hk": "Hong kong", - "hu": "Hungary", - "is": "Iceland", - "in": "India", - "id": "Indonesia", - "ie": "Ireland", - "il": "Israel", - "it": "Italy", - "jp": "Japan", - "lv": "Latvia", - "lt": "Lithuania", - "mk": "Macedonia", - "my": "Malaysia", - "mx": "Mexico", - "md": "Moldova", - "nl": "Netherlands", - "nz": "New zealand", - "no": "Norway", - "ph": "Philippines", - "pl": "Poland", - "pt": "Portugal", - "ro": "Romania", - "ru": "Russia", - "rs": "Serbia", - "sg": "Singapore", - "sk": "Slovakia", - "si": "Slovenia", - "za": "South Africa", - "kr": "South Korea", - "es": "Spain", - "se": "Sweden", - "ch": "Switzerland", - "th": "Thailand", - "tn": "Tunisia", - "tr": "Turkey", - "ua": "Ukraine", - "ae": "United Arab Emirates", - "uk": "United Kingdom", - "us-central": "US Central", - "us-east": "US East", - "us-west": "US West", - "vn": "Vietnam", - "wf-ca": "Windflix CA", - "wf-jp": "Windflix JP", - "wf-uk": "Windflix UK", - "wf-us": "Windflix US", - } -}