Monday, October 24, 2016

Cisco AnyConnect VPN and Remote Desktop Connection (VPN establishment capability from a remote desktop is disabled. A VPN connection will not be established.)

Preface: today's post is not a particular one. As you can see, usual topic of the posts here is software development and non-obvious caveats you can meet along the way. This post is about "software taming": how to tweak the software written not by you.

VPN? Not again...
So, it happened again: your company got a deal with another company, so from here and now both parties will work together on something secret and cool. All that NDAs, mutual agreements and other "paperware" are completed and ta-da! you're granted to remotely access another company's IT infrastructure! Indeed, you have to do that via VPN. And very often this is Cisco VPN. Well... You're one-to-one with a software that is quite noticeable with it's presence on your PC. And, as any enterprise-class software, it has a bunch of that half-bugs/half-features which can be a real pain between you and your chair under some circumstances. For instance, at one of old versions of that VPN client (3.x or 4.x, not remember exactly), with active VPN connection, we had no local LAN access even if a corresponding checkbox ticked ON. To cure this, I had to literally delete two files from the system (vsdata.dll and vsdatant.sys). It seems that part of ZoneAlaram Firewall engine was integrated into that VPN client version but something went not as smooth as expected, or lack of requirements happened, or something...

And it's happened again to me. Recently I got fresh version of the VPN installed, and quickly stumbled upon a strange policy assigned by server-side: your PC is forbidden to establish a VPN connection if you're logged in via Remote Desktop. Same time, if you have the connection active and THEN log in via Remote Desktop, everything works perfectly. Quickly googling about, I found a lot of complains from people who have to drive to their workplace at a night time just for entirely one purpose: reconnect that VPN if connectivity issue happens. Another case is "what if you have to install the VPN client on a staging server" (because today it's usual thing that servers are virtual ones, so any of your connections is RDP for sure). Dead end, period.

Challenge accepted!
Honestly, I don't like non-convenient restrictions that raise against you while you plan to do your job. And I really DON'T like stupid restrictions. You shall judge: if a RDP session is considered non-secure, why to allow keep VPN connection running? Let's drop it if RDP session detected, from very first second. But instead we have that strange situation: you can use it and you can't renew it. Arrrgh!

So, what we can do? One of googled options was to install another "remote access software" like VNC or TeamViewer or so. But we're still talking about security, right? One thing is to use RDP session secured by your IT department (with help of another VPN, of course) and quite opposite thing is to install a software that exposes your PC to outer Internet with only user/password protection plus potential backdoors/vulnerabilities. Indeed, you should NOT play that way.

To preserve existing security, we have to script something like that:

  • drop RDP session
  • say Cisco VPN to establish a connection (as there is no more RDP session active)
  • wait a bit as the connection can take some time to be established and then restore RDP back

Help me, Google?

Scripting a connection
From the first head, we have to learn how to script a connection itself. Quick googling will lead us to VBS/PowerShell/etc scripts that activate the VPN GUI and imitate necessary keyboard input: populate username, send TAB code, populate password, send TAB code, send ENTER code... However, this is a bad guess:
  • What if next GUI version has another order of controls? Your input is missed, objective failed, and failed silently.
  • What if another app will pop up and catch your input? Let imagine, it's a messenger app with a group chat: your login & password are typed and sent to outer world by last ENTER!
Luckily, Cisco also provides a command-line app named as "vpncli.exe". You can find it in your %programfiles(x86)% folder as something like "Cisco\Cisco AnyConnect Secure Mobility Client\" or whatever (depending on actual version). Let start it (don't forget to exit from VPN GUI app before! they can't work both at the same time!). You should see something like that:
  >> state: Disconnected
  >> state: Disconnected
  >> notice: Ready to connect.
  >> registered with local VPN subsystem.
  >> contacting host (your-VPN-server-here) for login information...
  >> notice: Contacting your-VPN-server-here
  >> Please enter your username and password.
  ...
Type your credentials here - they should be accepted by the VPN server. Also, depending on VPN configuration, you can be asked for extra things like group/profile/etc. Just make a note for yourself what is asked at which order and format (for example, groups are expected as zero-based integer index). We'll need all this info soon.
So, let create "connect.cmd" file and put the following content inside (prepend the file names with full paths or put the folders into PATH environment variable - the choice is yours, I just omit the paths here for simplicity):
 
vpncli.exe -s < connect.dat  

You see? "connect.dat" file expected, let create it too as a following input:
connect your-VPN-server-here
your-username-here
your-password-here
<-- put empty line at the very end! very important!
So, here "connect" word is a literal command what to do, then we're mentioning all the credentials in the same order and format as you noted to yourself before (see previous paragraph). And it's very important to finish your file with empty line as it's passed to the "vpncli.exe" sequentially. So if you don't place a new line after your password, your command-line tool will wait for someone who would press ENTER. The empty line ensures we provision that ENTER.

So, if all the stars are came together, we see the connection established:
  >> notice: Establishing VPN...
  >> state: Connected
VPN> goodbye...
  >> note: VPN Connection is still active.


Doing remotely
If you login via RDP and start the script we've composed, the answer could be the same: RDP sessions are prohibited to establish VPN connections. So, we have to disconnect first. If you prepend your script with a "timeout 10" command and drop RDP before that 10 seconds elapsed, the answer could be the same again! Why? Reason is simple: your session is disconnected but still associated with RDP. How to "redirect" it back to physical keyboard? Google + StackOverflow are advising:
for /f "tokens=3 delims= " %%G in ('tasklist /FI "IMAGENAME eq tasklist.exe" /NH') do SET RDP_SESSION=%%G
echo Current RDP Session ID: %RDP_SESSION%

rem lock the console
Rundll32.exe user32.dll, LockWorkStation

rem Here %RDP_SESSION% contains RDP-Tcp#NNN as the ID of your current Remote Desktop session, for example, RDP-Tcp#0. 
rem You can see it in the Windows Task Manager on the Users tab, in the Session column.
tscon.exe %RDP_SESSION% /dest:console


So, we use some process querying to determine what is the exact name of our RDP session. Then, we make sure that your keyboard and screen are locked. Finally, we use "tscon" pre-installed utility to detach our session from RDP and associate it with real screen and keyboard (and this is very important per-caution we have locked the screen on previous step, otherwise anyone who is near your PC right now can sit in to your chair and use your PC on behalf of you!)

One more important thing to note: this code has to be launched under admin privileges (at least as local admin). So start your command prompt with "Run as administrator" first, then launch this script inside the prompt.

Connect the halves
Finally, we can combine two pieces of our recipe together: sail away from RDP lands and establish VPN connection.
for /f "tokens=3 delims= " %%G in ('tasklist /FI "IMAGENAME eq tasklist.exe" /NH') do SET RDP_SESSION=%%G
echo Current RDP Session ID: %RDP_SESSION%

rem lock the console
Rundll32.exe user32.dll, LockWorkStation

rem Here %RDP_SESSION% contains RDP-Tcp#NNN as the ID of your current Remote Desktop session, for example, RDP-Tcp#0. 
rem You can see it in the Windows Task Manager on the Users tab, in the Session column.
tscon.exe %RDP_SESSION% /dest:console

vpncli.exe -s < connect.dat


Start the script, and your RDP session is auto-terminates. Don't worry, it's OK. Now start counting: one... two... three... ready or not, here I come! Start your RDP again and enjoy all the benefits of Cisco VPN connected.

P.S. Sure thing, this script is just a boilerplate. You can amend it with %ERRORLEVEL% handling, extra provisioning steps etc. And surely this script code is a public domain knowledge. Feel free to use it for free.

17 comments:

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. Hello and thank you.. I am getting this error after the first line. ShouldI replace the %%G with my ID#

    %%G was unexpected at this time.

    ReplyDelete
    Replies
    1. Hi there! I believe you're about to run that command directly from command prompt, right? Then, you have to replace "double percent sign" with single one. "Double percent" is for scripts only. See more here: http://stackoverflow.com/questions/14509652/what-is-the-difference-between-and-in-a-cmd-file

      Delete
    2. This comment has been removed by the author.

      Delete
    3. Hey Yury.. Thanks for the response.. Yes I was testing to see why the script is not working.. I insertted a pause before the "VPNCLI" command and logged back in.
      I am getting the below error:

      C:\VPN>tscon.exe Console /dest:console
      Could not connect sessionID 1 to sessionname console, Error code 7045
      Error [7045]:The requested session access is denied.

      Delete
    4. Make sure you started the script under local admin (see above "One more important thing to note...").

      Delete
  3. Thank you very much :) It works

    ReplyDelete
    Replies
    1. Hi Algirdas, glad you find it useful. Stay tuned, there is another investigation on the go (VPN conflicting with some Hyper-V instances). Will publish a post about it as soon as got a workaround.

      Delete
  4. Thanks for sharing this! I connect to the other company's VPN while I'm logged in to a virtual machine on my laptop. This works like a charm. In my situation the other company doesn't have a valid certificate, so I was getting an error message. After some trial and error, I realized that I just needed to put a "Y" in the connect.dat file to connect despite the certificate warning. So it looks like this:

    connect your-VPN-server-here
    Y <-- Tell it to connect despite certificate error
    your-username-here
    your-password-here
    empty-line

    ReplyDelete
    Replies
    1. Yes, this "connect.dat" is just a redirection of keyboard input, line-by-line whatever you're asked about during a connection process. So that, it can lack of some lines situated in my example, or introduce new ones like in your situation. Glad you got your case solved!

      Delete
  5. Thank you very much! But I've got a problem when VPN works I can connect via rdp only using MSTSC /admin. Is it possible to connect via MSTSC?

    ReplyDelete
  6. The former parts are great, but I got a problem in passing the "security warning: untrusted server certificate", which I need to bypass it by clicking mouse.

    ReplyDelete
    Replies
    1. What's worse, even I managed to get a qualified SSL certificate by using Let's Encrypt, and corectly bypass the security warning of untrusted server, another problem is "error: Unable to retrieve logon information to verify compliance with AnyConnect logon enforcement and VPN establishment profile settings. A VPN connection will not be established."

      Delete
    2. Hi Worldhero,
      I have the same problem with the "security warning: untrusted server certificate". Could you detail the steps on how you bypassed it?
      I have no problem with credentials but I still have the problem with the certificate, any help will be appreciated.

      Delete
    3. I had the same warnings and here's 3 possible fixes I found that may help you.

      1) If the cert is untrusted simply go to the https://*VPN-IP-OR-FQDN* (Where you can download VPN client) form your Web Browser, inspect the cert, save to file, and install to your Computers trusted root store (not sure if other stores would work).
      2) Open the cert using Web Browser (See Above), check the Subject (CN=) or Subject Alternative Name (DNS Name=) and ensure your *VPNServer* in AnyConnect matches. If you cannot reach that hostname just modify your (C:\Windows\System32\Drivers\Etc\hosts) file and add a (*VPNServerIP* *HostName*) line *Use tab between IP and HostName*.
      If the Cert is a wildcard cert (IE DNSName=*.MyDomain.Com) you MUST include that domain in your hosts file entry (IE-*VPNServerIP* *VPNServerName*.MyDomain.Com).
      ~ Note - AnyConnect only cares that the server you give it matches the CN/DNSName of the cert. The hosts file allows us to point that CN/DNSName value to the correct IP if necessary. A wildcard cert does not care what the DNSName is as long as the Domain.Com matches, so you could add (SuperAwesomeVPN.Domain.Com *VPN-IP*) in hosts and AnyConnect will not throw a cert warning when you connect to SuperAwesomeVPN.Domain.Com.
      3) If you are the AnyConnect Admin you could Generate a new cert with IPAddress & DNSName in Subject Alt Name section if there's a requirement to connect to the IP instead of hostname without warnings (Security folks would most likely get upset about IP's in certs since anyone can see them, so it's best to just use FQDN instead of IP).

      tl;dr - Install the cert from https://VPNServer to computer trusted root store and use the hostname in AnyConnect that you find in cert CN/DNSName (modify hosts file if necessary).

      Delete
  7. After running connect.cmd in admin mode, I am unable to rdp back in to my remote device unless I disconnect from the VPN.

    ReplyDelete
    Replies
    1. Very strange. Do you see any related record in Event Viewer? Maybe, you have to apply this mode in the client XML profile:
      AllowRemoteUsers

      Delete