Skip to content

Commit 09c4783

Browse files
committed
SERVER_DEDICATED option
1 parent 42c5a5d commit 09c4783

10 files changed

Lines changed: 80 additions & 13 deletions

File tree

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ ENV VPN_SERVICE_PROVIDER=pia \
192192
PREMIUM_ONLY= \
193193
# # PIA and ProtonVPN only:
194194
PORT_FORWARD_ONLY= \
195+
# # Ovpn only:
196+
SERVER_DEDICATED=no \
195197
# Firewall
196198
FIREWALL_ENABLED_DISABLING_IT_SHOOTS_YOU_IN_YOUR_FOOT=on \
197199
FIREWALL_VPN_INPUT_PORTS= \

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ require (
1515
github.com/mdlayher/netlink v1.9.0
1616
github.com/pelletier/go-toml/v2 v2.2.4
1717
github.com/qdm12/dns/v2 v2.0.0-rc9.0.20260421173011-9de8e7fdbe3a
18-
github.com/qdm12/gluetun-servers v0.1.1-0.20260521235724-060a16d4b34c
18+
github.com/qdm12/gluetun-servers v0.1.1-0.20260522005421-14277e92ce82
1919
github.com/qdm12/goservices v0.1.1-0.20251104135713-6bee97bd4978
2020
github.com/qdm12/gosettings v0.4.4
2121
github.com/qdm12/goshutdown v0.3.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
7676
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
7777
github.com/qdm12/dns/v2 v2.0.0-rc9.0.20260421173011-9de8e7fdbe3a h1:TE157yPQmAbVruH0MWCQzs0vTT/6t96DkoWUXd6PVuc=
7878
github.com/qdm12/dns/v2 v2.0.0-rc9.0.20260421173011-9de8e7fdbe3a/go.mod h1:98foWgXJZ+g8gJIuO+fdO+oWpFei5WShMFTeN4Im2lE=
79-
github.com/qdm12/gluetun-servers v0.1.1-0.20260521235724-060a16d4b34c h1:rPgmhMt9uOq6pdPr8k0sXUnZ0fjTBw+yUOaIl0ttFu4=
80-
github.com/qdm12/gluetun-servers v0.1.1-0.20260521235724-060a16d4b34c/go.mod h1:acttuyHyoFDu6GTbf3kAV+QXeiX8oJeh0MBic67/9z8=
79+
github.com/qdm12/gluetun-servers v0.1.1-0.20260522005421-14277e92ce82 h1:tE44IEW7o9yPQaO8HBeoO9RxtTTxqhboIypegrQlVt8=
80+
github.com/qdm12/gluetun-servers v0.1.1-0.20260522005421-14277e92ce82/go.mod h1:acttuyHyoFDu6GTbf3kAV+QXeiX8oJeh0MBic67/9z8=
8181
github.com/qdm12/goservices v0.1.1-0.20251104135713-6bee97bd4978 h1:TRGpCU1l0lNwtogEUSs5U+RFceYxkAJUmrGabno7J5c=
8282
github.com/qdm12/goservices v0.1.1-0.20251104135713-6bee97bd4978/go.mod h1:D1Po4CRQLYjccnAR2JsVlN1sBMgQrcNLONbvyuzcdTg=
8383
github.com/qdm12/gosettings v0.4.4 h1:SM6tOZDf6k8qbjWU8KWyBF4mWIixfsKCfh9DGRLHlj4=

internal/configuration/settings/serverselection.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ type ServerSelection struct {
6363
// TorOnly is true if VPN servers without tor should
6464
// be filtered. This is used with ProtonVPN.
6565
TorOnly *bool `json:"tor_only"`
66+
// Dedicated is true if dedicated VPN servers should be chosen only.
67+
// This is used with OVPN.
68+
Dedicated *bool `json:"dedicated"`
6669
// OpenVPN contains settings to select OpenVPN servers
6770
// and the final connection.
6871
OpenVPN OpenVPNSelection `json:"openvpn"`
@@ -272,6 +275,8 @@ func validateFeatureFilters(settings ServerSelection, vpnServiceProvider string)
272275
return errors.New("secure core only filter is not supported")
273276
case *settings.TorOnly && vpnServiceProvider != providers.Protonvpn:
274277
return errors.New("tor only filter is not supported")
278+
case *settings.Dedicated && vpnServiceProvider != providers.Ovpn:
279+
return errors.New("dedicated filter is not supported")
275280
default:
276281
return nil
277282
}
@@ -296,6 +301,7 @@ func (ss *ServerSelection) copy() (copied ServerSelection) {
296301
TorOnly: gosettings.CopyPointer(ss.TorOnly),
297302
PortForwardOnly: gosettings.CopyPointer(ss.PortForwardOnly),
298303
MultiHopOnly: gosettings.CopyPointer(ss.MultiHopOnly),
304+
Dedicated: gosettings.CopyPointer(ss.Dedicated),
299305
OpenVPN: ss.OpenVPN.copy(),
300306
Wireguard: ss.Wireguard.copy(),
301307
}
@@ -319,6 +325,7 @@ func (ss *ServerSelection) overrideWith(other ServerSelection) {
319325
ss.TorOnly = gosettings.OverrideWithPointer(ss.TorOnly, other.TorOnly)
320326
ss.MultiHopOnly = gosettings.OverrideWithPointer(ss.MultiHopOnly, other.MultiHopOnly)
321327
ss.PortForwardOnly = gosettings.OverrideWithPointer(ss.PortForwardOnly, other.PortForwardOnly)
328+
ss.Dedicated = gosettings.OverrideWithPointer(ss.Dedicated, other.Dedicated)
322329
ss.OpenVPN.overrideWith(other.OpenVPN)
323330
ss.Wireguard.overrideWith(other.Wireguard)
324331
}
@@ -335,6 +342,7 @@ func (ss *ServerSelection) setDefaults(vpnProvider string, portForwardingEnabled
335342
defaultPortForwardOnly := portForwardingEnabled &&
336343
helpers.IsOneOf(vpnProvider, providers.PrivateInternetAccess, providers.Protonvpn)
337344
ss.PortForwardOnly = gosettings.DefaultPointer(ss.PortForwardOnly, defaultPortForwardOnly)
345+
ss.Dedicated = gosettings.DefaultPointer(ss.Dedicated, false)
338346
ss.OpenVPN.setDefaults(vpnProvider)
339347
ss.Wireguard.setDefaults()
340348
}
@@ -410,6 +418,10 @@ func (ss ServerSelection) toLinesNode() (node *gotree.Node) {
410418
node.Appendf("Multi-hop only servers: yes")
411419
}
412420

421+
if *ss.Dedicated {
422+
node.Appendf("Dedicated servers: yes")
423+
}
424+
413425
if *ss.PortForwardOnly {
414426
node.Appendf("Port forwarding only servers: yes")
415427
}
@@ -501,6 +513,12 @@ func (ss *ServerSelection) read(r *reader.Reader,
501513
return err
502514
}
503515

516+
// Ovpn only
517+
ss.Dedicated, err = r.BoolPtr("SERVER_DEDICATED")
518+
if err != nil {
519+
return err
520+
}
521+
504522
err = ss.OpenVPN.read(r)
505523
if err != nil {
506524
return err

internal/models/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type Server struct {
3434
SecureCore bool `json:"secure_core,omitempty"`
3535
Tor bool `json:"tor,omitempty"`
3636
PortForward bool `json:"port_forward,omitempty"`
37+
Dedicated bool `json:"dedicated,omitempty"`
3738
Keep bool `json:"keep,omitempty"`
3839
IPs []netip.Addr `json:"ips,omitempty"`
3940
PortsTCP []uint16 `json:"ports_tcp,omitempty"`

internal/provider/ovpn/updater/api.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ type apiDataCenter struct {
2222
}
2323

2424
type apiServer struct {
25-
IP netip.Addr `json:"ip"`
26-
Ptr string `json:"ptr"` // hostname
27-
Online bool `json:"online"`
28-
PublicKey string `json:"public_key"`
29-
WireguardPorts []uint16 `json:"wireguard_ports"`
30-
MultiHopOpenvpnPort uint16 `json:"multihop_openvpn_port"`
31-
MultiHopWireguardPort uint16 `json:"multihop_wireguard_port"`
25+
IP netip.Addr `json:"ip"`
26+
Ptr string `json:"ptr"` // hostname
27+
Online bool `json:"online"`
28+
// PublicKey is for the Standard Shared Entry Point
29+
PublicKey string `json:"public_key"`
30+
// PublicKeyIPv4 is for the Public / Dedicated IP Entry Point
31+
PublicKeyIPv4 string `json:"public_key_ipv4"`
32+
WireguardPorts []uint16 `json:"wireguard_ports"`
33+
MultiHopOpenvpnPort uint16 `json:"multihop_openvpn_port"`
34+
MultiHopWireguardPort uint16 `json:"multihop_wireguard_port"`
3235
}
3336

3437
func fetchAPI(ctx context.Context, client *http.Client) (
@@ -106,6 +109,7 @@ func (a *apiServer) validate() (err error) {
106109
{err: "ip address is not set", condition: !a.IP.IsValid()},
107110
{err: "hostname field is not set", condition: a.Ptr == ""},
108111
{err: "public key field is not set", condition: a.PublicKey == ""},
112+
{err: "public key IPv4 field is not set", condition: a.PublicKeyIPv4 == ""},
109113
{err: "wireguard ports array is not set", condition: len(a.WireguardPorts) == 0},
110114
{
111115
err: "wireguard port is not the default 9929",

internal/provider/ovpn/updater/api_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func Test_fetchAPI(t *testing.T) {
7676
Ptr: "vpn44.prd.vienna.ovpn.com",
7777
Online: true,
7878
PublicKey: "r83LIc0Q2F8s3dY9x5y17Yz8wTADJc7giW1t5eSmoXc=",
79+
PublicKeyIPv4: "wFbSRyjSXBmkjJodlqz7DoYn3WNDPYFUIXyIUS2QU2A=",
7980
WireguardPorts: []uint16{9929},
8081
MultiHopOpenvpnPort: 20044,
8182
MultiHopWireguardPort: 30044,

internal/provider/ovpn/updater/servers.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,18 @@ func (u *Updater) FetchServers(ctx context.Context, minServers int) (
5656
multiHopWireguardServer := wireguardServer
5757
multiHopWireguardServer.MultiHop = true
5858
multiHopWireguardServer.PortsUDP = []uint16{apiServer.MultiHopWireguardPort}
59-
servers = append(servers, wireguardServer, multiHopWireguardServer)
59+
dedicatedWireguardServer := wireguardServer
60+
dedicatedWireguardServer.WgPubKey = apiServer.PublicKeyIPv4
61+
dedicatedWireguardServer.Dedicated = true
62+
dedicatedMultiHopWireguardServer := multiHopWireguardServer
63+
dedicatedMultiHopWireguardServer.WgPubKey = apiServer.PublicKeyIPv4
64+
dedicatedMultiHopWireguardServer.Dedicated = true
65+
servers = append(servers,
66+
wireguardServer,
67+
multiHopWireguardServer,
68+
dedicatedWireguardServer,
69+
dedicatedMultiHopWireguardServer,
70+
)
6071
}
6172
}
6273

internal/provider/ovpn/updater/servers_test.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func Test_Updater_FetchServers(t *testing.T) {
5555
errMessage: "validating data center 1 of 1: data center Vienna: country name is not set",
5656
},
5757
"not_enough_servers": {
58-
minServers: 5,
58+
minServers: 7,
5959
responseStatus: http.StatusOK,
6060
responseBody: `{
6161
"success": true,
@@ -69,6 +69,7 @@ func Test_Updater_FetchServers(t *testing.T) {
6969
"ptr": "vpn44.prd.vienna.ovpn.com",
7070
"online": true,
7171
"public_key": "r83LIc0Q2F8s3dY9x5y17Yz8wTADJc7giW1t5eSmoXc=",
72+
"public_key_ipv4": "wFbSRyjSXBmkjJodlqz7DoYn3WNDPYFUIXyIUS2QU2A=",
7273
"wireguard_ports": [9929],
7374
"multihop_openvpn_port": 20044,
7475
"multihop_wireguard_port": 30044
@@ -78,7 +79,9 @@ func Test_Updater_FetchServers(t *testing.T) {
7879
]
7980
}`,
8081
errWrapped: common.ErrNotEnoughServers,
81-
errMessage: "not enough servers found: 4 and expected at least 5",
82+
// Wireguard + dedicated Wireguard + Wireguard multi-hop +
83+
// dedicated Wireguard multi-hop + OpenVPN + OpenVPN multi-hop
84+
errMessage: "not enough servers found: 6 and expected at least 7",
8285
},
8386
"success": {
8487
minServers: 4,
@@ -114,6 +117,7 @@ func Test_Updater_FetchServers(t *testing.T) {
114117
"ptr": "vpn45.prd.vienna.ovpn.com",
115118
"online": false,
116119
"public_key": "r93LIc0Q2F8s3dY9x5y17Yz8wTADJc7giW1t5eSmoXc=",
120+
"public_key_ipv4": "wGbSRyjSXBmkjJodlqz7DoYn3WNDPYFUIXyIUS2QU2A=",
117121
"wireguard_ports": [9929],
118122
"multihop_openvpn_port": 20045,
119123
"multihop_wireguard_port": 30045
@@ -163,6 +167,26 @@ func Test_Updater_FetchServers(t *testing.T) {
163167
MultiHop: true,
164168
PortsUDP: []uint16{30044},
165169
},
170+
{
171+
Country: "Austria",
172+
City: "Vienna",
173+
Hostname: "vpn44.prd.vienna.ovpn.com",
174+
IPs: []netip.Addr{netip.MustParseAddr("37.120.212.227")},
175+
VPN: vpn.Wireguard,
176+
WgPubKey: "wFbSRyjSXBmkjJodlqz7DoYn3WNDPYFUIXyIUS2QU2A=",
177+
Dedicated: true,
178+
},
179+
{
180+
Country: "Austria",
181+
City: "Vienna",
182+
Hostname: "vpn44.prd.vienna.ovpn.com",
183+
IPs: []netip.Addr{netip.MustParseAddr("37.120.212.227")},
184+
VPN: vpn.Wireguard,
185+
WgPubKey: "wFbSRyjSXBmkjJodlqz7DoYn3WNDPYFUIXyIUS2QU2A=",
186+
MultiHop: true,
187+
Dedicated: true,
188+
PortsUDP: []uint16{30044},
189+
},
166190
},
167191
},
168192
}

internal/storage/filter.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func (s *Storage) FilterServers(provider string, selection settings.ServerSelect
4949
return servers, nil
5050
}
5151

52+
//nolint:gocognit,gocyclo
5253
func filterServer(server models.Server,
5354
selection settings.ServerSelection,
5455
) (filtered bool) {
@@ -91,6 +92,11 @@ func filterServer(server models.Server,
9192
return true
9293
}
9394

95+
if (*selection.Dedicated && !server.Dedicated) ||
96+
(!*selection.Dedicated && server.Dedicated) {
97+
return false
98+
}
99+
94100
if filterByPossibilities(server.Country, selection.Countries) {
95101
return true
96102
}

0 commit comments

Comments
 (0)