mirror of
https://github.com/qdm12/gluetun.git
synced 2025-12-10 10:45:38 -06:00
feat(surfshark): Wireguard support (#587)
This commit is contained in:
parent
4ace99f318
commit
5989f29035
@ -61,7 +61,7 @@ Lightweight swiss-knife-like VPN client to multiple VPN service providers
|
|||||||
- Supports: **Cyberghost**, **ExpressVPN**, **FastestVPN**, **HideMyAss**, **IPVanish**, **IVPN**, **Mullvad**, **NordVPN**, **Perfect Privacy**, **Privado**, **Private Internet Access**, **PrivateVPN**, **ProtonVPN**, **PureVPN**, **SlickVPN**, **Surfshark**, **TorGuard**, **VPNSecure.me**, **VPNUnlimited**, **Vyprvpn**, **WeVPN**, **Windscribe** servers
|
- Supports: **Cyberghost**, **ExpressVPN**, **FastestVPN**, **HideMyAss**, **IPVanish**, **IVPN**, **Mullvad**, **NordVPN**, **Perfect Privacy**, **Privado**, **Private Internet Access**, **PrivateVPN**, **ProtonVPN**, **PureVPN**, **SlickVPN**, **Surfshark**, **TorGuard**, **VPNSecure.me**, **VPNUnlimited**, **Vyprvpn**, **WeVPN**, **Windscribe** servers
|
||||||
- Supports OpenVPN for all providers listed
|
- Supports OpenVPN for all providers listed
|
||||||
- Supports Wireguard both kernelspace and userspace
|
- Supports Wireguard both kernelspace and userspace
|
||||||
- For **Mullvad**, **Ivpn** and **Windscribe**
|
- For **Mullvad**, **Ivpn**, **Surfshark** and **Windscribe**
|
||||||
- For **Torguard**, **VPN Unlimited** and **WeVPN** using [the custom provider](https://github.com/qdm12/gluetun/wiki/Custom-provider)
|
- For **Torguard**, **VPN Unlimited** and **WeVPN** using [the custom provider](https://github.com/qdm12/gluetun/wiki/Custom-provider)
|
||||||
- For custom Wireguard configurations using [the custom provider](https://github.com/qdm12/gluetun/wiki/Custom-provider)
|
- For custom Wireguard configurations using [the custom provider](https://github.com/qdm12/gluetun/wiki/Custom-provider)
|
||||||
- More in progress, see [#134](https://github.com/qdm12/gluetun/issues/134)
|
- More in progress, see [#134](https://github.com/qdm12/gluetun/issues/134)
|
||||||
|
|||||||
@ -37,6 +37,7 @@ var (
|
|||||||
ErrWireguardEndpointIPNotSet = errors.New("endpoint IP is not set")
|
ErrWireguardEndpointIPNotSet = errors.New("endpoint IP is not set")
|
||||||
ErrWireguardEndpointPortNotAllowed = errors.New("endpoint port is not allowed")
|
ErrWireguardEndpointPortNotAllowed = errors.New("endpoint port is not allowed")
|
||||||
ErrWireguardEndpointPortNotSet = errors.New("endpoint port is not set")
|
ErrWireguardEndpointPortNotSet = errors.New("endpoint port is not set")
|
||||||
|
ErrWireguardEndpointPortSet = errors.New("endpoint port is set")
|
||||||
ErrWireguardInterfaceAddressNotSet = errors.New("interface address is not set")
|
ErrWireguardInterfaceAddressNotSet = errors.New("interface address is not set")
|
||||||
ErrWireguardInterfaceNotValid = errors.New("interface name is not valid")
|
ErrWireguardInterfaceNotValid = errors.New("interface name is not valid")
|
||||||
ErrWireguardPreSharedKeyNotSet = errors.New("pre-shared key is not set")
|
ErrWireguardPreSharedKeyNotSet = errors.New("pre-shared key is not set")
|
||||||
|
|||||||
@ -33,6 +33,7 @@ func (p *Provider) validate(vpnType string, storage Storage) (err error) {
|
|||||||
providers.Custom,
|
providers.Custom,
|
||||||
providers.Ivpn,
|
providers.Ivpn,
|
||||||
providers.Mullvad,
|
providers.Mullvad,
|
||||||
|
providers.Surfshark,
|
||||||
providers.Windscribe,
|
providers.Windscribe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,7 @@ func (w Wireguard) validate(vpnProvider string) (err error) {
|
|||||||
providers.Custom,
|
providers.Custom,
|
||||||
providers.Ivpn,
|
providers.Ivpn,
|
||||||
providers.Mullvad,
|
providers.Mullvad,
|
||||||
|
providers.Surfshark,
|
||||||
providers.Windscribe,
|
providers.Windscribe,
|
||||||
) {
|
) {
|
||||||
// do not validate for VPN provider not supporting Wireguard
|
// do not validate for VPN provider not supporting Wireguard
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type WireguardSelection struct {
|
|||||||
// in the internal state.
|
// in the internal state.
|
||||||
EndpointIP net.IP
|
EndpointIP net.IP
|
||||||
// EndpointPort is a the server port to use for the VPN server.
|
// EndpointPort is a the server port to use for the VPN server.
|
||||||
// It is optional for VPN providers IVPN, Mullvad
|
// It is optional for VPN providers IVPN, Mullvad, Surfshark
|
||||||
// and Windscribe, and compulsory for the others.
|
// and Windscribe, and compulsory for the others.
|
||||||
// When optional, it can be set to 0 to indicate not use
|
// When optional, it can be set to 0 to indicate not use
|
||||||
// a custom endpoint port. It cannot be nil in the internal
|
// a custom endpoint port. It cannot be nil in the internal
|
||||||
@ -36,7 +36,9 @@ type WireguardSelection struct {
|
|||||||
func (w WireguardSelection) validate(vpnProvider string) (err error) {
|
func (w WireguardSelection) validate(vpnProvider string) (err error) {
|
||||||
// Validate EndpointIP
|
// Validate EndpointIP
|
||||||
switch vpnProvider {
|
switch vpnProvider {
|
||||||
case providers.Ivpn, providers.Mullvad, providers.Windscribe: // endpoint IP addresses are baked in
|
case providers.Ivpn, providers.Mullvad,
|
||||||
|
providers.Surfshark, providers.Windscribe:
|
||||||
|
// endpoint IP addresses are baked in
|
||||||
case providers.Custom:
|
case providers.Custom:
|
||||||
if len(w.EndpointIP) == 0 {
|
if len(w.EndpointIP) == 0 {
|
||||||
return ErrWireguardEndpointIPNotSet
|
return ErrWireguardEndpointIPNotSet
|
||||||
@ -51,6 +53,11 @@ func (w WireguardSelection) validate(vpnProvider string) (err error) {
|
|||||||
if *w.EndpointPort == 0 {
|
if *w.EndpointPort == 0 {
|
||||||
return ErrWireguardEndpointPortNotSet
|
return ErrWireguardEndpointPortNotSet
|
||||||
}
|
}
|
||||||
|
// EndpointPort cannot be set
|
||||||
|
case providers.Surfshark:
|
||||||
|
if *w.EndpointPort != 0 {
|
||||||
|
return ErrWireguardEndpointPortSet
|
||||||
|
}
|
||||||
case providers.Ivpn, providers.Mullvad, providers.Windscribe:
|
case providers.Ivpn, providers.Mullvad, providers.Windscribe:
|
||||||
// EndpointPort is optional and can be 0
|
// EndpointPort is optional and can be 0
|
||||||
if *w.EndpointPort == 0 {
|
if *w.EndpointPort == 0 {
|
||||||
@ -78,7 +85,9 @@ func (w WireguardSelection) validate(vpnProvider string) (err error) {
|
|||||||
|
|
||||||
// Validate PublicKey
|
// Validate PublicKey
|
||||||
switch vpnProvider {
|
switch vpnProvider {
|
||||||
case providers.Ivpn, providers.Mullvad, providers.Windscribe: // public keys are baked in
|
case providers.Ivpn, providers.Mullvad,
|
||||||
|
providers.Surfshark, providers.Windscribe:
|
||||||
|
// public keys are baked in
|
||||||
case providers.Custom:
|
case providers.Custom:
|
||||||
if w.PublicKey == "" {
|
if w.PublicKey == "" {
|
||||||
return ErrWireguardPublicKeyNotSet
|
return ErrWireguardPublicKeyNotSet
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
func (p *Provider) GetConnection(selection settings.ServerSelection) (
|
func (p *Provider) GetConnection(selection settings.ServerSelection) (
|
||||||
connection models.Connection, err error) {
|
connection models.Connection, err error) {
|
||||||
defaults := utils.NewConnectionDefaults(1443, 1194, 0) //nolint:gomnd
|
defaults := utils.NewConnectionDefaults(1443, 1194, 51820) //nolint:gomnd
|
||||||
return utils.GetConnection(p.Name(),
|
return utils.GetConnection(p.Name(),
|
||||||
p.storage, selection, defaults, p.randSource)
|
p.storage, selection, defaults, p.randSource)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,9 +10,9 @@ import (
|
|||||||
"github.com/qdm12/gluetun/internal/provider/surfshark/servers"
|
"github.com/qdm12/gluetun/internal/provider/surfshark/servers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Note: no multi-hop and some servers are missing from their API.
|
// Note: no multi-hop and some OpenVPN servers are missing from their API.
|
||||||
func addServersFromAPI(ctx context.Context, client *http.Client,
|
func addServersFromAPI(ctx context.Context, client *http.Client,
|
||||||
hts hostToServer) (err error) {
|
hts hostToServers) (err error) {
|
||||||
data, err := fetchAPI(ctx, client)
|
data, err := fetchAPI(ctx, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -21,12 +21,18 @@ func addServersFromAPI(ctx context.Context, client *http.Client,
|
|||||||
locationData := servers.LocationData()
|
locationData := servers.LocationData()
|
||||||
hostToLocation := hostToLocation(locationData)
|
hostToLocation := hostToLocation(locationData)
|
||||||
|
|
||||||
const tcp, udp = true, true
|
|
||||||
for _, serverData := range data {
|
for _, serverData := range data {
|
||||||
locationData := hostToLocation[serverData.Host] // TODO remove in v4
|
locationData := hostToLocation[serverData.Host] // TODO remove in v4
|
||||||
retroLoc := locationData.RetroLoc // empty string if the host has no retro-compatible region
|
retroLoc := locationData.RetroLoc // empty string if the host has no retro-compatible region
|
||||||
hts.add(serverData.Host, serverData.Region, serverData.Country,
|
|
||||||
|
tcp, udp := true, true // OpenVPN servers from API supports both TCP and UDP
|
||||||
|
hts.addOpenVPN(serverData.Host, serverData.Region, serverData.Country,
|
||||||
serverData.Location, retroLoc, tcp, udp)
|
serverData.Location, retroLoc, tcp, udp)
|
||||||
|
|
||||||
|
if serverData.PubKey != "" {
|
||||||
|
hts.addWireguard(serverData.Host, serverData.Region, serverData.Country,
|
||||||
|
serverData.Location, retroLoc, serverData.PubKey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -41,6 +47,7 @@ type serverData struct {
|
|||||||
Region string `json:"region"`
|
Region string `json:"region"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
Location string `json:"location"`
|
Location string `json:"location"`
|
||||||
|
PubKey string `json:"pubKey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchAPI(ctx context.Context, client *http.Client) (
|
func fetchAPI(ctx context.Context, client *http.Client) (
|
||||||
|
|||||||
@ -18,10 +18,10 @@ func Test_addServersFromAPI(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
hts hostToServer
|
hts hostToServers
|
||||||
responseStatus int
|
responseStatus int
|
||||||
responseBody io.ReadCloser
|
responseBody io.ReadCloser
|
||||||
expected hostToServer
|
expected hostToServers
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
"fetch API error": {
|
"fetch API error": {
|
||||||
@ -29,17 +29,18 @@ func Test_addServersFromAPI(t *testing.T) {
|
|||||||
err: errors.New("HTTP status code not OK: 204 No Content"),
|
err: errors.New("HTTP status code not OK: 204 No Content"),
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
hts: hostToServer{
|
hts: hostToServers{
|
||||||
"existinghost": {Hostname: "existinghost"},
|
"existinghost": []models.Server{{Hostname: "existinghost"}},
|
||||||
},
|
},
|
||||||
responseStatus: http.StatusOK,
|
responseStatus: http.StatusOK,
|
||||||
responseBody: io.NopCloser(strings.NewReader(`[
|
responseBody: io.NopCloser(strings.NewReader(`[
|
||||||
{"connectionName":"host1","region":"region1","country":"country1","location":"location1"},
|
{"connectionName":"host1","region":"region1","country":"country1","location":"location1"},
|
||||||
|
{"connectionName":"host1","region":"region1","country":"country1","location":"location1","pubkey":"pubKeyValue"},
|
||||||
{"connectionName":"host2","region":"region2","country":"country1","location":"location2"}
|
{"connectionName":"host2","region":"region2","country":"country1","location":"location2"}
|
||||||
]`)),
|
]`)),
|
||||||
expected: map[string]models.Server{
|
expected: map[string][]models.Server{
|
||||||
"existinghost": {Hostname: "existinghost"},
|
"existinghost": {{Hostname: "existinghost"}},
|
||||||
"host1": {
|
"host1": {{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
Region: "region1",
|
Region: "region1",
|
||||||
Country: "country1",
|
Country: "country1",
|
||||||
@ -47,8 +48,15 @@ func Test_addServersFromAPI(t *testing.T) {
|
|||||||
Hostname: "host1",
|
Hostname: "host1",
|
||||||
TCP: true,
|
TCP: true,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
},
|
}, {
|
||||||
"host2": {
|
VPN: vpn.Wireguard,
|
||||||
|
Region: "region1",
|
||||||
|
Country: "country1",
|
||||||
|
City: "location1",
|
||||||
|
Hostname: "host1",
|
||||||
|
WgPubKey: "pubKeyValue",
|
||||||
|
}},
|
||||||
|
"host2": {{
|
||||||
VPN: vpn.OpenVPN,
|
VPN: vpn.OpenVPN,
|
||||||
Region: "region2",
|
Region: "region2",
|
||||||
Country: "country1",
|
Country: "country1",
|
||||||
@ -57,6 +65,7 @@ func Test_addServersFromAPI(t *testing.T) {
|
|||||||
TCP: true,
|
TCP: true,
|
||||||
UDP: true,
|
UDP: true,
|
||||||
}},
|
}},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
|
|||||||
@ -7,52 +7,94 @@ import (
|
|||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type hostToServer map[string]models.Server
|
type hostToServers map[string][]models.Server
|
||||||
|
|
||||||
func (hts hostToServer) add(host, region, country, city, retroLoc string, tcp, udp bool) {
|
func (hts hostToServers) addOpenVPN(host, region, country, city,
|
||||||
server, ok := hts[host]
|
retroLoc string, tcp, udp bool) {
|
||||||
if !ok {
|
// Check for existing server for this host and OpenVPN.
|
||||||
server.VPN = vpn.OpenVPN
|
servers := hts[host]
|
||||||
server.Hostname = host
|
for i, existingServer := range servers {
|
||||||
server.Region = region
|
if existingServer.Hostname != host ||
|
||||||
server.Country = country
|
existingServer.VPN != vpn.OpenVPN {
|
||||||
server.City = city
|
continue
|
||||||
server.RetroLoc = retroLoc
|
}
|
||||||
|
|
||||||
|
// Update OpenVPN supported protocols and return
|
||||||
|
if !existingServer.TCP {
|
||||||
|
servers[i].TCP = tcp
|
||||||
|
}
|
||||||
|
if !existingServer.UDP {
|
||||||
|
servers[i].UDP = udp
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if tcp {
|
|
||||||
server.TCP = tcp
|
server := models.Server{
|
||||||
|
VPN: vpn.OpenVPN,
|
||||||
|
Region: region,
|
||||||
|
Country: country,
|
||||||
|
City: city,
|
||||||
|
RetroLoc: retroLoc,
|
||||||
|
Hostname: host,
|
||||||
|
TCP: tcp,
|
||||||
|
UDP: udp,
|
||||||
}
|
}
|
||||||
if udp {
|
hts[host] = append(servers, server)
|
||||||
server.UDP = udp
|
|
||||||
}
|
|
||||||
hts[host] = server
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) toHostsSlice() (hosts []string) {
|
func (hts hostToServers) addWireguard(host, region, country, city, retroLoc,
|
||||||
hosts = make([]string, 0, len(hts))
|
wgPubKey string) {
|
||||||
|
// Check for existing server for this host and Wireguard.
|
||||||
|
servers := hts[host]
|
||||||
|
for _, existingServer := range servers {
|
||||||
|
if existingServer.Hostname == host &&
|
||||||
|
existingServer.VPN == vpn.Wireguard {
|
||||||
|
// No update necessary for Wireguard
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server := models.Server{
|
||||||
|
VPN: vpn.Wireguard,
|
||||||
|
Region: region,
|
||||||
|
Country: country,
|
||||||
|
City: city,
|
||||||
|
RetroLoc: retroLoc,
|
||||||
|
Hostname: host,
|
||||||
|
WgPubKey: wgPubKey,
|
||||||
|
}
|
||||||
|
hts[host] = append(servers, server)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hts hostToServers) toHostsSlice() (hosts []string) {
|
||||||
|
const vpnServerTypes = 2 // OpenVPN + Wireguard
|
||||||
|
hosts = make([]string, 0, vpnServerTypes*len(hts))
|
||||||
for host := range hts {
|
for host := range hts {
|
||||||
hosts = append(hosts, host)
|
hosts = append(hosts, host)
|
||||||
}
|
}
|
||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
func (hts hostToServers) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
||||||
for host, IPs := range hostToIPs {
|
for host, IPs := range hostToIPs {
|
||||||
server := hts[host]
|
servers := hts[host]
|
||||||
server.IPs = IPs
|
for i := range servers {
|
||||||
hts[host] = server
|
servers[i].IPs = IPs
|
||||||
|
}
|
||||||
|
hts[host] = servers
|
||||||
}
|
}
|
||||||
for host, server := range hts {
|
for host, servers := range hts {
|
||||||
if len(server.IPs) == 0 {
|
if len(servers[0].IPs) == 0 {
|
||||||
delete(hts, host)
|
delete(hts, host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hts hostToServer) toServersSlice() (servers []models.Server) {
|
func (hts hostToServers) toServersSlice() (servers []models.Server) {
|
||||||
servers = make([]models.Server, 0, len(hts))
|
const vpnServerTypes = 2 // OpenVPN + Wireguard
|
||||||
for _, server := range hts {
|
servers = make([]models.Server, 0, vpnServerTypes*len(hts))
|
||||||
servers = append(servers, server)
|
for _, serversForHost := range hts {
|
||||||
|
servers = append(servers, serversForHost...)
|
||||||
}
|
}
|
||||||
return servers
|
return servers
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// getRemainingServers finds extra servers not found in the API or in the ZIP file.
|
// getRemainingServers finds extra servers not found in the API or in the ZIP file.
|
||||||
func getRemainingServers(hts hostToServer) {
|
func getRemainingServers(hts hostToServers) {
|
||||||
locationData := servers.LocationData()
|
locationData := servers.LocationData()
|
||||||
hostnameToLocationLeft := hostToLocation(locationData)
|
hostnameToLocationLeft := hostToLocation(locationData)
|
||||||
for _, hostnameDone := range hts.toHostsSlice() {
|
for _, hostnameDone := range hts.toHostsSlice() {
|
||||||
@ -13,9 +13,9 @@ func getRemainingServers(hts hostToServer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for hostname, locationData := range hostnameToLocationLeft {
|
for hostname, locationData := range hostnameToLocationLeft {
|
||||||
// we assume the server supports TCP and UDP
|
// we assume the OpenVPN server supports both TCP and UDP
|
||||||
const tcp, udp = true, true
|
const tcp, udp = true, true
|
||||||
hts.add(hostname, locationData.Region, locationData.Country,
|
hts.addOpenVPN(hostname, locationData.Region, locationData.Country,
|
||||||
locationData.City, locationData.RetroLoc, tcp, udp)
|
locationData.City, locationData.RetroLoc, tcp, udp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, err error) {
|
servers []models.Server, err error) {
|
||||||
hts := make(hostToServer)
|
hts := make(hostToServers)
|
||||||
|
|
||||||
err = addServersFromAPI(ctx, u.client, hts)
|
err = addServersFromAPI(ctx, u.client, hts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -37,14 +37,13 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(hostToIPs) < minServers {
|
|
||||||
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
|
||||||
common.ErrNotEnoughServers, len(servers), minServers)
|
|
||||||
}
|
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
|
|
||||||
|
if len(hts) < minServers {
|
||||||
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
|
common.ErrNotEnoughServers, len(hts), minServers)
|
||||||
|
}
|
||||||
|
|
||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
sort.Sort(models.SortableServers(servers))
|
sort.Sort(models.SortableServers(servers))
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func addOpenVPNServersFromZip(ctx context.Context,
|
func addOpenVPNServersFromZip(ctx context.Context,
|
||||||
unzipper common.Unzipper, hts hostToServer) (
|
unzipper common.Unzipper, hts hostToServers) (
|
||||||
warnings []string, err error) {
|
warnings []string, err error) {
|
||||||
const url = "https://my.surfshark.com/vpn/api/v1/server/configurations"
|
const url = "https://my.surfshark.com/vpn/api/v1/server/configurations"
|
||||||
contents, err := unzipper.FetchAndExtract(ctx, url)
|
contents, err := unzipper.FetchAndExtract(ctx, url)
|
||||||
@ -66,7 +66,7 @@ func addOpenVPNServersFromZip(ctx context.Context,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.add(host, data.Region, data.Country, data.City,
|
hts.addOpenVPN(host, data.Region, data.Country, data.City,
|
||||||
data.RetroLoc, tcp, udp)
|
data.RetroLoc, tcp, udp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@
|
|||||||
- gofumpt
|
- gofumpt
|
||||||
- Use netip
|
- Use netip
|
||||||
- Split servers.json
|
- Split servers.json
|
||||||
|
- Common slice of Wireguard providers in config settings
|
||||||
- DNS block lists as LFS and built in image
|
- DNS block lists as LFS and built in image
|
||||||
- Add HTTP server v3 as json rpc
|
- Add HTTP server v3 as json rpc
|
||||||
- Use `github.com/qdm12/ddns-updater/pkg/publicip`
|
- Use `github.com/qdm12/ddns-updater/pkg/publicip`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user