18
README.md
18
README.md
@@ -68,6 +68,10 @@
|
|||||||
|
|
||||||
- Pick the [region](https://github.com/qdm12/private-internet-access-docker/wiki/Cyberghost)
|
- Pick the [region](https://github.com/qdm12/private-internet-access-docker/wiki/Cyberghost)
|
||||||
|
|
||||||
|
### Vyprvpn
|
||||||
|
|
||||||
|
- Pick the [region](https://www.vyprvpn.com/server-locations)
|
||||||
|
|
||||||
### Extra niche features
|
### Extra niche features
|
||||||
|
|
||||||
- Possibility of split horizon DNS by selecting multiple DNS over TLS providers
|
- Possibility of split horizon DNS by selecting multiple DNS over TLS providers
|
||||||
@@ -86,7 +90,9 @@
|
|||||||
[](https://windscribe.com/?affid=mh7nyafu)
|
[](https://windscribe.com/?affid=mh7nyafu)
|
||||||
|
|
||||||
- Surfshark: **username** and **password** ([sign up](https://order.surfshark.com/))
|
- Surfshark: **username** and **password** ([sign up](https://order.surfshark.com/))
|
||||||
- Cyberghost: **username**, **password** and **device client key file** ([sign up](https://www.cyberghostvpn.com/en_US/buy/cyberghost-vpn-4))
|
- Cyberghost: **username**, **password** and **device client key file**
|
||||||
|
([sign up](https://www.cyberghostvpn.com/en_US/buy/cyberghost-vpn-4))
|
||||||
|
- Vyprvpn: **username** and **password**
|
||||||
- If you have a host or router firewall, please refer [to the firewall documentation](https://github.com/qdm12/private-internet-access-docker/blob/master/doc/firewall.md)
|
- If you have a host or router firewall, please refer [to the firewall documentation](https://github.com/qdm12/private-internet-access-docker/blob/master/doc/firewall.md)
|
||||||
|
|
||||||
1. On some devices you may need to setup your tunnel kernel module on your host with `insmod /lib/modules/tun.ko` or `modprobe tun`
|
1. On some devices you may need to setup your tunnel kernel module on your host with `insmod /lib/modules/tun.ko` or `modprobe tun`
|
||||||
@@ -136,7 +142,7 @@ Want more testing? ▶ [see the Wiki](https://github.com/qdm12/private-internet-
|
|||||||
|
|
||||||
| Variable | Default | Choices | Description |
|
| Variable | Default | Choices | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| 🏁 `VPNSP` | `private internet access` | `private internet access`, `mullvad`, `windscribe`, `surfshark` | VPN Service Provider |
|
| 🏁 `VPNSP` | `private internet access` | `private internet access`, `mullvad`, `windscribe`, `surfshark`, `vyprvpn` | VPN Service Provider |
|
||||||
| `IP_STATUS_FILE` | `/ip` | Any filepath | Filepath to store the public IP address assigned |
|
| `IP_STATUS_FILE` | `/ip` | Any filepath | Filepath to store the public IP address assigned |
|
||||||
| `PROTOCOL` | `udp` | `udp` or `tcp` | Network protocol to use |
|
| `PROTOCOL` | `udp` | `udp` or `tcp` | Network protocol to use |
|
||||||
| `OPENVPN_VERBOSITY` | `1` | `0` to `6` | Openvpn verbosity level |
|
| `OPENVPN_VERBOSITY` | `1` | `0` to `6` | Openvpn verbosity level |
|
||||||
@@ -201,6 +207,14 @@ Want more testing? ▶ [see the Wiki](https://github.com/qdm12/private-internet-
|
|||||||
|
|
||||||
And use the line produced as the environment variable `CLIENT_KEY`
|
And use the line produced as the environment variable `CLIENT_KEY`
|
||||||
|
|
||||||
|
- VyprVPN
|
||||||
|
|
||||||
|
| Variable | Default | Choices | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 🏁 `USER` | | | Your username |
|
||||||
|
| 🏁 `PASSWORD` | | | Your password |
|
||||||
|
| `REGION` | `Austria` | One of the [VyprVPN regions](https://www.vyprvpn.com/server-locations) | VPN server region |
|
||||||
|
|
||||||
### DNS over TLS
|
### DNS over TLS
|
||||||
|
|
||||||
None of the following values are required.
|
None of the following values are required.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -20,8 +21,9 @@ func main() {
|
|||||||
os.Exit(_main())
|
os.Exit(_main())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find subdomains from .ovpn files contained in a .zip file
|
||||||
func _main() int {
|
func _main() int {
|
||||||
provider := flag.String("provider", "surfshark", "VPN provider to parse openvpn files for, can be 'surfshark'")
|
provider := flag.String("provider", "surfshark", "VPN provider to parse openvpn files for, can be 'surfshark' or 'vyprvpn")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
var urls []string
|
var urls []string
|
||||||
@@ -33,6 +35,11 @@ func _main() int {
|
|||||||
"https://v2uploads.zopim.io/p/2/L/p2LbwLkvfQoSdzOl6VEltzQA6StiZqrs/12500634259669c77012765139bcfe4f4c90db1e.zip",
|
"https://v2uploads.zopim.io/p/2/L/p2LbwLkvfQoSdzOl6VEltzQA6StiZqrs/12500634259669c77012765139bcfe4f4c90db1e.zip",
|
||||||
}
|
}
|
||||||
suffix = ".prod.surfshark.com"
|
suffix = ".prod.surfshark.com"
|
||||||
|
case "vyprvpn":
|
||||||
|
urls = []string{
|
||||||
|
"https://support.vyprvpn.com/hc/article_attachments/360052617332/Vypr_OpenVPN_20200320.zip",
|
||||||
|
}
|
||||||
|
suffix = ".vyprvpn.com"
|
||||||
default:
|
default:
|
||||||
fmt.Printf("Provider %q is not supported\n", *provider)
|
fmt.Printf("Provider %q is not supported\n", *provider)
|
||||||
return 1
|
return 1
|
||||||
@@ -43,31 +50,44 @@ func _main() int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
uniqueSubdomains := make(map[string]struct{})
|
uniqueSubdomainsToFilename := make(map[string]string)
|
||||||
for _, content := range contents {
|
for fileName, content := range contents {
|
||||||
subdomain, err := extractInformation(content, suffix)
|
subdomain, err := extractInformation(content, suffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return 1
|
return 1
|
||||||
} else if len(subdomain) > 0 {
|
} else if len(subdomain) > 0 {
|
||||||
uniqueSubdomains[subdomain] = struct{}{}
|
fileName = strings.TrimSuffix(fileName, ".ovpn")
|
||||||
|
fileName = strings.ReplaceAll(fileName, " - ", " ")
|
||||||
|
uniqueSubdomainsToFilename[subdomain] = fileName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subdomains := make([]string, len(uniqueSubdomains))
|
type subdomainFilename struct {
|
||||||
|
subdomain string
|
||||||
|
fileName string
|
||||||
|
}
|
||||||
|
subdomains := make([]subdomainFilename, len(uniqueSubdomainsToFilename))
|
||||||
i := 0
|
i := 0
|
||||||
for subdomain := range uniqueSubdomains {
|
for subdomain, fileName := range uniqueSubdomainsToFilename {
|
||||||
subdomains[i] = subdomain
|
subdomains[i] = subdomainFilename{
|
||||||
|
subdomain: subdomain,
|
||||||
|
fileName: fileName,
|
||||||
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
sort.Slice(subdomains, func(i, j int) bool {
|
sort.Slice(subdomains, func(i, j int) bool {
|
||||||
return subdomains[i] < subdomains[j]
|
return subdomains[i].subdomain < subdomains[j].subdomain
|
||||||
})
|
})
|
||||||
fmt.Println("Subdomains found are: ", strings.Join(subdomains, ","))
|
fmt.Println("Subdomain Filename")
|
||||||
|
for i := range subdomains {
|
||||||
|
fmt.Printf("%s %s\n", subdomains[i].subdomain, subdomains[i].fileName)
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchAndExtractFiles(urls ...string) (contents [][]byte, err error) {
|
func fetchAndExtractFiles(urls ...string) (contents map[string][]byte, err error) {
|
||||||
client := network.NewClient(10 * time.Second)
|
client := network.NewClient(10 * time.Second)
|
||||||
|
contents = make(map[string][]byte)
|
||||||
for _, url := range urls {
|
for _, url := range urls {
|
||||||
zipBytes, status, err := client.GetContent(url)
|
zipBytes, status, err := client.GetContent(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -79,24 +99,30 @@ func fetchAndExtractFiles(urls ...string) (contents [][]byte, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
contents = append(contents, newContents...)
|
for fileName, content := range newContents {
|
||||||
|
contents[fileName] = content
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return contents, nil
|
return contents, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func zipExtractAll(zipBytes []byte) (contents [][]byte, err error) {
|
func zipExtractAll(zipBytes []byte) (contents map[string][]byte, err error) {
|
||||||
r, err := zip.NewReader(bytes.NewReader(zipBytes), int64(len(zipBytes)))
|
r, err := zip.NewReader(bytes.NewReader(zipBytes), int64(len(zipBytes)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
contents = make([][]byte, len(r.File))
|
contents = map[string][]byte{}
|
||||||
for i, zf := range r.File {
|
for _, zf := range r.File {
|
||||||
|
fileName := filepath.Base(zf.Name)
|
||||||
|
if !strings.HasSuffix(fileName, ".ovpn") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
f, err := zf.Open()
|
f, err := zf.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
contents[i], err = ioutil.ReadAll(f)
|
contents[fileName], err = ioutil.ReadAll(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -122,5 +148,5 @@ func extractInformation(content []byte, suffix string) (subdomain string, err er
|
|||||||
return strings.TrimSuffix(host, suffix), nil
|
return strings.TrimSuffix(host, suffix), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("could not find remote line")
|
return "", fmt.Errorf("could not find remote line in: %s", string(content))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func main() {
|
|||||||
|
|
||||||
func _main(ctx context.Context) int {
|
func _main(ctx context.Context) int {
|
||||||
resolverAddress := flag.String("resolver", "1.1.1.1", "DNS Resolver IP address to use")
|
resolverAddress := flag.String("resolver", "1.1.1.1", "DNS Resolver IP address to use")
|
||||||
provider := flag.String("provider", "pia", "VPN provider to resolve for, 'pia', 'windscribe' or 'cyberghost'")
|
provider := flag.String("provider", "pia", "VPN provider to resolve for, 'pia', 'windscribe', 'cyberghost' or 'vyprvpn'")
|
||||||
region := flag.String("region", "all", "Comma separated list of VPN provider region names to resolve for, use 'all' to resolve all")
|
region := flag.String("region", "all", "Comma separated list of VPN provider region names to resolve for, use 'all' to resolve all")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@@ -40,6 +40,9 @@ func _main(ctx context.Context) int {
|
|||||||
case "cyberghost":
|
case "cyberghost":
|
||||||
domain = "cg-dialup.net"
|
domain = "cg-dialup.net"
|
||||||
servers = cyberghostServers()
|
servers = cyberghostServers()
|
||||||
|
case "vyprvpn":
|
||||||
|
domain = "vyprvpn.com"
|
||||||
|
servers = vyprvpnServers()
|
||||||
default:
|
default:
|
||||||
fmt.Printf("Provider %q is not supported\n", *provider)
|
fmt.Printf("Provider %q is not supported\n", *provider)
|
||||||
return 1
|
return 1
|
||||||
@@ -127,6 +130,11 @@ func formatLine(provider string, s server, ips []net.IP) string {
|
|||||||
"{Region: %q, Group: %q, IPs: []net.IP{%s}},",
|
"{Region: %q, Group: %q, IPs: []net.IP{%s}},",
|
||||||
s.region, s.group, ipString,
|
s.region, s.group, ipString,
|
||||||
)
|
)
|
||||||
|
case "vyprvpn":
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"{Region: %q, IPs: []net.IP{%s}},",
|
||||||
|
s.region, ipString,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -661,3 +669,81 @@ func cyberghostServers() []server {
|
|||||||
{subdomain: "96-1-vn", region: "Vietnam", group: "Premium TCP Asia"},
|
{subdomain: "96-1-vn", region: "Vietnam", group: "Premium TCP Asia"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func vyprvpnServers() []server {
|
||||||
|
return []server{
|
||||||
|
{subdomain: "ae1", region: "Dubai"},
|
||||||
|
{subdomain: "ar1", region: "Argentina"},
|
||||||
|
{subdomain: "at1", region: "Austria"},
|
||||||
|
{subdomain: "au1", region: "Australia Sydney"},
|
||||||
|
{subdomain: "au2", region: "Australia Melbourne"},
|
||||||
|
{subdomain: "au3", region: "Australia Perth"},
|
||||||
|
{subdomain: "be1", region: "Belgium"},
|
||||||
|
{subdomain: "bg1", region: "Bulgaria"},
|
||||||
|
{subdomain: "bh1", region: "Bahrain"},
|
||||||
|
{subdomain: "br1", region: "Brazil"},
|
||||||
|
{subdomain: "ca1", region: "Canada"},
|
||||||
|
{subdomain: "ch1", region: "Switzerland"},
|
||||||
|
{subdomain: "co1", region: "Columbia"},
|
||||||
|
{subdomain: "cr1", region: "Costa Rica"},
|
||||||
|
{subdomain: "cz1", region: "Czech Republic"},
|
||||||
|
{subdomain: "de1", region: "Germany"},
|
||||||
|
{subdomain: "dk1", region: "Denmark"},
|
||||||
|
{subdomain: "dz1", region: "Algeria"},
|
||||||
|
{subdomain: "eg1", region: "Egypt"},
|
||||||
|
{subdomain: "es1", region: "Spain"},
|
||||||
|
{subdomain: "eu1", region: "Netherlands"},
|
||||||
|
{subdomain: "fi1", region: "Finland"},
|
||||||
|
{subdomain: "fr1", region: "France"},
|
||||||
|
{subdomain: "gr1", region: "Greece"},
|
||||||
|
{subdomain: "hk1", region: "Hong Kong"},
|
||||||
|
{subdomain: "id1", region: "Indonesia"},
|
||||||
|
{subdomain: "ie1", region: "Ireland"},
|
||||||
|
{subdomain: "il1", region: "Israel"},
|
||||||
|
{subdomain: "in1", region: "India"},
|
||||||
|
{subdomain: "is1", region: "Iceland"},
|
||||||
|
{subdomain: "it1", region: "Italy"},
|
||||||
|
{subdomain: "jp1", region: "Japan"},
|
||||||
|
{subdomain: "kr1", region: "South Korea"},
|
||||||
|
{subdomain: "li1", region: "Liechtenstein"},
|
||||||
|
{subdomain: "lt1", region: "Lithuania"},
|
||||||
|
{subdomain: "lu1", region: "Luxembourg"},
|
||||||
|
{subdomain: "lv1", region: "Latvia"},
|
||||||
|
{subdomain: "mh1", region: "Marshall Islands"},
|
||||||
|
{subdomain: "mo1", region: "Macao"},
|
||||||
|
{subdomain: "mv1", region: "Maldives"},
|
||||||
|
{subdomain: "mx1", region: "Mexico"},
|
||||||
|
{subdomain: "my1", region: "Malaysia"},
|
||||||
|
{subdomain: "no1", region: "Norway"},
|
||||||
|
{subdomain: "nz1", region: "New Zealand"},
|
||||||
|
{subdomain: "pa1", region: "Panama"},
|
||||||
|
{subdomain: "ph1", region: "Philippines"},
|
||||||
|
{subdomain: "pk1", region: "Pakistan"},
|
||||||
|
{subdomain: "pl1", region: "Poland"},
|
||||||
|
{subdomain: "pt1", region: "Portugal"},
|
||||||
|
{subdomain: "qa1", region: "Qatar"},
|
||||||
|
{subdomain: "ro1", region: "Romania"},
|
||||||
|
{subdomain: "ru1", region: "Russia"},
|
||||||
|
{subdomain: "sa1", region: "Saudi Arabia"},
|
||||||
|
{subdomain: "se1", region: "Sweden"},
|
||||||
|
{subdomain: "sg1", region: "Singapore"},
|
||||||
|
{subdomain: "si1", region: "Slovenia"},
|
||||||
|
{subdomain: "sk1", region: "Slovakia"},
|
||||||
|
{subdomain: "sv1", region: "El Salvador"},
|
||||||
|
{subdomain: "th1", region: "Thailand"},
|
||||||
|
{subdomain: "tr1", region: "Turkey"},
|
||||||
|
{subdomain: "tw1", region: "Taiwan"},
|
||||||
|
{subdomain: "ua1", region: "Ukraine"},
|
||||||
|
{subdomain: "uk1", region: "United Kingdom"},
|
||||||
|
{subdomain: "us1", region: "USA Los Angeles"},
|
||||||
|
{subdomain: "us2", region: "USA Washington DC"},
|
||||||
|
{subdomain: "us3", region: "USA Austin"},
|
||||||
|
{subdomain: "us4", region: "USA Miami"},
|
||||||
|
{subdomain: "us5", region: "USA New York"},
|
||||||
|
{subdomain: "us6", region: "USA Chicago"},
|
||||||
|
{subdomain: "us7", region: "USA San Francisco"},
|
||||||
|
{subdomain: "us8", region: "USA Seattle"},
|
||||||
|
{subdomain: "uy1", region: "Uruguay"},
|
||||||
|
{subdomain: "vn1", region: "Vietnam"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ const (
|
|||||||
Surfshark models.VPNProvider = "surfshark"
|
Surfshark models.VPNProvider = "surfshark"
|
||||||
// Cyberghost is a VPN provider
|
// Cyberghost is a VPN provider
|
||||||
Cyberghost models.VPNProvider = "cyberghost"
|
Cyberghost models.VPNProvider = "cyberghost"
|
||||||
|
// Vyprvpn is a VPN provider
|
||||||
|
Vyprvpn models.VPNProvider = "vyprvpn"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
98
internal/constants/vyprvpn.go
Normal file
98
internal/constants/vyprvpn.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/qdm12/private-internet-access-docker/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
VyprvpnCertificate = "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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VyprvpnRegionChoices() (choices []string) {
|
||||||
|
servers := VyprvpnServers()
|
||||||
|
choices = make([]string, len(servers))
|
||||||
|
for i := range servers {
|
||||||
|
choices[i] = servers[i].Region
|
||||||
|
}
|
||||||
|
return choices
|
||||||
|
}
|
||||||
|
|
||||||
|
func VyprvpnServers() []models.VyprvpnServer {
|
||||||
|
return []models.VyprvpnServer{
|
||||||
|
{Region: "Algeria", IPs: []net.IP{{209, 99, 75, 20}}},
|
||||||
|
{Region: "Argentina", IPs: []net.IP{{209, 99, 109, 19}}},
|
||||||
|
{Region: "Australia Melbourne", IPs: []net.IP{{209, 99, 117, 19}}},
|
||||||
|
{Region: "Australia Perth", IPs: []net.IP{{209, 99, 1, 19}}},
|
||||||
|
{Region: "Australia Sydney", IPs: []net.IP{{209, 99, 117, 18}}},
|
||||||
|
{Region: "Austria", IPs: []net.IP{{128, 90, 96, 18}}},
|
||||||
|
{Region: "Bahrain", IPs: []net.IP{{209, 99, 115, 19}}},
|
||||||
|
{Region: "Belgium", IPs: []net.IP{{128, 90, 96, 20}}},
|
||||||
|
{Region: "Brazil", IPs: []net.IP{{209, 99, 109, 20}}},
|
||||||
|
{Region: "Bulgaria", IPs: []net.IP{{128, 90, 96, 22}}},
|
||||||
|
{Region: "Canada", IPs: []net.IP{{209, 99, 21, 18}}},
|
||||||
|
{Region: "Columbia", IPs: []net.IP{{209, 99, 109, 21}}},
|
||||||
|
{Region: "Costa Rica", IPs: []net.IP{{209, 99, 109, 22}}},
|
||||||
|
{Region: "Czech Republic", IPs: []net.IP{{128, 90, 96, 24}}},
|
||||||
|
{Region: "Denmark", IPs: []net.IP{{128, 90, 96, 28}}},
|
||||||
|
{Region: "Dubai", IPs: []net.IP{{128, 90, 45, 104}}},
|
||||||
|
{Region: "Egypt", IPs: []net.IP{{128, 90, 228, 43}}},
|
||||||
|
{Region: "El Salvador", IPs: []net.IP{{209, 99, 61, 20}}},
|
||||||
|
{Region: "Finland", IPs: []net.IP{{128, 90, 96, 32}}},
|
||||||
|
{Region: "France", IPs: []net.IP{{128, 90, 96, 34}}},
|
||||||
|
{Region: "Germany", IPs: []net.IP{{128, 90, 96, 26}}},
|
||||||
|
{Region: "Greece", IPs: []net.IP{{128, 90, 228, 59}}},
|
||||||
|
{Region: "Hong Kong", IPs: []net.IP{{128, 90, 227, 18}}},
|
||||||
|
{Region: "Iceland", IPs: []net.IP{{209, 99, 22, 20}}},
|
||||||
|
{Region: "India", IPs: []net.IP{{209, 99, 115, 20}}},
|
||||||
|
{Region: "Indonesia", IPs: []net.IP{{209, 99, 1, 20}}},
|
||||||
|
{Region: "Ireland", IPs: []net.IP{{209, 99, 22, 19}}},
|
||||||
|
{Region: "Israel", IPs: []net.IP{{128, 90, 228, 20}}},
|
||||||
|
{Region: "Italy", IPs: []net.IP{{128, 90, 96, 36}}},
|
||||||
|
{Region: "Japan", IPs: []net.IP{{209, 99, 113, 18}}},
|
||||||
|
{Region: "Latvia", IPs: []net.IP{{128, 90, 96, 44}}},
|
||||||
|
{Region: "Liechtenstein", IPs: []net.IP{{128, 90, 96, 38}}},
|
||||||
|
{Region: "Lithuania", IPs: []net.IP{{128, 90, 96, 40}}},
|
||||||
|
{Region: "Luxembourg", IPs: []net.IP{{128, 90, 96, 42}}},
|
||||||
|
{Region: "Macao", IPs: []net.IP{{128, 90, 227, 36}}},
|
||||||
|
{Region: "Malaysia", IPs: []net.IP{{209, 99, 1, 21}}},
|
||||||
|
{Region: "Maldives", IPs: []net.IP{{209, 99, 1, 26}}},
|
||||||
|
{Region: "Marshall Islands", IPs: []net.IP{{209, 99, 1, 25}}},
|
||||||
|
{Region: "Mexico", IPs: []net.IP{{209, 99, 61, 19}}},
|
||||||
|
{Region: "Netherlands", IPs: []net.IP{{128, 90, 96, 16}}},
|
||||||
|
{Region: "New Zealand", IPs: []net.IP{{209, 99, 117, 20}}},
|
||||||
|
{Region: "Norway", IPs: []net.IP{{128, 90, 96, 46}}},
|
||||||
|
{Region: "Pakistan", IPs: []net.IP{{128, 90, 228, 67}}},
|
||||||
|
{Region: "Panama", IPs: []net.IP{{209, 99, 109, 23}}},
|
||||||
|
{Region: "Philippines", IPs: []net.IP{{209, 99, 1, 22}}},
|
||||||
|
{Region: "Poland", IPs: []net.IP{{128, 90, 96, 48}}},
|
||||||
|
{Region: "Portugal", IPs: []net.IP{{128, 90, 96, 50}}},
|
||||||
|
{Region: "Qatar", IPs: []net.IP{{209, 99, 115, 21}}},
|
||||||
|
{Region: "Romania", IPs: []net.IP{{128, 90, 96, 52}}},
|
||||||
|
{Region: "Russia", IPs: []net.IP{{128, 90, 96, 54}}},
|
||||||
|
{Region: "Saudi Arabia", IPs: []net.IP{{209, 99, 115, 22}}},
|
||||||
|
{Region: "Singapore", IPs: []net.IP{{209, 99, 1, 18}}},
|
||||||
|
{Region: "Slovakia", IPs: []net.IP{{128, 90, 96, 60}}},
|
||||||
|
{Region: "Slovenia", IPs: []net.IP{{128, 90, 96, 58}}},
|
||||||
|
{Region: "South Korea", IPs: []net.IP{{209, 99, 113, 19}}},
|
||||||
|
{Region: "Spain", IPs: []net.IP{{128, 90, 96, 30}}},
|
||||||
|
{Region: "Sweden", IPs: []net.IP{{128, 90, 96, 56}}},
|
||||||
|
{Region: "Switzerland", IPs: []net.IP{{209, 99, 60, 18}}},
|
||||||
|
{Region: "Taiwan", IPs: []net.IP{{128, 90, 227, 27}}},
|
||||||
|
{Region: "Thailand", IPs: []net.IP{{209, 99, 1, 23}}},
|
||||||
|
{Region: "Turkey", IPs: []net.IP{{128, 90, 96, 62}}},
|
||||||
|
{Region: "USA Austin", IPs: []net.IP{{209, 99, 61, 18}}},
|
||||||
|
{Region: "USA Chicago", IPs: []net.IP{{209, 99, 93, 18}}},
|
||||||
|
{Region: "USA Los Angeles", IPs: []net.IP{{209, 99, 67, 18}}},
|
||||||
|
{Region: "USA Miami", IPs: []net.IP{{209, 99, 109, 18}}},
|
||||||
|
{Region: "USA New York", IPs: []net.IP{{209, 99, 63, 18}}},
|
||||||
|
{Region: "USA San Francisco", IPs: []net.IP{{209, 99, 95, 18}}},
|
||||||
|
{Region: "USA Seattle", IPs: []net.IP{{209, 99, 94, 18}}},
|
||||||
|
{Region: "USA Washington DC", IPs: []net.IP{{209, 99, 62, 18}}},
|
||||||
|
{Region: "Ukraine", IPs: []net.IP{{128, 90, 96, 64}}},
|
||||||
|
{Region: "United Kingdom", IPs: []net.IP{{209, 99, 22, 18}}},
|
||||||
|
{Region: "Uruguay", IPs: []net.IP{{209, 99, 61, 21}}},
|
||||||
|
{Region: "Vietnam", IPs: []net.IP{{209, 99, 1, 24}}},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -90,6 +90,10 @@ func (p *ProviderSettings) String() string {
|
|||||||
"Group: "+p.ServerSelection.Group,
|
"Group: "+p.ServerSelection.Group,
|
||||||
"Region: "+p.ServerSelection.Region,
|
"Region: "+p.ServerSelection.Region,
|
||||||
)
|
)
|
||||||
|
case "vyprvpn":
|
||||||
|
settingsList = append(settingsList,
|
||||||
|
"Region: "+p.ServerSelection.Region,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if p.ServerSelection.TargetIP != nil {
|
if p.ServerSelection.TargetIP != nil {
|
||||||
settingsList = append(settingsList,
|
settingsList = append(settingsList,
|
||||||
|
|||||||
@@ -31,3 +31,8 @@ type CyberghostServer struct {
|
|||||||
Group string
|
Group string
|
||||||
IPs []net.IP
|
IPs []net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VyprvpnServer struct {
|
||||||
|
Region string
|
||||||
|
IPs []net.IP
|
||||||
|
}
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ type Reader interface {
|
|||||||
GetCyberghostRegion() (region string, err error)
|
GetCyberghostRegion() (region string, err error)
|
||||||
GetCyberghostClientKey() (clientKey string, err error)
|
GetCyberghostClientKey() (clientKey string, err error)
|
||||||
|
|
||||||
|
// Vyprvpn getters
|
||||||
|
GetVyprvpnRegion() (region string, err error)
|
||||||
|
|
||||||
// Shadowsocks getters
|
// Shadowsocks getters
|
||||||
GetShadowSocks() (activated bool, err error)
|
GetShadowSocks() (activated bool, err error)
|
||||||
GetShadowSocksLog() (activated bool, err error)
|
GetShadowSocksLog() (activated bool, err error)
|
||||||
@@ -117,7 +120,7 @@ func NewReader(logger logging.Logger) Reader {
|
|||||||
|
|
||||||
// GetVPNSP obtains the VPN service provider to use from the environment variable VPNSP
|
// GetVPNSP obtains the VPN service provider to use from the environment variable VPNSP
|
||||||
func (r *reader) GetVPNSP() (vpnServiceProvider models.VPNProvider, err error) {
|
func (r *reader) GetVPNSP() (vpnServiceProvider models.VPNProvider, err error) {
|
||||||
s, err := r.envParams.GetValueIfInside("VPNSP", []string{"pia", "private internet access", "mullvad", "windscribe", "surfshark", "cyberghost"})
|
s, err := r.envParams.GetValueIfInside("VPNSP", []string{"pia", "private internet access", "mullvad", "windscribe", "surfshark", "cyberghost", "vyprvpn"})
|
||||||
if s == "pia" {
|
if s == "pia" {
|
||||||
s = "private internet access"
|
s = "private internet access"
|
||||||
}
|
}
|
||||||
|
|||||||
11
internal/params/vypervpn.go
Normal file
11
internal/params/vypervpn.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package params
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetVyprvpnRegion obtains the region for the Vyprvpn server from the
|
||||||
|
// environment variable REGION
|
||||||
|
func (r *reader) GetVyprvpnRegion() (region string, err error) {
|
||||||
|
return r.envParams.GetValueIfInside("REGION", constants.VyprvpnRegionChoices())
|
||||||
|
}
|
||||||
@@ -26,6 +26,8 @@ func New(provider models.VPNProvider, client network.Client, fileManager files.F
|
|||||||
return newSurfshark(fileManager)
|
return newSurfshark(fileManager)
|
||||||
case constants.Cyberghost:
|
case constants.Cyberghost:
|
||||||
return newCyberghost(fileManager)
|
return newCyberghost(fileManager)
|
||||||
|
case constants.Vyprvpn:
|
||||||
|
return newVyprvpn(fileManager)
|
||||||
default:
|
default:
|
||||||
return nil // should never occur
|
return nil // should never occur
|
||||||
}
|
}
|
||||||
|
|||||||
113
internal/provider/vyprvpn.go
Normal file
113
internal/provider/vyprvpn.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/golibs/files"
|
||||||
|
"github.com/qdm12/private-internet-access-docker/internal/constants"
|
||||||
|
"github.com/qdm12/private-internet-access-docker/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type vyprvpn struct {
|
||||||
|
fileManager files.FileManager
|
||||||
|
lookupIP func(host string) ([]net.IP, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newVyprvpn(fileManager files.FileManager) *vyprvpn {
|
||||||
|
return &vyprvpn{fileManager, net.LookupIP}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *vyprvpn) GetOpenVPNConnections(selection models.ServerSelection) (connections []models.OpenVPNConnection, err error) {
|
||||||
|
var IPs []net.IP
|
||||||
|
for _, server := range constants.VyprvpnServers() {
|
||||||
|
if strings.EqualFold(server.Region, selection.Region) {
|
||||||
|
IPs = server.IPs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(IPs) == 0 {
|
||||||
|
return nil, fmt.Errorf("no IP found for region %q", selection.Region)
|
||||||
|
}
|
||||||
|
if selection.TargetIP != nil {
|
||||||
|
found := false
|
||||||
|
for i := range IPs {
|
||||||
|
if IPs[i].Equal(selection.TargetIP) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return nil, fmt.Errorf("target IP address %q not found in IP addresses", selection.TargetIP)
|
||||||
|
}
|
||||||
|
IPs = []net.IP{selection.TargetIP}
|
||||||
|
}
|
||||||
|
var port uint16
|
||||||
|
switch {
|
||||||
|
case selection.Protocol == constants.TCP:
|
||||||
|
return nil, fmt.Errorf("TCP protocol not supported by this VPN provider")
|
||||||
|
case selection.Protocol == constants.UDP:
|
||||||
|
port = 443
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("protocol %q is unknown", selection.Protocol)
|
||||||
|
}
|
||||||
|
for _, IP := range IPs {
|
||||||
|
connections = append(connections, models.OpenVPNConnection{IP: IP, Port: port, Protocol: selection.Protocol})
|
||||||
|
}
|
||||||
|
return connections, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *vyprvpn) BuildConf(connections []models.OpenVPNConnection, verbosity, uid, gid int, root bool, cipher, auth string, extras models.ExtraConfigOptions) (err error) {
|
||||||
|
if len(cipher) == 0 {
|
||||||
|
cipher = aes256cbc
|
||||||
|
}
|
||||||
|
if len(auth) == 0 {
|
||||||
|
auth = "SHA256"
|
||||||
|
}
|
||||||
|
lines := []string{
|
||||||
|
"client",
|
||||||
|
"dev tun",
|
||||||
|
"nobind",
|
||||||
|
"persist-key",
|
||||||
|
"remote-cert-tls server",
|
||||||
|
|
||||||
|
// Vyprvpn specific
|
||||||
|
"comp-lzo",
|
||||||
|
"keepalive 10 60",
|
||||||
|
// "verify-x509-name lu1.vyprvpn.com name",
|
||||||
|
"tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
|
||||||
|
|
||||||
|
// Added constant values
|
||||||
|
"auth-nocache",
|
||||||
|
"mute-replay-warnings",
|
||||||
|
"pull-filter ignore \"auth-token\"", // prevent auth failed loops
|
||||||
|
"auth-retry nointeract",
|
||||||
|
"remote-random",
|
||||||
|
"suppress-timestamps",
|
||||||
|
|
||||||
|
// Modified variables
|
||||||
|
fmt.Sprintf("verb %d", verbosity),
|
||||||
|
fmt.Sprintf("auth-user-pass %s", constants.OpenVPNAuthConf),
|
||||||
|
fmt.Sprintf("proto %s", connections[0].Protocol),
|
||||||
|
fmt.Sprintf("cipher %s", cipher),
|
||||||
|
fmt.Sprintf("auth %s", auth),
|
||||||
|
}
|
||||||
|
if !root {
|
||||||
|
lines = append(lines, "user nonrootuser")
|
||||||
|
}
|
||||||
|
for _, connection := range connections {
|
||||||
|
lines = append(lines, fmt.Sprintf("remote %s %d", connection.IP, connection.Port))
|
||||||
|
}
|
||||||
|
lines = append(lines, []string{
|
||||||
|
"<ca>",
|
||||||
|
"-----BEGIN CERTIFICATE-----",
|
||||||
|
constants.VyprvpnCertificate,
|
||||||
|
"-----END CERTIFICATE-----",
|
||||||
|
"</ca>",
|
||||||
|
}...)
|
||||||
|
return s.fileManager.WriteLinesToFile(string(constants.OpenVPNConf), lines, files.Ownership(uid, gid), files.Permissions(0400))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *vyprvpn) GetPortForward() (port uint16, err error) {
|
||||||
|
panic("port forwarding is not supported for vyprvpn")
|
||||||
|
}
|
||||||
@@ -62,6 +62,8 @@ func GetOpenVPNSettings(paramsReader params.Reader, vpnProvider models.VPNProvid
|
|||||||
settings.Provider, err = GetSurfsharkSettings(paramsReader)
|
settings.Provider, err = GetSurfsharkSettings(paramsReader)
|
||||||
case constants.Cyberghost:
|
case constants.Cyberghost:
|
||||||
settings.Provider, err = GetCyberghostSettings(paramsReader)
|
settings.Provider, err = GetCyberghostSettings(paramsReader)
|
||||||
|
case constants.Vyprvpn:
|
||||||
|
settings.Provider, err = GetVyprvpnSettings(paramsReader)
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("VPN service provider %q is not valid", vpnProvider)
|
err = fmt.Errorf("VPN service provider %q is not valid", vpnProvider)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,3 +135,21 @@ func GetCyberghostSettings(paramsReader params.Reader) (settings models.Provider
|
|||||||
}
|
}
|
||||||
return settings, nil
|
return settings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetVyprvpnSettings obtains Vyprvpn settings from environment variables using the params package.
|
||||||
|
func GetVyprvpnSettings(paramsReader params.Reader) (settings models.ProviderSettings, err error) {
|
||||||
|
settings.Name = constants.Vyprvpn
|
||||||
|
settings.ServerSelection.Protocol, err = paramsReader.GetNetworkProtocol()
|
||||||
|
if err != nil {
|
||||||
|
return settings, err
|
||||||
|
}
|
||||||
|
settings.ServerSelection.TargetIP, err = paramsReader.GetTargetIP()
|
||||||
|
if err != nil {
|
||||||
|
return settings, err
|
||||||
|
}
|
||||||
|
settings.ServerSelection.Region, err = paramsReader.GetVyprvpnRegion()
|
||||||
|
if err != nil {
|
||||||
|
return settings, err
|
||||||
|
}
|
||||||
|
return settings, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user