Compare commits
20 Commits
v4-storage
...
v3.39.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09c47c740c | ||
|
|
ecbfc02713 | ||
|
|
7be9288685 | ||
|
|
d1f57d0e36 | ||
|
|
74ea1a0f5a | ||
|
|
2a9ab29e7d | ||
|
|
8be78a5741 | ||
|
|
4a669c3458 | ||
|
|
ae5b71a864 | ||
|
|
6fff2ce1a4 | ||
|
|
f6165d206a | ||
|
|
8dbe7b8888 | ||
|
|
10f43d7a70 | ||
|
|
01283def17 | ||
|
|
b32e085354 | ||
|
|
ac9446e296 | ||
|
|
dea4080a7b | ||
|
|
2e63dba817 | ||
|
|
10384c9e37 | ||
|
|
34e8f5f3a9 |
@@ -37,12 +37,12 @@
|
||||
"go.useLanguageServer": true,
|
||||
"[go]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
"source.organizeImports": "explicit"
|
||||
}
|
||||
},
|
||||
"[go.mod]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
"source.organizeImports": "explicit"
|
||||
}
|
||||
},
|
||||
"gopls": {
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,10 +1,10 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Report a Wiki issue
|
||||
url: https://github.com/qdm12/gluetun-wiki/issues/new
|
||||
url: https://github.com/qdm12/gluetun-wiki/issues/new/choose
|
||||
about: Please create an issue on the gluetun-wiki repository.
|
||||
- name: Configuration help?
|
||||
url: https://github.com/qdm12/gluetun/discussions/new
|
||||
url: https://github.com/qdm12/gluetun/discussions/new/choose
|
||||
about: Please create a Github discussion.
|
||||
- name: Unraid template issue
|
||||
url: https://github.com/qdm12/gluetun/discussions/550
|
||||
|
||||
8
.github/labels.yml
vendored
8
.github/labels.yml
vendored
@@ -3,6 +3,9 @@
|
||||
- name: "Status: 🔴 Blocked"
|
||||
color: "f7d692"
|
||||
description: "Blocked by another issue or pull request"
|
||||
- name: "Status: 📌 Before next release"
|
||||
color: "f7d692"
|
||||
description: "Has to be done before the next release"
|
||||
- name: "Status: 🔒 After next release"
|
||||
color: "f7d692"
|
||||
description: "Will be done after the next release"
|
||||
@@ -36,6 +39,8 @@
|
||||
# VPN providers
|
||||
- name: "☁️ AirVPN"
|
||||
color: "cfe8d4"
|
||||
- name: "☁️ Custom"
|
||||
color: "cfe8d4"
|
||||
- name: "☁️ Cyberghost"
|
||||
color: "cfe8d4"
|
||||
- name: "☁️ HideMyAss"
|
||||
@@ -91,6 +96,9 @@
|
||||
- name: "Category: Maintenance ⛓️"
|
||||
description: "Anything related to code or other maintenance"
|
||||
color: "ffc7ea"
|
||||
- name: "Category: Logs 📚"
|
||||
description: "Something to change in logs"
|
||||
color: "ffc7ea"
|
||||
- name: "Category: Good idea 🎯"
|
||||
description: "This is a good idea, judged by the maintainers"
|
||||
color: "ffc7ea"
|
||||
|
||||
@@ -120,9 +120,3 @@ linters:
|
||||
- wastedassign
|
||||
- whitespace
|
||||
- zerologlint
|
||||
|
||||
run:
|
||||
skip-dirs:
|
||||
- .devcontainer
|
||||
- .github
|
||||
- doc
|
||||
|
||||
@@ -60,8 +60,8 @@ 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 **ProtonVPN**, **PureVPN**, **Torguard**, **VPN Unlimited** and **WeVPN** using [the custom provider](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/custom.md)
|
||||
- For **AirVPN**, **FastestVPN**, **Ivpn**, **Mullvad**, **NordVPN**, **Perfect privacy**, **ProtonVPN**, **Surfshark** and **Windscribe**
|
||||
- For **Cyberghost**, **Private Internet Access**, **PrivateVPN**, **PureVPN**, **Torguard**, **VPN Unlimited**, **VyprVPN** 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)
|
||||
- DNS over TLS baked in with service provider(s) of your choice
|
||||
@@ -73,7 +73,7 @@ Lightweight swiss-knife-like VPN client to multiple VPN service providers
|
||||
- [Connect other containers to it](https://github.com/qdm12/gluetun-wiki/blob/main/setup/connect-a-container-to-gluetun.md)
|
||||
- [Connect LAN devices to it](https://github.com/qdm12/gluetun-wiki/blob/main/setup/connect-a-lan-device-to-gluetun.md)
|
||||
- Compatible with amd64, i686 (32 bit), **ARM** 64 bit, ARM 32 bit v6 and v7, and even ppc64le 🎆
|
||||
- [Custom VPN server side port forwarding for Private Internet Access](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/private-internet-access.md#vpn-server-port-forwarding)
|
||||
- Custom VPN server side port forwarding for [Perfect Privacy](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/perfect-privacy.md#vpn-server-port-forwarding), [Private Internet Access](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/private-internet-access.md#vpn-server-port-forwarding) and [ProtonVPN](https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/protonvpn.md#vpn-server-port-forwarding)
|
||||
- Possibility of split horizon DNS by selecting multiple DNS over TLS providers
|
||||
- Unbound subprogram drops root privileges once launched
|
||||
- Can work as a Kubernetes sidecar container, thanks @rorph
|
||||
@@ -84,7 +84,7 @@ Lightweight swiss-knife-like VPN client to multiple VPN service providers
|
||||
|
||||
Go to the [Wiki](https://github.com/qdm12/gluetun-wiki)!
|
||||
|
||||
[🐛 Found a bug in the Wiki?!](https://github.com/qdm12/gluetun-wiki/issues/new)
|
||||
[🐛 Found a bug in the Wiki?!](https://github.com/qdm12/gluetun-wiki/issues/new/choose)
|
||||
|
||||
Here's a docker-compose.yml for the laziest:
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
|
||||
Emails: []string{"quentin.mcgaw@gmail.com"},
|
||||
Version: buildInfo.Version,
|
||||
Commit: buildInfo.Commit,
|
||||
BuildDate: buildInfo.Created,
|
||||
Created: buildInfo.Created,
|
||||
Announcement: "Wiki moved to https://github.com/qdm12/gluetun-wiki",
|
||||
AnnounceExp: announcementExp,
|
||||
// Sponsor information
|
||||
|
||||
4
go.mod
4
go.mod
@@ -3,7 +3,7 @@ module github.com/qdm12/gluetun
|
||||
go 1.22
|
||||
|
||||
require (
|
||||
github.com/breml/rootcerts v0.2.16
|
||||
github.com/breml/rootcerts v0.2.17
|
||||
github.com/fatih/color v1.17.0
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/klauspost/compress v1.17.8
|
||||
@@ -12,7 +12,7 @@ require (
|
||||
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6
|
||||
github.com/qdm12/gosettings v0.4.2
|
||||
github.com/qdm12/goshutdown v0.3.0
|
||||
github.com/qdm12/gosplash v0.1.0
|
||||
github.com/qdm12/gosplash v0.2.0
|
||||
github.com/qdm12/gotree v0.2.0
|
||||
github.com/qdm12/log v0.1.0
|
||||
github.com/qdm12/ss-server v0.6.0
|
||||
|
||||
10
go.sum
10
go.sum
@@ -4,8 +4,8 @@ github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/g
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/breml/rootcerts v0.2.16 h1:yN1TGvicfHx8dKz3OQRIrx/5nE/iN3XT1ibqGbd6urc=
|
||||
github.com/breml/rootcerts v0.2.16/go.mod h1:S/PKh+4d1HUn4HQovEB8hPJZO6pUZYrIhmXBhsegfXw=
|
||||
github.com/breml/rootcerts v0.2.17 h1:0/M2BE2Apw0qEJCXDOkaiu7d5Sx5ObNfe1BkImJ4u1I=
|
||||
github.com/breml/rootcerts v0.2.17/go.mod h1:S/PKh+4d1HUn4HQovEB8hPJZO6pUZYrIhmXBhsegfXw=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@@ -93,14 +93,12 @@ github.com/qdm12/golibs v0.0.0-20210603202746-e5494e9c2ebb/go.mod h1:15RBzkun0i8
|
||||
github.com/qdm12/golibs v0.0.0-20210723175634-a75ca7fd74c2/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
|
||||
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6 h1:bge5AL7cjHJMPz+5IOz5yF01q/l8No6+lIEBieA8gMg=
|
||||
github.com/qdm12/golibs v0.0.0-20210822203818-5c568b0777b6/go.mod h1:6aRbg4Z/bTbm9JfxsGXfWKHi7zsOvPfUTK1S5HuAFKg=
|
||||
github.com/qdm12/gosettings v0.4.1 h1:c7+14jO1Y2kFXBCUfS2+QE2NgwTKfzcdJzGEFRItCI8=
|
||||
github.com/qdm12/gosettings v0.4.1/go.mod h1:uItKwGXibJp2pQ0am6MBKilpjfvYTGiH+zXHd10jFj8=
|
||||
github.com/qdm12/gosettings v0.4.2 h1:Gb39NScPr7OQV+oy0o1OD7A121udITDJuUGa7ljDF58=
|
||||
github.com/qdm12/gosettings v0.4.2/go.mod h1:CPrt2YC4UsURTrslmhxocVhMCW03lIrqdH2hzIf5prg=
|
||||
github.com/qdm12/goshutdown v0.3.0 h1:pqBpJkdwlZlfTEx4QHtS8u8CXx6pG0fVo6S1N0MpSEM=
|
||||
github.com/qdm12/goshutdown v0.3.0/go.mod h1:EqZ46No00kCTZ5qzdd3qIzY6ayhMt24QI8Mh8LVQYmM=
|
||||
github.com/qdm12/gosplash v0.1.0 h1:Sfl+zIjFZFP7b0iqf2l5UkmEY97XBnaKkH3FNY6Gf7g=
|
||||
github.com/qdm12/gosplash v0.1.0/go.mod h1:+A3fWW4/rUeDXhY3ieBzwghKdnIPFJgD8K3qQkenJlw=
|
||||
github.com/qdm12/gosplash v0.2.0 h1:DOxCEizbW6ZG+FgpH2oK1atT6bM8MHL9GZ2ywSS4zZY=
|
||||
github.com/qdm12/gosplash v0.2.0/go.mod h1:k+1PzhO0th9cpX4q2Nneu4xTsndXqrM/x7NTIYmJ4jo=
|
||||
github.com/qdm12/gotree v0.2.0 h1:+58ltxkNLUyHtATFereAcOjBVfY6ETqRex8XK90Fb/c=
|
||||
github.com/qdm12/gotree v0.2.0/go.mod h1:1SdFaqKZuI46U1apbXIf25pDMNnrPuYLEqMF/qL4lY4=
|
||||
github.com/qdm12/log v0.1.0 h1:jYBd/xscHYpblzZAd2kjZp2YmuYHjAAfbTViJWxoPTw=
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
@@ -173,10 +174,15 @@ func (w *Wireguard) overrideWith(other Wireguard) {
|
||||
func (w *Wireguard) setDefaults(vpnProvider string) {
|
||||
w.PrivateKey = gosettings.DefaultPointer(w.PrivateKey, "")
|
||||
w.PreSharedKey = gosettings.DefaultPointer(w.PreSharedKey, "")
|
||||
if vpnProvider == providers.Nordvpn {
|
||||
switch vpnProvider {
|
||||
case providers.Nordvpn:
|
||||
defaultNordVPNAddress := netip.AddrFrom4([4]byte{10, 5, 0, 2})
|
||||
defaultNordVPNPrefix := netip.PrefixFrom(defaultNordVPNAddress, defaultNordVPNAddress.BitLen())
|
||||
w.Addresses = gosettings.DefaultSlice(w.Addresses, []netip.Prefix{defaultNordVPNPrefix})
|
||||
case providers.Protonvpn:
|
||||
defaultAddress := netip.AddrFrom4([4]byte{10, 2, 0, 2})
|
||||
defaultPrefix := netip.PrefixFrom(defaultAddress, defaultAddress.BitLen())
|
||||
w.Addresses = gosettings.DefaultSlice(w.Addresses, []netip.Prefix{defaultPrefix})
|
||||
}
|
||||
defaultAllowedIPs := []netip.Prefix{
|
||||
netip.PrefixFrom(netip.IPv4Unspecified(), 0),
|
||||
|
||||
@@ -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() {
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
// empty string path is returned.
|
||||
func findIP6tablesSupported(ctx context.Context, runner command.Runner) (
|
||||
ip6tablesPath string, err error) {
|
||||
ip6tablesPath, err = checkIptablesSupport(ctx, runner, "ip6tables-legacy", "ip6tables", "ip6tables-nft")
|
||||
ip6tablesPath, err = checkIptablesSupport(ctx, runner, "ip6tables", "ip6tables-nft", "ip6tables-legacy")
|
||||
if errors.Is(err, ErrIPTablesNotSupported) {
|
||||
return "", nil
|
||||
} else if err != nil {
|
||||
|
||||
@@ -210,10 +210,14 @@ func (c *Config) redirectPort(ctx context.Context, intf string,
|
||||
}
|
||||
|
||||
err = c.runIptablesInstructions(ctx, []string{
|
||||
fmt.Sprintf("-t nat %s PREROUTING %s -d 127.0.0.1 -p tcp --dport %d -j REDIRECT --to-ports %d",
|
||||
fmt.Sprintf("-t nat %s PREROUTING %s -p tcp --dport %d -j REDIRECT --to-ports %d",
|
||||
appendOrDelete(remove), interfaceFlag, sourcePort, destinationPort),
|
||||
fmt.Sprintf("-t nat %s PREROUTING %s -d 127.0.0.1 -p udp --dport %d -j REDIRECT --to-ports %d",
|
||||
fmt.Sprintf("%s INPUT %s -p tcp -m tcp --dport %d -j ACCEPT",
|
||||
appendOrDelete(remove), interfaceFlag, destinationPort),
|
||||
fmt.Sprintf("-t nat %s PREROUTING %s -p udp --dport %d -j REDIRECT --to-ports %d",
|
||||
appendOrDelete(remove), interfaceFlag, sourcePort, destinationPort),
|
||||
fmt.Sprintf("%s INPUT %s -p udp -m udp --dport %d -j ACCEPT",
|
||||
appendOrDelete(remove), interfaceFlag, destinationPort),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("redirecting IPv4 source port %d to destination port %d on interface %s: %w",
|
||||
@@ -221,10 +225,14 @@ func (c *Config) redirectPort(ctx context.Context, intf string,
|
||||
}
|
||||
|
||||
err = c.runIP6tablesInstructions(ctx, []string{
|
||||
fmt.Sprintf("-t nat %s PREROUTING %s -d ::1 -p tcp --dport %d -j REDIRECT --to-ports %d",
|
||||
fmt.Sprintf("-t nat %s PREROUTING %s -p tcp --dport %d -j REDIRECT --to-ports %d",
|
||||
appendOrDelete(remove), interfaceFlag, sourcePort, destinationPort),
|
||||
fmt.Sprintf("-t nat %s PREROUTING %s -d ::1 -p udp --dport %d -j REDIRECT --to-ports %d",
|
||||
fmt.Sprintf("%s INPUT %s -p tcp -m tcp --dport %d -j ACCEPT",
|
||||
appendOrDelete(remove), interfaceFlag, destinationPort),
|
||||
fmt.Sprintf("-t nat %s PREROUTING %s -p udp --dport %d -j REDIRECT --to-ports %d",
|
||||
appendOrDelete(remove), interfaceFlag, sourcePort, destinationPort),
|
||||
fmt.Sprintf("%s INPUT %s -p udp -m udp --dport %d -j ACCEPT",
|
||||
appendOrDelete(remove), interfaceFlag, destinationPort),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("redirecting IPv6 source port %d to destination port %d on interface %s: %w",
|
||||
|
||||
@@ -21,7 +21,7 @@ type Connection struct {
|
||||
PubKey string `json:"pubkey"`
|
||||
// ServerName is used for PIA for port forwarding
|
||||
ServerName string `json:"server_name,omitempty"`
|
||||
// PortForward is used for PIA for port forwarding
|
||||
// PortForward is used for PIA and ProtonVPN for port forwarding
|
||||
PortForward bool `json:"port_forward"`
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ func getMarkdownHeaders(vpnProvider string) (headers []string) {
|
||||
case providers.Mullvad:
|
||||
return []string{countryHeader, cityHeader, ispHeader, ownedHeader, hostnameHeader, vpnHeader}
|
||||
case providers.Nordvpn:
|
||||
return []string{countryHeader, regionHeader, cityHeader, hostnameHeader, categoriesHeader}
|
||||
return []string{countryHeader, regionHeader, cityHeader, hostnameHeader, vpnHeader, categoriesHeader}
|
||||
case providers.Perfectprivacy:
|
||||
return []string{cityHeader, tcpHeader, udpHeader}
|
||||
case providers.Privado:
|
||||
@@ -135,14 +135,15 @@ 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}
|
||||
case providers.SlickVPN:
|
||||
return []string{regionHeader, countryHeader, cityHeader, hostnameHeader}
|
||||
case providers.Surfshark:
|
||||
return []string{regionHeader, countryHeader, cityHeader, hostnameHeader, multiHopHeader, tcpHeader, udpHeader}
|
||||
return []string{regionHeader, countryHeader, cityHeader, hostnameHeader,
|
||||
vpnHeader, multiHopHeader, tcpHeader, udpHeader}
|
||||
case providers.Torguard:
|
||||
return []string{countryHeader, cityHeader, hostnameHeader, tcpHeader, udpHeader}
|
||||
case providers.VPNSecure:
|
||||
|
||||
@@ -18,6 +18,11 @@ var (
|
||||
func extractDataFromLines(lines []string) (
|
||||
connection models.Connection, err error) {
|
||||
for i, line := range lines {
|
||||
hashSymbolIndex := strings.Index(line, "#")
|
||||
if hashSymbolIndex >= 0 {
|
||||
line = line[:hashSymbolIndex]
|
||||
}
|
||||
|
||||
ip, port, protocol, err := extractDataFromLine(line)
|
||||
if err != nil {
|
||||
return connection, fmt.Errorf("on line %d: %w", i+1, err)
|
||||
|
||||
@@ -40,11 +40,12 @@ func getOpenVPNConnection(extractor Extractor,
|
||||
connection.Port = customPort
|
||||
}
|
||||
|
||||
// assume all custom provider servers support port forwarding
|
||||
connection.PortForward = true
|
||||
if len(selection.Names) > 0 {
|
||||
// Set the server name for PIA port forwarding code used
|
||||
// together with the custom provider.
|
||||
connection.ServerName = selection.Names[0]
|
||||
connection.PortForward = true
|
||||
}
|
||||
|
||||
return connection, nil
|
||||
@@ -53,17 +54,17 @@ func getOpenVPNConnection(extractor Extractor,
|
||||
func getWireguardConnection(selection settings.ServerSelection) (
|
||||
connection models.Connection) {
|
||||
connection = models.Connection{
|
||||
Type: vpn.Wireguard,
|
||||
IP: selection.Wireguard.EndpointIP,
|
||||
Port: *selection.Wireguard.EndpointPort,
|
||||
Protocol: constants.UDP,
|
||||
PubKey: selection.Wireguard.PublicKey,
|
||||
Type: vpn.Wireguard,
|
||||
IP: selection.Wireguard.EndpointIP,
|
||||
Port: *selection.Wireguard.EndpointPort,
|
||||
Protocol: constants.UDP,
|
||||
PubKey: selection.Wireguard.PublicKey,
|
||||
PortForward: true, // assume all custom provider servers support port forwarding
|
||||
}
|
||||
if len(selection.Names) > 0 {
|
||||
// Set the server name for PIA port forwarding code used
|
||||
// together with the custom provider.
|
||||
connection.ServerName = selection.Names[0]
|
||||
connection.PortForward = true
|
||||
}
|
||||
return connection
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/constants"
|
||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/qdm12/gluetun/internal/provider/common"
|
||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||
@@ -64,6 +65,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
||||
continue
|
||||
}
|
||||
server := models.Server{
|
||||
VPN: vpn.OpenVPN,
|
||||
Country: country,
|
||||
City: city,
|
||||
IPs: ips,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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) (
|
||||
|
||||
@@ -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
|
||||
@@ -16,36 +16,50 @@ 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
|
||||
}
|
||||
|
||||
func (its ipToServers) numberOfServers() int {
|
||||
const serversPerIP = 2
|
||||
return len(its) * serversPerIP
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -65,6 +65,7 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
|
||||
|
||||
hostname := physicalServer.Domain
|
||||
entryIP := physicalServer.EntryIP
|
||||
wgPubKey := physicalServer.X25519PublicKey
|
||||
|
||||
// Note: for multi-hop use the server name or hostname
|
||||
// instead of the country
|
||||
@@ -74,11 +75,11 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ipToServer) < minServers {
|
||||
if ipToServer.numberOfServers() < minServers {
|
||||
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||
common.ErrNotEnoughServers, len(ipToServer), minServers)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
@@ -49,13 +50,17 @@ func getLatestRelease(ctx context.Context, client *http.Client) (tagName, name s
|
||||
if err != nil {
|
||||
return "", "", time, err
|
||||
}
|
||||
// Sort releases by tag names (semver)
|
||||
sort.Slice(releases, func(i, j int) bool {
|
||||
return releases[i].TagName > releases[j].TagName
|
||||
})
|
||||
for _, release := range releases {
|
||||
if release.Prerelease {
|
||||
continue
|
||||
}
|
||||
return release.TagName, release.Name, release.PublishedAt, nil
|
||||
}
|
||||
return "", "", time, errReleaseNotFound
|
||||
return "", "", time, fmt.Errorf("%w", errReleaseNotFound)
|
||||
}
|
||||
|
||||
var errCommitNotFound = errors.New("commit not found")
|
||||
|
||||
Reference in New Issue
Block a user