VPNScripter Un scripter para conexiones VPN en Windows

Crear conexiones VPN rápidamente en Windows según un archivo de configuración XML

Introducción

Este es un script general de PowerShell que crea automáticamente un conjunto de conexiones VPN según un archivo de configuración XML. Muy útil si desea configurar rápidamente una VPN directamente en Windows sin usar ningún software VPN personalizado desarrollado por su proveedor de VPN.

Antecedentes

Las VPN siempre han sido históricamente una forma de conectarse a la red privada de las empresas desde Internet. Hoy en día, se han vuelto comerciales utilizándose principalmente por problemas de privacidad, enrutando todo el tráfico de Internet del cliente a servidores de retransmisión distribuidos en todo el mundo. Hay algunos protocolos diferentes para las conexiones VPN y Windows admite nativamente la mayoría de ellos, en particular:

  • PPTP: Uno de los primeros protocolos VPN, basado en la encapsulación (a través del protocolo GRE) y en la encriptación (RC4) del protocolo PPP [1]. PPTP fue desarrollado por Microsoft y ahora está siendo abandonado debido al algoritmo de encriptación débil e inseguro. La autenticación del cliente se realiza generalmente a través de un inicio de sesión y una contraseña, aunque también se pueden utilizar certificados de cliente. Desde el punto de vista de la red, PPTP utiliza el puerto TCP 1723 y requiere que los routers reenvíen el protocolo IP GRE.
  • L2TP/IPSEC: L2TP es un protocolo de túnel que, al igual que PPTP, se utiliza para encapsular el protocolo PPP. Dado que L2TP no es seguro (no tiene ningún tipo de encriptación), para proporcionar seguridad, a menudo se utiliza junto con otro protocolo, IPSEC [2]. La autenticación del cliente en L2TP requiere un inicio de sesión y una contraseña y, además, el cliente y el servidor suelen compartir también una clave previamente acordada (PSK) para permitir que el cliente establezca el túnel IPSEC, aunque el cliente también puede autenticarse en el servidor IPSEC con certificados. Desde el punto de vista de la red, L2TP utiliza el puerto UDP 1701, mientras que IPSEC utiliza los puertos UDP 4500 y 500 (si no está detrás de un protocolo NAT, ESP de IP también debe ser reenviado por los routers). Es el protocolo “más pesado”.
  • SSTP: Desarrollado por Microsoft, al igual que PPTP y L2TP, se basa en la encapsulación del protocolo PPP utilizando en su lugar un canal SSL/TLS para asegurar todo el tráfico (los mismos protocolos que se utilizan al navegar con https en sitios web seguros de Internet). Al igual que PPTP, la autenticación del cliente se realiza generalmente a través de un inicio de sesión y una contraseña, aunque también se pueden utilizar certificados de cliente. Dado que utiliza solo el puerto HTTPS estándar (TCP 443), es el protocolo más adecuado para eludir casi cualquier restricción de firewall y también se puede utilizar perfectamente con proxies.
  • IKEv2: Es una ligera variación de IPSEC en la que la autenticación del cliente no se realiza solo mediante una clave previamente acordada (PSK) o un certificado, sino también mediante el uso de credenciales de usuario-contraseña estándar. Además, IKEv2 es mucho más resistente a los cambios en la conectividad de la red, lo que lo convierte en una buena opción para usuarios móviles que se mueven entre puntos de acceso. Desde el punto de vista de la red, IKEv2 utiliza los puertos UDP 500 y 4500 (si no está detrás de un protocolo NAT, ESP de IP también debe ser reenviado por los routers).

Windows también tiene el protocolo automático, que básicamente intenta establecer la conexión VPN probando todos los protocolos IKEv2, SSTP, L2TP/IPSEC, PPTP en orden. Para obtener más información, consulte [3].

Uso del código

Toda la configuración del script se realiza en el archivo XML llamado vpnconfig.xml (consulte a continuación). Este archivo define un conjunto de proveedores de VPN (Elemento de nodo “Provider”) y, para cada proveedor, especifica un conjunto de servidores (Elemento secundario “Server”) para cada uno de los cuales se creará una conexión VPN en Windows. Examinemos los nodos:

  • Provider: Este nodo corresponde a un proveedor de VPN. Atributos:
    • name: Se utiliza para generar el nombre de la conexión VPN en Windows
    • basedomain: Se utiliza para generar el nombre de host del servidor VPN (normalmente, un proveedor de VPN ofrece un conjunto de servidores que comparten un nombre de dominio común). Puede sobrescribirse en el nodo del servidor.
    • l2tppsk: Es el secreto compartido previamente acordado para la conexión L2TP/IPSEC (normalmente es el mismo en todos los servidores del proveedor).
    • user: Es el nombre de usuario para acceder a la VPN (normalmente, es el mismo en todos los servidores del proveedor).
    • password: Es la contraseña asociada al nombre de usuario (normalmente, es la misma en todos los servidores del proveedor).
    • proto: Especifica el protocolo VPN a utilizar para todos los servidores, si se deja vacío, significa automático.
  • Server: Este nodo corresponde a un servidor de un proveedor de VPN. Atributos:
    • server: Especifica el nombre de host del servidor. Si este atributo no contiene el carácter “.”, el nombre de host se obtiene concatenando este campo con el dominio base del proveedor, de lo contrario, el nombre de host es igual a este campo.
    • proto: Especifica el protocolo VPN a utilizar. También anula cualquier protocolo definido en el nodo del proveedor.
    • user: Es el nombre de usuario para acceder a la VPN. También anula cualquier usuario definido en el nodo del proveedor.
    • password: Es la contraseña asociada al nombre de usuario. También anula cualquier contraseña definida en el nodo del proveedor.
<!-- Archivo de configuración VpnScripter © 2016 Federico Di Marco

El proveedor define los proveedores de VPN que tienes.
Cada proveedor de VPN tiene normalmente un conjunto de servidores a los que puedes conectarte, y el script crea una conexión VPN para cada servidor que especifiques para cada proveedor listado.
La conexión creada tendrá:
- Nombre: Atributo Server (hasta el primer .) + Nombre del proveedor si Proto es auto o está vacío. Nombre del servidor + Proto + Nombre del proveedor si no es nulo.
- Protocolo: el especificado en el elemento server o, si es nulo, el especificado en el elemento provider o, si es nulo, auto.
- L2tp PSK, Usuario, Contraseña: los especificados en el elemento server o, si es nulo, los especificados en el elemento provider (no tienes que repetirlos para todos los servidores).
- Nombre de host del servidor: Atributo Server + Dominio base del proveedor si el atributo del servidor no contiene ningún carácter "."; de lo contrario, el atributo del servidor.
-->

<Providers>
  <Proveedor nombre="TestVPN1" 
  basedomain="myvpn.com" usuario="user01" 
  contraseña="hottie">   
    <Servidor servidor="sw" />   
    <!--La VPN tendrá sw.myvpn.com como dirección de host y SW TestVPN1 como nombre, protocolo automático-->
    <Servidor servidor="ro" proto="PPTP"/>   
    <!--El protocolo del servidor anula el protocolo especificado por el proveedor (auto en este caso)-->
    <Servidor servidor="kick-vm.myvpnext.com" 
    proto="SSTP"/>  
    <!--La VPN tendrá kick-vm.myvpnext.com como dirección de host y KICK-VM TestVPN1 como nombre-->
    <Servidor servidor="sp" proto="IKEV2" 
    usuario="user15" contraseña="beer" /> 
</Proveedor>
<Proveedor nombre="TestVPN2" basedomain="myvpn2.com" 
l2tppsk="12345" usuario="test001" contraseña="master">
    <Servidor servidor="karate" proto="L2TP" 
    l2tppsk="314pi"/>
    <Servidor servidor="kazu"  />
    <Servidor servidor="moon"  />
    <Servidor servidor="sun" />
</Proveedor>
</Providers>

Dentro del archivo zip, encontrarás 3 archivos:

  • DotRas.dll: Es una biblioteca de clases de .NET que es utilizada por el script de PowerShell para crear conexiones VPN y debe estar en la misma carpeta que el script.
  • vpnconfig.xml: Es el archivo de configuración XML mencionado anteriormente, el cual debe ser editado con tu configuración.
  • VpnScripter.ps1: Es un script de PowerShell que se puede ejecutar desde PowerShell o hacer doble clic en él. Acepta un parámetro opcional llamado ConfigFile que especifica el nombre del archivo de configuración XML a utilizar (por defecto, vpnconfig.xml). Puedes especificar la bandera -Debug para obtener una salida de registro más detallada.

El script ha sido probado en Windows 10, pero también debería funcionar en cualquier versión de Windows con al menos PowerShell 3.0.

Descripción general de la implementación

Básicamente, todo el código se encuentra dentro de un único archivo de PowerShell llamado VpnScripter.ps1, el cual contiene una mezcla de XSD, C# y código de PowerShell. Básicamente:

  • Analiza y verifica el archivo de configuración XML vpnconfig.xml utilizando un esquema XSD incrustado definido dentro del script de PowerShell.
    El esquema en sí es muy simple (por ejemplo, contiene principalmente cláusulas xs:attribute que especifican los atributos permitidos/requeridos del archivo de configuración) y define un tipo simple llamado NotEmptyTrimmedString que, como su nombre indica, verifica mediante una expresión regular que un valor de atributo sea una “cadena no vacía y sin espacios” (se utiliza para el atributo del servidor que debe ser “significativo”). La verificación del esquema XSD se realiza a través de una función de PowerShell llamada ValidateLoadXml que utiliza funciones .NET estándar para realizar la validación (por ejemplo, new XmlDocument().Load(XmlReader.Create(<archivo>,<configuraciones con archivo de esquema>))).

    function ValidateLoadXml([string] $XmlFile, [string] $Schema) {
    
    	$verr={ 
    		Write-Error "Error: archivo XSD/XML con formato incorrecto. Línea: $($_.Exception.LineNumber) 
    		Desplazamiento: $($_.Exception.LinePosition) - $($_.Message)" 
    		throw [System.IO.InvalidDataException] 
    	}
    
    	try {
    		[System.Xml.XmlReaderSettings]$readsett=New-Object System.Xml.XmlReaderSettings
    		$readsett.Schemas.Add([System.Xml.Schema.XmlSchema]::Read
    		((New-Object System.IO.StringReader($Schema)),$verr))
    		$readsett.ValidationType=[System.Xml.ValidationType]::Schema
    		$readsett.add_ValidationEventHandler($verr)
    		$xmlconf = New-Object System.Xml.XmlDocument
    		$xmlconf.Load([System.Xml.XmlReader]::Create($XmlFile,$readsett))
    	}
    	catch [System.IO.InvalidDataException]  {
    		return $null
    	}
    	
    	return $xmlconf
    }
    	
  • Recorre todos los nodos Servidor de todos los nodos Proveedor del archivo de configuración XML
    • Genera la lista de parámetros necesarios para crear la entrada de VPN en Windows según las reglas mencionadas anteriormente (si el atributo del servidor contiene un punto ‘.’, es el nombre DNS completo del punto final de la VPN; de lo contrario, debe concatenarse con el atributo basedomain, etc.). Para evaluar el usuario, la contraseña, el protocolo y el L2tp PSK necesarios a partir de la información contenida en los nodos Servidor y Proveedor, el script utiliza un operador de fusión, bastante común en consultas SQL y en C# (operador ??), pero lamentablemente no disponible en PowerShell, por lo tanto, implementado en una función de PowerShell definida llamada Coalesce.
      function Coalesce([string[]] $StringsToLookThrough, [switch]$EmptyStringAsNull) {
        if ($EmptyStringAsNull.IsPresent) {
          return ($StringsToLookThrough | Where-Object { $_ } | Select-Object -first 1)
        }
        else {
          return (($StringsToLookThrough -ne $null) | Select-Object -first 1)
        }  
      }
      	
    • Realiza verificaciones adicionales en los parámetros que no son tan sencillas de hacer con XSD:
      • Si

        Como ya se ha mencionado, tanto el esquema XSD como el código helper de .NET se han incrustado dentro del script de PowerShell en un solo archivo casi autocontenido (requiere DotRas.dll). De hecho, los scripts de PowerShell tienen la interesante característica de permitir la inclusión de cualquier código .NET en ellos, lo que les permite hacer todo lo que se puede hacer con código C#. Es interesante la forma en la que se puede analizar y compilar un código C#:

        • Primero “cargar” cualquier DLL (con Add-Type -Path <archivo dll>) o ensamblado (con Add-Type -AssemblyName <ensamblado>) utilizado por el código personalizado.
        • Luego analizar y compilar tu código C# personalizado con Add-Type -ReferencedAssemblies <lista de ensamblados referenciales> -TypeDefinition <cadena que contiene el código C#> -Language CSharp
        Add-Type -Path $psscriptroot\DotRas.dll
        Add-Type -AssemblyName System.Xml
        Add-Type -ReferencedAssemblies $psscriptroot\DotRas.dll,System.Xml 
                 -TypeDefinition $Source -Language CSharp

        Puntos de interés

        Se ha utilizado la biblioteca externa DotRas.dll porque no parece haber una forma de configurar credenciales (usuario y contraseña) con el comando estándar de PowerShell Add-VpnConnection, por favor, avísame si encuentras una forma de hacerlo.

        Repositorio

        Puedes encontrar el repositorio del código fuente en GitHub. Si quieres agregar un archivo de configuración predefinido para tu proveedor de VPN con todos los servidores o mejorar el código, eres bienvenido/a.

        Historial

        • V1.0 (2 de diciembre de 2016)
          • Primera versión
        • V1.1. (7 de diciembre de 2016)
          • Se agregó la anulación de l2tppsk, usuario y contraseña en los nodos del servidor
          • Se agregó validación XML mediante XSD y comprobaciones simples en los parámetros usuario/contraseña/l2tppsk
        • V1.2 (27 de marzo de 2017)
          • Se agregó la sección de “Resumen de implementación”

        Referencias

        • [1] PPP es un antiguo protocolo punto a punto utilizado históricamente para conectarse a ISP mediante módems. Permite establecer una conexión entre dos puntos finales.
        • [2] IPSEC es un túnel cifrado entre dos puntos finales basado en un conjunto de reglas (llamadas asociaciones de seguridad) que establecen los algoritmos de cifrado e integridad que se utilizarán en el túnel y los paquetes de red que deben ser tunelizados (por ejemplo, todos los paquetes TCP, TCP dirigidos a un puerto en particular, etc.). Básicamente, encapsula TCP/UDP en un nuevo paquete IP cifrado (ESP). Los algoritmos utilizados para cifrar y verificar la integridad del mensaje se establecen a través de un protocolo de negociación llamado IKE. Dado que el cliente y el servidor se autentican principalmente mutuamente mediante certificados, IPSEC se utiliza habitualmente en VPN de LAN a LAN (por ejemplo, para la conexión de dos redes de organizaciones diferentes) y no en un escenario de cliente a LAN, sin embargo, para este tipo de escenario, es posible autenticarse mediante una clave compartida (pre-shared key o secreto compartido), aunque esto implica una seguridad menor.
        • [3] Protocolos de túnel de VPN de Microsoft

Leave a Reply

Your email address will not be published. Required fields are marked *