Skip to content

Instantly share code, notes, and snippets.

@Lazza
Last active April 16, 2024 09:36
Show Gist options
  • Save Lazza/bbc15561b65c16db8ca8 to your computer and use it in GitHub Desktop.
Save Lazza/bbc15561b65c16db8ca8 to your computer and use it in GitHub Desktop.
VPNGate Python script

This script is NOT MAINTAINED

This snippet of code was posted in 2014 and slightly revised in 2016 and 2017. It was more of a quick'n'dirty script than a polished tool. It is made only for Linux and in Python 2, which has since become outdated.

I currently do not use it, and I suggest you avoid it as well. Please do not expect support for using this script.

🔥 If you need an alternative, @glaucocustodio has kindly suggested EasyVPN in this comment.

The rest of the README is left for historical purposed.


vpngate.py

This script allows to use the free VPN service provided by VPNGate in an easy way. The user just needs to provide the desidered output country, and the script automatically chooses the best server.

After this step, OpenVPN is launched with the proper configuration. The VPN can be terminated by pressing Ctrl+C.

Usage

Run the script by providing the desired output country:

vpngate.py US

Both country codes and country names are supported, as listed on the VPNGate website, e.g.:

vpngate.py "United Kingdom"

Moreover, the script allows to input countries with any case (Italy, italy, ItALy all work) and with partial names:

  • Korea will work for Korea Republic Of
  • Russia will work for Russian Federation
  • ... and so on

Demo

Here is a short Youtube video showcasing an example usage:

YT video

Requirements

OpenVPN needs to be installed.

The script should run on any Linux distribution with the Python Requests module installed. The user running the script must be able to run sudo commands in order to start openvpn.

#!/usr/bin/env python
"""Pick server and start connection with VPNGate (http://www.vpngate.net/en/)"""
import requests, os, sys, tempfile, subprocess, base64, time
__author__ = "Andrea Lazzarotto"
__copyright__ = "Copyright 2014+, Andrea Lazzarotto"
__license__ = "GPLv3"
__version__ = "1.0"
__maintainer__ = "Andrea Lazzarotto"
__email__ = "andrea.lazzarotto@gmail.com"
if len(sys.argv) != 2:
print 'usage: ' + sys.argv[0] + ' [country name | country code]'
exit(1)
country = sys.argv[1]
if len(country) == 2:
i = 6 # short name for country
elif len(country) > 2:
i = 5 # long name for country
else:
print 'Country is too short!'
exit(1)
try:
vpn_data = requests.get('http://www.vpngate.net/api/iphone/').text.replace('\r','')
servers = [line.split(',') for line in vpn_data.split('\n')]
labels = servers[1]
labels[0] = labels[0][1:]
servers = [s for s in servers[2:] if len(s) > 1]
except:
print 'Cannot get VPN servers data'
exit(1)
desired = [s for s in servers if country.lower() in s[i].lower()]
found = len(desired)
print 'Found ' + str(found) + ' servers for country ' + country
if found == 0:
exit(1)
supported = [s for s in desired if len(s[-1]) > 0]
print str(len(supported)) + ' of these servers support OpenVPN'
# We pick the best servers by score
winner = sorted(supported, key=lambda s: float(s[2].replace(',','.')), reverse=True)[0]
print "\n== Best server =="
pairs = zip(labels, winner)[:-1]
for (l, d) in pairs[:4]:
print l + ': ' + d
print pairs[4][0] + ': ' + str(float(pairs[4][1]) / 10**6) + ' MBps'
print "Country: " + pairs[5][1]
print "\nLaunching VPN..."
_, path = tempfile.mkstemp()
f = open(path, 'w')
f.write(base64.b64decode(winner[-1]))
f.write('\nscript-security 2\nup /etc/openvpn/update-resolv-conf\ndown /etc/openvpn/update-resolv-conf')
f.close()
x = subprocess.Popen(['sudo', 'openvpn', '--config', path])
try:
while True:
time.sleep(600)
# termination with Ctrl+C
except:
try:
x.kill()
except:
pass
while x.poll() != 0:
time.sleep(1)
print '\nVPN terminated'
@chavarera
Copy link

python vpngate.py korea
Found 50 servers for country korea
50 of these servers support OpenVPN

== Best server ==
Traceback (most recent call last):
File "/Users/...../PycharmProjects/key/vpngate.py", line 50, in
pairs = zip(labels, winner)[:-1]
TypeError: 'zip' object is not subscriptable

