Conectar VPN usando Python

Migel Hewage Nimesha 10 octubre 2023
  1. ¿Qué es una VPN?
  2. Conectar VPN usando Python
  3. Conclusión
Conectar VPN usando Python

En el mundo, la seguridad y la privacidad se han convertido en las principales preocupaciones de las personas. En busca de una solución, los desarrolladores crearon VPN.

¿Qué es una VPN?

Una red privada virtual, también conocida como VPN, es un software donde crea una red privada para proteger nuestra privacidad en línea. VPN nos brinda muchos beneficios, pero la privacidad protegida y el cifrado de datos son las principales ventajas para los usuarios.

  1. Privacidad protegida

    Dado que VPN crea una red privada dentro de la red pública, lo que hacemos en Internet no se puede rastrear virtualmente. Oculta nuestra dirección IP, por lo que terceros no pueden rastrear nuestras actividades.

    Ocultar la IP significa que el sitio web que visitamos a través de una VPN ve el servidor VPN como el origen del tráfico.

    Entonces, VPN enmascarará la dirección IP del usuario y la IP del servidor VPN será visible. Lo que es más importante, este proceso evita la explotación de la ubicación del usuario y el tráfico; por lo tanto, la privacidad del usuario está protegida.

  2. Cifrado de datos

    VPN también encripta nuestros datos en línea. La VPN cifra los datos que enviamos a través de Internet para que los piratas informáticos y otros terceros no puedan recuperarlos.

    Incluso si los recuperan, no podrán comprender el contenido ni descifrar los datos.

    Como sabemos bien qué es una VPN ahora, intentemos conectarla. En este artículo, discutimos cómo conectar VPN usando Python.

Conectar VPN usando Python

Este tutorial utilizará un servicio VPN gratuito del software VPNGate y OpenVPN. VPNGate es un servicio público de VPN en la nube que podemos utilizar de forma gratuita.

Para usar OpenVPN, necesitamos instalarlo en nuestro sistema. Para el sistema operativo Windows, puede descargarlo e instalarlo manualmente.

Para usuarios de Linux o Ubuntu, use el siguiente comando.

Instalar OpenVPN:

$ apt-get install openvpn easy-rsa

Después de instalarlo, podemos crear un script de Python para conectarnos a la VPN. Cuando ejecutamos este script en la terminal, debemos proporcionar un país como argumento.

La sintaxis está abajo.

Python3 <filename.py> <countryname>

Al dar el nombre del país, hay dos opciones.

  1. Nombre largo del país

    $ python3 vpn.py Japan
    
  2. Nombre corto del país

    $ python3 vpn.py JP
    

Como primer paso, debemos importar las siguientes bibliotecas al script.

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

A veces, un usuario puede ingresar más de un país cuando ejecuta el script. Para evitar eso, podemos usar el siguiente fragmento de código.

Como primer paso, debemos importar las siguientes bibliotecas al script.

if len(sys.argv) != 2:
    print("Enter one country at a time!")
    exit(1)
cntry = sys.argv[1]

Aquí, en la primera línea, verificamos si el total de argumentos no es igual a dos. Si es igual, seguimos con el país dado; en caso contrario, ponemos precaución y salimos.

A continuación, podemos comprobar si el usuario ha dado el nombre largo o corto del país. Si el usuario ingresa una letra, podemos arrojar un mensaje de error.

if len(cntry) > 2:
    j = 5
elif len(cntry) == 2:
    j = 6
else:
    print("Cannot identify the country. Name is too short.")
    exit(1)

Entonces ahora podemos recuperar una lista de servidores VPN gratuitos disponibles del sitio web VPNGate. Junto a la lista podemos obtener etiquetas de los servidores VPN, como HostName, IP, Score, Ping, etc., y sus valores.

try:
    vpnServerListData = requests.get("http://www.vpngate.net/api/iphone/").text.replace(
        "\r", ""
    )
    freeServers = [line.split(",") for line in vpnServerListData.split("\n")]
    serverLabels = freeServers[1]
    serverLabels[0] = serverLabels[0][1:]
    freeServers = [srvrs for srvrs in freeServers[2:] if len(srvrs) > 1]
except:
    print("Something is wrong! Cannot load the VPN server's data")
    exit(1)

Luego necesitamos recuperar los servidores disponibles y obtener el número total. Luego podemos mostrar la cantidad de servidores disponibles.

Podemos lanzar un mensaje mencionándolo y salir si no hay servidores disponibles. Para lograr esta tarea, podemos usar el siguiente fragmento de código.

availableServers = [srvrs for srvrs in freeServers if cntry.lower() in srvrs[j].lower()]
numOfServers = len(availableServers)
print("We found " + str(numOfServers) + " servers for " + cntry)
if numOfServers == 0:
    exit(1)

Ahora deberíamos mostrar cuántos servidores admiten la herramienta OpenVPN. Dado que usamos esta herramienta para conectarnos a VPN, es esencial contar con servidores VPN compatibles, y luego podemos filtrarlos.

supporteServers = [srvrs for srvrs in availableServers if len(srvrs[-1]) > 0]
print("There are " + str(len(supporteServers)) + " servers that support OpenVPN")

Como hemos filtrado los servidores admitidos, debemos elegir el mejor servidor entre ellos, con el ping más bajo y la velocidad y puntuación más altas.

Entonces podemos mostrar sus atributos (etiquetas) usando un bucle for. Y finalmente, se puede mostrar el país.

bestServer = sorted(
    supporteServers, key=lambda srvrs: float(srvrs[2].replace(",", ".")), reverse=True
)[0]
print("\n------------------Best server------------------")
labelPair = list(zip(serverLabels, bestServer))[:-1]
for (l, d) in labelPair[:4]:
    print(l + ": " + d)
print(labelPair[4][0] + ": " + str(float(labelPair[4][1]) / 10 ** 6) + " MBps")
print("Country: " + labelPair[5][1])

Producción:

mejor servidor

Antes de lanzar la VPN, debemos actualizar el resolveconf con la configuración de DNS. Además, deben estar en formato de cadena.

Por defecto, viene en formato binario. Usando decodificación base64, podemos convertirlos en cadenas.

Entonces podemos lanzar la VPN.

print("\nLaunching VPN...")
_, path = tempfile.mkstemp()
file = open(path, "wb")
file.write(base64.b64decode(bestServer[-1]))
file.write(
    b"\nscript-security 2\nup /etc/openvpn/update-resolv-conf\ndown /etc/openvpn/update-resolv-conf"
)
file.close()
vpnR = subprocess.Popen(["sudo", "openvpn", "--config", path])

Después de ejecutarlo, podemos obtener el siguiente resultado.

lanzar vpn

Tenemos una conexión exitosa si recibe un mensaje como “Secuencia de inicialización completada”.

Secuencia de inicialización completada

Ahora nos hemos conectado con éxito a la VPN. A continuación puede ver la información del servidor VPNGate que podemos ver después de una conexión exitosa.

Además, podemos configurar el tiempo requerido para conectar OpenVPN al servidor VPN. A través del siguiente fragmento de código, podemos lograrlo.

try:
    # time required to connect the openvpn to connect the vpn server
    time.sleep(60)
    start_time = time.time()
    nUrl = "http://bot.whatismyipaddress.com/"
    nRet = requests.get(nUrl)
    if nRet.status_code == 200:
        with open('resp', "wb") as txtFile:
            txtFile.write(nRet.text)
            print('Time took to check Ip address  ',
                  (time.time() - start_time))
    vpnR.kill()

Para finalizar la conexión VPN, utilice Ctrl+C. Luego, la conexión terminará y el sistema lanzará un mensaje para notificar al usuario.

except Exception as ex:
    try:
        vpnR.kill()
    except:
        pass
    while vpnR.poll() != 0:
        time.sleep(1)
    print('\nVPN has terminated')

Producción:

vpn terminado

Código completo:

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

if len(sys.argv) != 2:
    print("Enter one country at a time!")
    exit(1)
cntry = sys.argv[1]

if len(cntry) > 2:
    j = 5
elif len(cntry) == 2:
    j = 6
else:
    print("Cannot identify the country. Name is too short.")
    exit(1)

try:
    vpnServerListData = requests.get("http://www.vpngate.net/api/iphone/").text.replace(
        "\r", ""
    )
    freeServers = [line.split(",") for line in vpnServerListData.split("\n")]
    serverLabels = freeServers[1]
    serverLabels[0] = serverLabels[0][1:]
    freeServers = [srvrs for srvrs in freeServers[2:] if len(srvrs) > 1]
except:
    print("Something is wrong! Cannot load the VPN server's data")
    exit(1)

    availableServers = [
        srvrs for srvrs in freeServers if cntry.lower() in srvrs[j].lower()
    ]
    numOfServers = len(availableServers)
    print("We found " + str(numOfServers) + " servers for " + cntry)
    if numOfServers == 0:
        exit(1)

    supporteServers = [srvrs for srvrs in availableServers if len(srvrs[-1]) > 0]
    print(str(len(supporteServers)) + " of these servers support OpenVPN")

    bestServer = sorted(
        supporteServers,
        key=lambda srvrs: float(srvrs[2].replace(",", ".")),
        reverse=True,
    )[0]
    print("\n== Best server ==")
    labelPair = list(zip(serverLabels, bestServer))[:-1]
    for (l, d) in labelPair[:4]:
        print(l + ": " + d)
    print(labelPair[4][0] + ": " + str(float(labelPair[4][1]) / 10 ** 6) + " MBps")
    print("Country: " + labelPair[5][1])

    print("\nLaunching VPN...")
    _, path = tempfile.mkstemp()
    file = open(path, "wb")
    file.write(base64.b64decode(bestServer[-1]))
    file.write(
        b"\nscript-security 2\nup /etc/openvpn/update-resolv-conf\ndown /etc/openvpn/update-resolv-conf"
    )
    file.close()
    vpnR = subprocess.Popen(["sudo", "openvpn", "--config", path])

try:
    # time required to connect the openvpn to connect the vpn server
    time.sleep(60)
    timeS = time.time()
    nUrl = "http://bot.whatismyipaddress.com/"
    nRet = requests.get(nUrl)
    if nRet.status_code == 200:
        with open("resp", "wb") as txtFile:
            txtFile.write(nRet.text)
    print("Time took to check Ip address  ", (time.time() - timeS))
    vpnR.kill()

except Exception as ex:
    try:
        vpnR.kill()
    except:
        pass
    while vpnR.poll() != 0:
        time.sleep(1)
    print("\nVPN has terminated")

Salida (sin terminación):

sin terminar

Conclusión

A lo largo de este artículo, discutimos qué es una VPN y sus beneficios. Luego conectamos un servicio VPN gratuito usando Python.

Existen otros métodos para alcanzar nuestro objetivo, pero podemos comprender fácilmente los conceptos básicos de conexión a una VPN a través de este método.

Migel Hewage Nimesha avatar Migel Hewage Nimesha avatar

Nimesha is a Full-stack Software Engineer for more than five years, he loves technology, as technology has the power to solve our many problems within just a minute. He have been contributing to various projects over the last 5+ years and working with almost all the so-called 03 tiers(DB, M-Tier, and Client). Recently, he has started working with DevOps technologies such as Azure administration, Kubernetes, Terraform automation, and Bash scripting as well.