Skip to content

Commit

Permalink
feat(protonvpn): Wireguard support
Browse files Browse the repository at this point in the history
  • Loading branch information
qdm12 committed Aug 1, 2024
1 parent ceb6ff4 commit be0c12b
Show file tree
Hide file tree
Showing 10 changed files with 12,607 additions and 3,781 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Lightweight swiss-knife-like VPN client to multiple VPN service providers
- Supports: **AirVPN**, **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 Wireguard both kernelspace and userspace
- For **AirVPN**, **FastestVPN**, **Ivpn**, **Mullvad**, **NordVPN**, **Perfect privacy**, **Surfshark** and **Windscribe**
- For **AirVPN**, **FastestVPN**, **Ivpn**, **Mullvad**, **NordVPN**, **Perfect privacy**, **ProtonVPN**, **Surfshark** and **Windscribe**
- For **ProtonVPN**, **PureVPN**, **Torguard**, **VPN Unlimited** and **WeVPN** using [the custom provider](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/custom.md)
- For custom Wireguard configurations using [the custom provider](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/custom.md)
- More in progress, see [#134](https://github.com/qdm12/gluetun/issues/134)
Expand Down
1 change: 1 addition & 0 deletions internal/configuration/settings/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func (p *Provider) validate(vpnType string, storage Storage) (err error) {
providers.Ivpn,
providers.Mullvad,
providers.Nordvpn,
providers.Protonvpn,
providers.Surfshark,
providers.Windscribe,
}
Expand Down
1 change: 1 addition & 0 deletions internal/configuration/settings/wireguard.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func (w Wireguard) validate(vpnProvider string, ipv6Supported bool) (err error)
providers.Ivpn,
providers.Mullvad,
providers.Nordvpn,
providers.Protonvpn,
providers.Surfshark,
providers.Windscribe,
) {
Expand Down
7 changes: 4 additions & 3 deletions internal/configuration/settings/wireguardselection.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func (w WireguardSelection) validate(vpnProvider string) (err error) {
// Validate EndpointIP
switch vpnProvider {
case providers.Airvpn, providers.Fastestvpn, providers.Ivpn,
providers.Mullvad, providers.Nordvpn, providers.Surfshark,
providers.Windscribe:
providers.Mullvad, providers.Nordvpn, providers.Protonvpn,
providers.Surfshark, providers.Windscribe:
// endpoint IP addresses are baked in
case providers.Custom:
if !w.EndpointIP.IsValid() || w.EndpointIP.IsUnspecified() {
Expand All @@ -57,7 +57,8 @@ func (w WireguardSelection) validate(vpnProvider string) (err error) {
return fmt.Errorf("%w", ErrWireguardEndpointPortNotSet)
}
// EndpointPort cannot be set
case providers.Fastestvpn, providers.Surfshark, providers.Nordvpn:
case providers.Fastestvpn, providers.Nordvpn,
providers.Protonvpn, providers.Surfshark:
if *w.EndpointPort != 0 {
return fmt.Errorf("%w", ErrWireguardEndpointPortSet)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/models/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func getMarkdownHeaders(vpnProvider string) (headers []string) {
case providers.Privatevpn:
return []string{countryHeader, cityHeader, hostnameHeader}
case providers.Protonvpn:
return []string{countryHeader, regionHeader, cityHeader, hostnameHeader,
return []string{countryHeader, regionHeader, cityHeader, hostnameHeader, vpnHeader,
freeHeader, portForwardHeader, secureHeader, torHeader}
case providers.Purevpn:
return []string{countryHeader, regionHeader, cityHeader, hostnameHeader, tcpHeader, udpHeader}
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/protonvpn/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

func (p *Provider) GetConnection(selection settings.ServerSelection, ipv6Supported bool) (
connection models.Connection, err error) {
defaults := utils.NewConnectionDefaults(443, 1194, 0) //nolint:gomnd
defaults := utils.NewConnectionDefaults(443, 1194, 51820) //nolint:gomnd
return utils.GetConnection(p.Name(),
p.storage, selection, defaults, ipv6Supported, p.randSource)
}
9 changes: 5 additions & 4 deletions internal/provider/protonvpn/updater/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ type logicalServer struct {
}

type physicalServer struct {
EntryIP netip.Addr `json:"EntryIP"`
ExitIP netip.Addr `json:"ExitIP"`
Domain string `json:"Domain"`
Status uint8 `json:"Status"`
EntryIP netip.Addr `json:"EntryIP"`
ExitIP netip.Addr `json:"ExitIP"`
Domain string `json:"Domain"`
Status uint8 `json:"Status"`
X25519PublicKey string `json:"X25519PublicKey"`
}

func fetchAPI(ctx context.Context, client *http.Client) (
Expand Down
55 changes: 32 additions & 23 deletions internal/provider/protonvpn/updater/iptoserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/qdm12/gluetun/internal/models"
)

type ipToServer map[string]models.Server
type ipToServers map[string][2]models.Server // first server is OpenVPN, second is Wireguard.

type features struct {
secureCore bool
Expand All @@ -16,36 +16,45 @@ type features struct {
stream bool
}

func (its ipToServer) add(country, region, city, name, hostname string,
func (its ipToServers) add(country, region, city, name, hostname, wgPubKey string,
free bool, entryIP netip.Addr, features features) {
key := entryIP.String()

server, ok := its[key]
servers, ok := its[key]
if ok {
return
}

server.VPN = vpn.OpenVPN
server.Country = country
server.Region = region
server.City = city
server.ServerName = name
server.Hostname = hostname
server.Free = free
server.SecureCore = features.secureCore
server.Tor = features.tor
server.PortForward = features.p2p
server.Stream = features.stream
server.UDP = true
server.TCP = true
server.IPs = []netip.Addr{entryIP}
its[key] = server
baseServer := models.Server{
Country: country,
Region: region,
City: city,
ServerName: name,
Hostname: hostname,
Free: free,
SecureCore: features.secureCore,
Tor: features.tor,
PortForward: features.p2p,
Stream: features.stream,
IPs: []netip.Addr{entryIP},
}
openvpnServer := baseServer
openvpnServer.VPN = vpn.OpenVPN
openvpnServer.UDP = true
openvpnServer.TCP = true
servers[0] = openvpnServer
wireguardServer := baseServer
wireguardServer.VPN = vpn.Wireguard
wireguardServer.WgPubKey = wgPubKey
servers[1] = wireguardServer
its[key] = servers
}

func (its ipToServer) toServersSlice() (servers []models.Server) {
servers = make([]models.Server, 0, len(its))
for _, server := range its {
servers = append(servers, server)
func (its ipToServers) toServersSlice() (serversSlice []models.Server) {
const vpnProtocols = 2
serversSlice = make([]models.Server, 0, vpnProtocols*len(its))
for _, servers := range its {
serversSlice = append(serversSlice, servers[0], servers[1])
}
return servers
return serversSlice
}
8 changes: 6 additions & 2 deletions internal/provider/protonvpn/updater/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
common.ErrNotEnoughServers, count, minServers)
}

ipToServer := make(ipToServer, count)
ipToServer := make(ipToServers, count)
for _, logicalServer := range data.LogicalServers {
region := getStringValue(logicalServer.Region)
city := getStringValue(logicalServer.City)
Expand Down Expand Up @@ -65,6 +65,10 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (

hostname := physicalServer.Domain
entryIP := physicalServer.EntryIP
wgPubKey := physicalServer.X25519PublicKey
if wgPubKey == "" {
fmt.Println("wgPubKey is empty!")
}

// Note: for multi-hop use the server name or hostname
// instead of the country
Expand All @@ -74,7 +78,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
u.warner.Warn(warning)
}

ipToServer.add(country, region, city, name, hostname, free, entryIP, features)
ipToServer.add(country, region, city, name, hostname, wgPubKey, free, entryIP, features)
}
}

Expand Down
Loading

0 comments on commit be0c12b

Please sign in to comment.