what to do to fix this problem

Replace following line if you running on python3

pairs = zip(labels, winner)[:-1]

with

pairs = list(zip(labels, winner))[:-1]

@Lazza
Copy link
Author

Lazza commented Jan 11, 2022

Please check the "Requirements" section.

@robinestrad
Copy link

Hola, hay algun cliente para configurar una VPN l2tp con Python 3 en windows?

@Mertozturkk
Copy link

how can ı find the country code?

@sameer15-hue
Copy link

i am getting error in this way

Traceback (most recent call last):
File "C:\Users\shaik\Music\waste\aa.py", line 73, in
x = subprocess.Popen(["sudo", "openvpn", "--config", path])
File "C:\Users\shaik\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 969, in init
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:\Users\shaik\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1438, in _execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] The system cannot find the file specified

please help me
how to solve this issue

@Lazza
Copy link
Author

Lazza commented Jul 15, 2022

I believe for some reason you are trying to run the script on a Windows system.

@yasirismail009
Copy link

i am getting error in this way

Traceback (most recent call last): File "C:\Users\shaik\Music\waste\aa.py", line 73, in x = subprocess.Popen(["sudo", "openvpn", "--config", path]) File "C:\Users\shaik\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 969, in init self._execute_child(args, executable, preexec_fn, close_fds, File "C:\Users\shaik\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1438, in _execute_child hp, ht, pid, tid = _winapi.CreateProcess(executable, args, FileNotFoundError: [WinError 2] The system cannot find the file specified

please help me how to solve this issue

Any Updates

@dayojohn19
Copy link

dayojohn19@campoutHackatonEarth Python % brew info openvpn
openvpn: stable 2.5.5 (bottled)
SSL/TLS VPN implementing OSI layer 2 or 3 secure network extension
https://openvpn.net/community/
/opt/homebrew/Cellar/openvpn/2.5.5 (86 files, 1.7MB) *
Poured from bottle on 2022-09-10 at 17:27:04
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openvpn.rb
License: GPL-2.0-only with openvpn-openssl-exception
==> Dependencies
Build: pkg-config ✔
Required: lz4 ✔, lzo ✔, openssl@1.1 ✔, pkcs11-helper ✔
==> Caveats
To restart openvpn after an upgrade:
sudo brew services restart openvpn
Or, if you don't want/need a background service you can just run:
/opt/homebrew/opt/openvpn/sbin/openvpn --config /opt/homebrew/etc/openvpn/openvpn.conf

@dayojohn19
Copy link

2022-09-10 18:08:10 Cipher negotiation is disabled since neither P2MP client nor server mode is enabled
Options error: You must define TUN/TAP device (--dev)
Use --help for more information.

@R3DHULK
Copy link

R3DHULK commented Oct 15, 2022

Anyone got the script for python3 on windows 10?

"""Pick server and start connection with VPNGate (http://www.vpngate.net/en/)"""

import requests, os, sys, tempfile, subprocess, base64, time

author = "Andrea Lazzarotto"
copyright = "Copyright 2014+, Andrea Lazzarotto"
license = "GPLv3"
version = "1.0"
maintainer = "Andrea Lazzarotto"
email = "andrea.lazzarotto@gmail.com"

if len(sys.argv) != 2:
print ('usage: ' + sys.argv[0] + ' [country name | country code]')
exit(1)
country = sys.argv[1]

if len(country) == 2:
i = 6 # short name for country
elif len(country) > 2:
i = 5 # long name for country
else:
print ('Country is too short!')
exit(1)

try:
vpn_data = requests.get('http://www.vpngate.net/api/iphone/').text.replace('\r','')
servers = [line.split(',') for line in vpn_data.split('\n')]
labels = servers[1]
labels[0] = labels[0][1:]
servers = [s for s in servers[2:] if len(s) > 1]
except:
print ('Cannot get VPN servers data')
exit(1)

desired = [s for s in servers if country.lower() in s[i].lower()]
found = len(desired)
print ('Found ' + str(found) + ' servers for country ' + country)
if found == 0:
exit(1)

supported = [s for s in desired if len(s[-1]) > 0]
print (str(len(supported)) + ' of these servers support OpenVPN')

We pick the best servers by score

winner = sorted(supported, key=lambda s: float(s[2].replace(',','.')), reverse=True)[0]

print ("\n== Best server ==")
pairs = list(zip(labels, winner))[:-1]
for (l, d) in pairs[:4]:
print (l + ': ' + d)

print (pairs[4][0] + ': ' + str(float(pairs[4][1]) / 10**6) + ' MBps')
print ("Country: " + pairs[5][1])

print ("\nLaunching VPN...")
_, path = tempfile.mkstemp()

f = open(path, 'w')
f.write(base64.b64decode(winner[-1]))
f.write('\nscript-security 2\nup /etc/openvpn/update-resolv-conf\ndown /etc/openvpn/update-resolv-conf')
f.close()

x = subprocess.Popen(['sudo', 'openvpn', '--config', path])

try:
while True:
time.sleep(600)

termination with Ctrl+C

except:
try:
x.kill()
except:
pass
while x.poll() != 0:
time.sleep(1)
print ('\nVPN terminated')

@Lazza
Copy link
Author

Lazza commented Oct 15, 2022

@R3DHULK please do not dump Python code in the comments, it triggers unwanted Markdown rendering.

Feel free to post your own gist and link it here. Thank you.

@storm0611
Copy link

Could you tell me how can I run it on windows?
I have installed OpenVPN on my OS - windows 10.

@Rayan25062011
Copy link

Hello when i run the code it shows me: TypeError: ‘zip’ object is not subscriptable
Line 47

@Rayan25062011
Copy link

Can someone help me fix

@sameer15-hue
Copy link

sameer15-hue commented Nov 5, 2022 via email

@sameer15-hue
Copy link

sameer15-hue commented Nov 5, 2022 via email

@glaucocustodio
Copy link

@Lazza
Copy link
Author

Lazza commented Nov 26, 2022

@glaucocustodio Thank you for linking EasyVPN, it seems to be a quite neat script. I will add a note in the README file.

@Skippern
Copy link

Skippern commented Jan 6, 2023

It was close enough so I could rewrite it in python3 for my needs, I did some modifications for it since I have a scraper that needs to cycle through VPN's.

@Madkhix
Copy link

Madkhix commented Mar 21, 2023

Hi everyone when i try to run the code. Its giving error:
exit(1)
NameError: name 'exit' is not defined

I try with sys.exit(1) but nothing fixed. Can you help me about this problem please?

@Rayan25062011
Copy link

Try running pip install sys because the code has already imported the sys library

@Madkhix
Copy link

Madkhix commented Mar 21, 2023

I did that and this is the result:
sys.exit(1)
SystemExit: 1
@Rayan25062011

@Rayan25062011
Copy link

I did that and this is the result:
sys.exit(1)
SystemExit: 1
@Rayan25062011

So now its working! Now Make sure your connected to a fast internet and run the code, it should work

@Madkhix
Copy link

Madkhix commented Mar 21, 2023

Oh i got it. Yeah its working its always giving systemexit: 1 now and i dont know why. Can it be about country and country number ? I ma sure about my internet connection.
@Rayan25062011

@Rayan25062011
Copy link

Rayan25062011 commented Mar 21, 2023

Oh i got it. Yeah its working its always giving systemexit: 1 now and i dont know why. Can it be about country and country number ? I ma sure about my internet connection.
@Rayan25062011

Maybe its about the vpn gate servers, they are probably restarting or something, or the country your entering wrong. If its none of them then im sorry but i dont know either.

@Madkhix
Copy link

Madkhix commented Mar 21, 2023

I will try to solve somehow. Thanks for your help. I appreciate it. @Rayan25062011

@sameer15-hue
Copy link

sameer15-hue commented Mar 23, 2023 via email

@aashanm
Copy link

aashanm commented Jun 15, 2023

The code works for me, but I keep getting prompted to enter a password. Anyone know why?

image

@samrahimi
Copy link

Username, password, and preshared key are always "vpn" - if you are asked. Depending on the config of the host usually you will not be.

Yes this is amazing for webscrapers that need to cycle through IPs or for casual use cases like watching American Netflix. But the security implications are considerable... the hosts are random volunteers who are sharing their internet connections to help people in countries like China, Russia, and Iran break out of censorship mode. Which is awesome. But I wouldn't put in my credit card number while this thing is connected, because you never know if there could be a compromised host.

PS. If you get an error about a cipher, add this line to the config file and retry the connection, it should work:

data-ciphers AES-128-CBC:AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305

@taintedsilk
Copy link

anyone know how to run this in google colab?
no matter what i try to do i always can't get pass this error

2024-04-16 09:33:55 DEPRECATED OPTION: --cipher set to 'AES-128-CBC' but missing in --data-ciphers (AES-256-GCM:AES-128-GCM). Future OpenVPN version will ignore --cipher for cipher negotiations. Add 'AES-128-CBC' to --data-ciphers or change --cipher 'AES-128-CBC' to --data-ciphers-fallback 'AES-128-CBC' to silence this warning.
2024-04-16 09:33:55 OpenVPN 2.5.9 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Sep 29 2023
2024-04-16 09:33:55 library versions: OpenSSL 3.0.2 15 Mar 2022, LZO 2.10
2024-04-16 09:33:55 WARNING: No server certificate verification method has been enabled. See http://openvpn.net/howto.html#mitm for more info.
2024-04-16 09:33:55 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
2024-04-16 09:33:55 TCP/UDP: Preserving recently used remote address: [AF_INET]219.100.37.54:443
2024-04-16 09:33:55 Socket Buffers: R=[131072->131072] S=[16384->16384]
2024-04-16 09:33:55 Attempting to establish TCP connection with [AF_INET]219.100.37.54:443 [nonblock]
2024-04-16 09:33:55 TCP connection established with [AF_INET]219.100.37.54:443
2024-04-16 09:33:55 TCP_CLIENT link local: (not bound)
2024-04-16 09:33:55 TCP_CLIENT link remote: [AF_INET]219.100.37.54:443
2024-04-16 09:33:56 TLS: Initial packet from [AF_INET]219.100.37.54:443, sid=da46ef5f 7624c209
2024-04-16 09:33:56 VERIFY OK: depth=2, C=US, O=Internet Security Research Group, CN=ISRG Root X1
2024-04-16 09:33:56 VERIFY OK: depth=1, C=US, O=Let's Encrypt, CN=R3
2024-04-16 09:33:56 VERIFY OK: depth=0, CN=opengw.net
2024-04-16 09:33:56 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 2048 bit RSA, signature: RSA-SHA256
2024-04-16 09:33:56 [opengw.net] Peer Connection Initiated with [AF_INET]219.100.37.54:443
2024-04-16 09:33:57 SENT CONTROL [opengw.net]: 'PUSH_REQUEST' (status=1)
2024-04-16 09:34:03 SENT CONTROL [opengw.net]: 'PUSH_REQUEST' (status=1)
2024-04-16 09:34:03 PUSH: Received control message: 'PUSH_REPLY,ping 3,ping-restart 10,ifconfig 10.236.18.49 10.236.18.50,dhcp-option DNS 10.236.254.254,dhcp-option DNS 8.8.8.8,route-gateway 10.236.18.50,redirect-gateway def1'
2024-04-16 09:34:03 OPTIONS IMPORT: timers and/or timeouts modified
2024-04-16 09:34:03 OPTIONS IMPORT: --ifconfig/up options modified
2024-04-16 09:34:03 OPTIONS IMPORT: route options modified
2024-04-16 09:34:03 OPTIONS IMPORT: route-related options modified
2024-04-16 09:34:03 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
2024-04-16 09:34:03 Using peer cipher 'AES-128-CBC'
2024-04-16 09:34:03 Outgoing Data Channel: Cipher 'AES-128-CBC' initialized with 128 bit key
2024-04-16 09:34:03 Outgoing Data Channel: Using 160 bit message hash 'SHA1' for HMAC authentication
2024-04-16 09:34:03 Incoming Data Channel: Cipher 'AES-128-CBC' initialized with 128 bit key
2024-04-16 09:34:03 Incoming Data Channel: Using 160 bit message hash 'SHA1' for HMAC authentication
2024-04-16 09:34:03 net_route_v4_best_gw query: dst 0.0.0.0
2024-04-16 09:34:03 net_route_v4_best_gw result: via 172.28.0.1 dev eth0
2024-04-16 09:34:03 ROUTE_GATEWAY 172.28.0.1/255.255.0.0 IFACE=eth0 HWADDR=02:42:ac:1c:00:0c
2024-04-16 09:34:04 ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1)
2024-04-16 09:34:04 Exiting due to fatal error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment