Si trabajáis con redes virtuales y sistemas Cisco, es probable que alguna vez os encontréis con este problema.
Resulta que cuando un usuario de Windows utiliza el Cisco VPN Client para conectar a la VPN de su empresa, este levanta una interfaz virtual para enrutar el tráfico privado por el IPsec Tunnel creado por el cliente Cisco. Hasta aquí todo correcto y previsible.
El problema viene cuando dicha interfaz virtual toma los DNS que el peer remoto le asigna, y no te dan opción a poner tú los tuyos, ya que estos son "machacados" cada vez que conectas con la VPN. Es fácil configurar cuando se tiene acceso a todos los parámetros de ambos extremos, y en especial cuando tienes la gestión del router/firewall que está actuando como terminador de túneles (típicamente un ASA, un PIX o algún otro chisme cisquero con esas capacidades). Pero en la vida real no suele ser el caso si utilizas un servicio gestionado por compañías como Movistar (cuya flexibilidad en la gestión de la VPN deja mucho que desear).
¿Qué pasa si no tienes tus DNS? Si tu equipo pertenece a un dominio Active Directory (o alguna otra tecnología dependiente de los DNS internos de la infrastructura de tu grupo) estás vendido por completo. No sólo no podrás resolver nombres de equipos internos (sin hacer la abominable chapuza de añadir nombres al archivo hosts, que me consta que aún hay quien lo hace), sino que tendrás otros problemas relacionados con la falta de resolución interna, por ejemplo algo tan básico como la autenticación o la aplicación de directivas de grupo.
Para colmo, suele producirse un efecto indeseado más: cuando en la LAN del cliente remoto existe un rango de direccionamiento IPv4 utilizado también por la sede remota a la que se pretende llegar por VPN. En este caso, aunque el software de Cisco tiene parámetros para controlar esta circunstancia, la realidad es que siempre termina habiendo problemas.
La solución
En este caso ayuda bastante el hecho de que el propio cliente Cisco te permite lanzar un ejecutable arbitrario una vez producida la autenticación remota. Haremos un script que se encargue de lidiar con los problemas anteriormente citados.
Como primer requisito es que el usuario que lance el cliente VPN Cisco debe tener permisos locales suficientes para gestionar parámetros de las interfaces de red. Aunque he visto más de un sysadmin cazurro agregar al usuario al grupo de Administradores solamente para que disponga de estos privilegios (¡qué barbaridad!), la manera correcta y elegante de hacer esto es agregar al usuario al grupo Operadores de configuración de red. Es un grupo local y por tanto lo encontraremos en la ventana de Administración de equipos.
El siguiente paso es abrir el Cisco VPN Client para indicarle la línea de comandos del script que se ejecutará tras la conexión. Digamos que llamaremos al script vpn.vbs y que para no complicarnos mucho la vida, lo copiaremos a la propia ruta del ejecutable de Cisco. El script lo vamos a hacer en VBscript, aunque sería realmente fácil portarlo a JScript. En cualquier caso, lo ejecutaremos con CSCRIPT para poder mostrar mensajes en pantalla sin que nos aparezcan continuos "pop-ups".
Así la cosa, la ruta será la siguiente:
C:\WINDOWS\System32\cscript.exe "C:\Archivos de programa\Cisco Systems\VPN Client\VPN.vbs"
Que tendremos que especificar en la opción del menú correspondiente:
Una vez preconfigurado todo, pasamos al meollo del asunto.
El script
Nuestro script hará las siguientes tareas de manera automatizada:
- Esperar a que la interfaz virtual esté levantada
- Obtener la dirección IP de dicha interfaz
- Agregar una ruta dinámica para llegar a la sede remota aún cuando el rango coincida con el local
- Borrar los DNS asignados por el extremo remoto del túnel y añadir los de nuestra compañía
- Abandonar el script
Un ejemplo del código de dicho script es el siguiente (adaptadlo a los parámetros de vuestro escenario).
'---------------------------------------------------------------------------- ' Configurador de red para clientes CISCO VPN ' The Debug Machine ' http://www.debugmachine.com ' ' Copyright 2013 José Ángel Morente ' Licensed under the Apache License, Version 2.0 (the "License"); ' you may not use this file except in compliance with the License. ' You may obtain a copy of the License at ' http://www.apache.org/licenses/LICENSE-2.0 ' Unless required by applicable law or agreed to in writing, software ' distributed under the License is distributed on an "AS IS" BASIS, ' WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ' See the License for the specific language governing permissions and ' limitations under the License. ' FUNCIONAMIENTO: ' ' Las conexiones VPN CISCO, tal y como están configuradas por Telefónica, dan ' problemas de rutas a la red 192.168.1.0 cuando coincide con la red local, ' así como problemas de resolución DNS (imposibilita resolver los objetos de ' sistema con los DNS propios). ' ' Este configurador ha de ejecutarse durante el proceso de conexión (usando la ' opción "Application Launcher" del cliente VPN CISCO. El programa espera ' hasta encontrar levantada la interfaz "CVirtA" (nombre interno de la conexión ' Cisco VPN). Una vez levantada, halla la dirección IP, agrega una ruta para ' forzar el tráfico de la 192.168.1.0 a través de la interfaz virtual, y ' finalmente selecciona los DNS internos de la compañía para que todas las ' resoluciones se hagan a través de ahí ' ' El script tiene varios parámetros configurables en forma de constantes. ' '----------------------------------------------------------------------------- Option Explicit 'CONFIGURACIÓN DEL SCRIPT Const NICServiceName = "CVirtA" Const strComputer = "." 'Equipo local Const remoteRoute = "192.168.1.0" Const remoteMask = "255.255.255.0" Const DNSservers = "192.168.1.11,192.168.1.12,192.168.1.13" '--------------MAIN Dim strIPAddress, NICIndex WScript.Echo "Esperando a que la interfaz " & NICServiceName & " esté lista..." 'Obtiene dirección IP y la muestra strIPAddress = GetVPNIPAddress (strComputer, NICServiceName) WScript.Echo "Dirección IP detectada: " & strIPAddress 'Crea la ruta WScript.Echo "Agregando ruta de sede remota a la interfaz " & strIPAddress AddRouteIP4 strComputer, remoteRoute, remoteMask, strIPAddress, NICIndex, 22 'Configura los DNS WScript.Echo "Configurando los DNS de la interfaz " & strIPAddress SetDNS NICServiceName, Split (DNSservers,",") 'Salir de la aplicación WScript.Quit 0 '--------------DECLARACION FUNCIONES Function GetVPNIPAddress (computerName, interfaceServiceName) '------------------------------------------------------------ ' Queda en espera hasta que se levante la interfaz de Cisco y ' devuelve su IP ' ' Entrada: ' computerName Nombre del equipo ("." para el equipo local) ' interfaceServiceName Nombre de servicio de la interfaz ' ' ' Salida: ' dirección IP en formato String ' '------------------------------------------------------------ dim strIPAddress dim objWMI,colInterfaces,objInterface Set objWMI = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & computerName & _ "\root\cimv2") 'Crea conexión local a la WMI 'obtiene todas las interfaces llamadas deseadas y que estén activas 'la interface de CISCO aparece como "IPenabled=false" hasta que no tiene una IP asignada 'por tanto hacemos un bucle hasta que dicha interface sea obtenida en la consulta, lo cuál significa 'que ya tiene una IP (IPenabled=true) Do Set colInterfaces = objWMI.ExecQuery _ ("Select * From Win32_NetworkAdapterConfiguration where ServiceName=""" & interfaceServiceName & _ """ and IPEnabled=true") Loop While colInterfaces.count=0 For each objInterface in colInterfaces strIPAddress = Join(objInterface.IPAddress, ",") GetVPNIPAddress = strIPAddress Next End Function Sub AddRouteIP4 (computerName, route, mask, gateway, InterfaceIndex, metric) '------------------------------------------------------------------------- ' Agrega una ruta dinámica en la tabla de rutas IPv4 ' Aunque esta función podría haber sido realizada mediante WMI, para evitar ' problemas de privilegios de usuario lo haremos ejecutando el comando "route" ' de Windows a través de una shell. ' Entrada: computerName Dim objShell, strCMD Set objShell = CreateObject ("WScript.Shell") strCMD = "route add " & route & " mask " & mask & " " & gateway 'Parámetros "metric" e "index" pueden ser "null" If metric <> Null Then strCMD = strCMD & " metric " & metric If InterfaceIndex <> Null Then strCMD = strCMD & " if " & InterfaceIndex objShell.Exec(strCMD) End Sub Sub SetDNS (interfaceServiceName, DNSlist) Dim objShell, i, strCMD, strNIC 'Obtiene el nombre de la interfaz strNIC = GetInterfaceNamebyServiceName (interfaceServiceName) Set objShell = CreateObject ("WScript.shell") 'Borra las DNS existentes strCMD = "netsh interface ip delete dns name=""" & strNIC & """ all" WScript.Echo vbTab & "Borrando DNS actualmente asignados" objShell.Run strCMD, 0, True 'ventana oculta y espera a que retorne 'Añade las demás DNS For i = 0 To UBound(DNSlist) Select Case i+1 'Comando DNS primaria Case 1: strCMD = "netsh interface ip set dns name=""" & strNIC & """" & _ " source=static addr=" & DNSlist(i) & " register=PRIMARY" 'Comando DNS secundarias Case Else: strCMD = "netsh interface ip add dns name=""" & strNIC & """" & _ " addr=" & DNSlist(i) & " index=" & i+1 End Select WScript.Echo vbTab & "Agregando DNS: " & DNSlist(i) objShell.Run strCMD, 0, True Next End Sub '-------------------------------------------- ' Obtiene el nombre de la interfaz de red ' a partir del "service name" (CVirtA) '-------------------------------------------- Function GetInterfaceNamebyServiceName (InterfaceServiceName) Dim objWMI, colInterfaces, objInterface Set objWMI = GetObject("winmgmts:" _ & "{impersonationLevel=Impersonate}!\\" & strComputer & "\root\cimv2") Set colInterfaces = objWMI.ExecQuery _ ("Select * From Win32_NetworkAdapter Where ServiceName=""" & interfaceServiceName & _ """") If colInterfaces.count Then For Each objInterface in colInterfaces GetInterfaceNamebyServiceName = objInterface.NetConnectionId Next End If End Function
Espero os haya servido de ayuda.
Saludos
No hay comentarios:
Publicar un comentario