Skip to content
This repository was archived by the owner on Nov 5, 2025. It is now read-only.

Commit f9515e9

Browse files
committed
Add country code exclusion in connect command
1 parent c3f8dff commit f9515e9

File tree

3 files changed

+39
-18
lines changed

3 files changed

+39
-18
lines changed

USAGE.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,16 @@ You can use the `--random` or `-r` flag to connect to a random server:
281281

282282
`protonvpn c -r`
283283

284-
There are several other variables to keep in mind when you want to connect to the “fastest” server. You can connect to the fastest server in a country, the fastest Secure Core server, the fastest P2P-enabled server, or the fastest Tor server.
284+
There are several other variables to keep in mind when you want to connect to the “fastest” server. You can connect to the fastest server in a country, the fastest server outside a country, the fastest Secure Core server, the fastest P2P-enabled server, or the fastest Tor server.
285285

286286
Fastest server in a country (replace UK with the code of the desired country, e.g. `US` for USA, `JP` for Japan, `AU` for Australia, etc.):
287287

288288
`protonvpn c --cc UK`
289289

290+
Fastest server outside a country (replace UK with the code of the desired country, e.g. `US` for USA, `JP` for Japan, `AU` for Australia, etc.):
291+
292+
`protonvpn c --not-cc UK`
293+
290294
Fastest Secure Core server:
291295

292296
`protonvpn c --sc`

protonvpn_cli/cli.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
protonvpn (c | connect) [<servername>] [-p <protocol>]
77
protonvpn (c | connect) [-f | --fastest] [-p <protocol>]
88
protonvpn (c | connect) [--cc <code>] [-p <protocol>]
9+
protonvpn (c | connect) [--not-cc <code>] [-p <protocol>]
910
protonvpn (c | connect) [--sc] [-p <protocol>]
1011
protonvpn (c | connect) [--p2p] [-p <protocol>]
1112
protonvpn (c | connect) [--tor] [-p <protocol>]
@@ -23,6 +24,7 @@
2324
-f, --fastest Select the fastest ProtonVPN server.
2425
-r, --random Select a random ProtonVPN server.
2526
--cc CODE Determine the country for fastest connect.
27+
--not-cc CODE Determine the country to exclude for fastest connect.
2628
--sc Connect to the fastest Secure-Core server.
2729
--p2p Connect to the fastest torrent server.
2830
--tor Connect to the fastest Tor server.
@@ -118,6 +120,8 @@ def cli():
118120
connection.direct(args.get("<servername>"), protocol)
119121
elif args.get("--cc") is not None:
120122
connection.country_f(args.get("--cc"), protocol)
123+
elif args.get("--not-cc") is not None:
124+
connection.country_f(args.get("--not-cc"), protocol, True)
121125
# Features: 1: Secure-Core, 2: Tor, 4: P2P
122126
elif args.get("--p2p"):
123127
connection.feature_f(4, protocol)
@@ -286,6 +290,9 @@ def print_examples():
286290
"protonvpn connect --cc AU\n"
287291
" Connect to the fastest Australian server\n"
288292
" with the default protocol.\n\n"
293+
"protonvpn connect --not-cc AU\n"
294+
" Connect to the fastest server outside Australia\n"
295+
" with the default protocol.\n\n"
289296
"protonvpn c --p2p -p tcp\n"
290297
" Connect to the fastest torrent server with TCP.\n\n"
291298
"protonvpn c --sc\n"
@@ -558,7 +565,7 @@ def set_killswitch():
558565
"The Kill Switch will block all network traffic\n"
559566
"if the VPN connection drops unexpectedly.\n"
560567
"\n"
561-
"Please note that the Kill Switch assumes only one network interface being active.\n" # noqa
568+
"Please note that the Kill Switch assumes only one network interface being active.\n" # noqa
562569
"\n"
563570
"1) Enable Kill Switch (Block access to/from LAN)\n"
564571
"2) Enable Kill Switch (Allow access to/from LAN)\n"

protonvpn_cli/connection.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def fastest(protocol=None):
165165
openvpn_connect(fastest_server, protocol)
166166

167167

168-
def country_f(country_code, protocol=None):
168+
def country_f(country_code, protocol=None, excluded=False):
169169
"""Connect to the fastest server in a specific country."""
170170
logger.debug("Starting fastest country connect")
171171

@@ -185,23 +185,33 @@ def country_f(country_code, protocol=None):
185185
# Filter out excluded features and countries
186186
server_pool = []
187187
for server in servers:
188-
if server["Features"] not in excluded_features and server["ExitCountry"] == country_code:
189-
server_pool.append(server)
188+
if server["Features"] not in excluded_features:
189+
if (excluded and server["ExitCountry"] != country_code) or (
190+
not excluded and server["ExitCountry"] == country_code
191+
):
192+
server_pool.append(server)
190193

191194
if len(server_pool) == 0:
192-
print(
193-
"[!] No Server in country {0} found\n".format(country_code)
194-
+ "[!] Please choose a valid country"
195-
)
196-
logger.debug("No server in country {0}".format(country_code))
195+
if not excluded:
196+
print(
197+
"[!] No Server in country {0} found\n".format(country_code)
198+
+ "[!] Please choose a valid country"
199+
)
200+
logger.debug("No server in country {0}".format(country_code))
201+
else:
202+
print(
203+
"[!] No Server found outside country {0}\n".format(country_code)
204+
+ "[!] Please choose a valid country"
205+
)
206+
logger.debug("No server outside country {0}".format(country_code))
197207
sys.exit(1)
198208

199209
fastest_server = get_fastest_server(server_pool)
200210
openvpn_connect(fastest_server, protocol)
201211

202212

203213
def feature_f(feature, protocol=None):
204-
"""Connect to the fastest server in a specific country."""
214+
"""Connect to the fastest server with have a specific feature"""
205215
logger.debug(
206216
"Starting fastest feature connect with feature {0}".format(feature)
207217
)
@@ -715,7 +725,7 @@ def manage_ipv6(mode):
715725
ipv6_addr = lines[1].strip()
716726

717727
ipv6_info = subprocess.run(
718-
"ip addr show dev {0} | grep '\<inet6.*global\>'".format(default_nic), # noqa
728+
"ip addr show dev {0} | grep '\<inet6.*global\>'".format(default_nic), # noqa
719729
shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE
720730
)
721731

@@ -833,10 +843,10 @@ def manage_killswitch(mode, proto=None, port=None):
833843
"iptables -A INPUT -i lo -j ACCEPT",
834844
"iptables -A OUTPUT -o {0} -j ACCEPT".format(device),
835845
"iptables -A INPUT -i {0} -j ACCEPT".format(device),
836-
"iptables -A OUTPUT -o {0} -m state --state ESTABLISHED,RELATED -j ACCEPT".format(device), # noqa
837-
"iptables -A INPUT -i {0} -m state --state ESTABLISHED,RELATED -j ACCEPT".format(device), # noqa
838-
"iptables -A OUTPUT -p {0} -m {1} --dport {2} -j ACCEPT".format(proto.lower(), proto.lower(), port), # noqa
839-
"iptables -A INPUT -p {0} -m {1} --sport {2} -j ACCEPT".format(proto.lower(), proto.lower(), port), # noqa
846+
"iptables -A OUTPUT -o {0} -m state --state ESTABLISHED,RELATED -j ACCEPT".format(device), # noqa
847+
"iptables -A INPUT -i {0} -m state --state ESTABLISHED,RELATED -j ACCEPT".format(device), # noqa
848+
"iptables -A OUTPUT -p {0} -m {1} --dport {2} -j ACCEPT".format(proto.lower(), proto.lower(), port), # noqa
849+
"iptables -A INPUT -p {0} -m {1} --sport {2} -j ACCEPT".format(proto.lower(), proto.lower(), port), # noqa
840850
]
841851

842852
if int(get_config_value("USER", "killswitch")) == 2:
@@ -849,8 +859,8 @@ def manage_killswitch(mode, proto=None, port=None):
849859
local_network = local_network.stdout.decode().strip().split()[1]
850860

851861
exclude_lan_commands = [
852-
"iptables -A OUTPUT -o {0} -d {1} -j ACCEPT".format(default_nic, local_network), # noqa
853-
"iptables -A INPUT -i {0} -s {1} -j ACCEPT".format(default_nic, local_network), # noqa
862+
"iptables -A OUTPUT -o {0} -d {1} -j ACCEPT".format(default_nic, local_network), # noqa
863+
"iptables -A INPUT -i {0} -s {1} -j ACCEPT".format(default_nic, local_network), # noqa
854864
]
855865

856866
for lan_command in exclude_lan_commands:

0 commit comments

Comments
 (0)