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
<-- 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.


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

  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.

    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:

    2. This comment has been removed by the author.

    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.

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