To access some company resources i need to use Network Connect VPN from Juniper. Network Connect is a software package that interfaces with its Secure Access hardware and provides a Virtual Private Network (VPN) solution. There are two software products that connect to Secure Access servers: Windows Secure Application Manager which, as you might guess, runs on Microsoft Windows; and Network Connect which runs on other platforms, in particular GNU/Linux. All clients are closed source, without open source alternative.
I personally think that all closes source VPN clients should die one day – typically it is a perfect example of security by obscurity – internally they are using known algorithms and typically built with OpenSSL inside so there are no “secret” technologies. But closed source form will not allow to audit the code or to connect from non-supported OS (including non-x86 Linux, e.g. ARM). Also i`m sure that code security level is very low – often such clients contains statically linked outdated libraries or input parameter validation is bad. In the worst case such clients including kernel modules (some s..t from Cisco) and then you forced to use only supported kernel. In Juniper case native Linux client requires Java + web browser installed. Also its built with JNI (Java Native Interface) so it will run only on 32-bit platforms. To run it on my Linux/x86_64 i installed 32 bit versions of the Firefox and Oracle Java. It was very annoying to keep all this blobs in the RAM, so i decided to understand how it works and write some alternative.
How Network Connect works
After debugging with strace, java decompiler and tcpdump i got a clear view how Network Connect works:
- In the web browser client opening VPN page and entering Login/Password (in my case password generated from RSA Secure device)
- If authorization successful browser checks if VPN software is installed using Java applet. If it is not installed – ncLinux.jar file is downloaded and installation script is running. Client is installed to ~/.juniper_networks/network_connect. Also it will set SUID bit on ncsvc binary using su or sudo (password is prompted)
- Then optionally host checker (tncc.jar) client is running. This package validating if your system conforms policies configured on VPN host. In my case HC is running but probably is not strict – i am able to logon to VPN from my home Linux.
- On next step Java Applet launcing NC.jar and passing some parameters to it. Most important one is DSID – dynamic session key, taken from the browser cookie.
- NC.jar will start Java (AWT based) GUI and console client (ncsvc) using JNI (code is inside libncui.so). I found that after ncsvc startup it listening on TCP port 4242 (127.0.0.1 address). Then Java GUI starts and connecting to the ncsvc (port 4242).
- After connecting Java GUI sending configuration to the ncsvc using non-documented protocol and ncsvc establishing remote connection. In configuration packet i found DSID, certificate md5 fingerprint, hostname and some other data.
- When connection is established Java GUI getting reply and communicating with ncsvc to get connection statistic (number of data transferred, VPN algorithm, etc.).
- On disconnect GUI sends special command to ncsvc process and it disconnecting from the remote host and doing some cleanup (e.g. reverting /etc/resolv.conf and /etc/hosts).
Connection is established and maintained with ncsvc client. I found some information in the network (e.g. mad-scientist.us/juniper.html or www.joshhardman.net/juniper-network-connect-vpn-linux-64-bit/) on how to run it from command line, including some scripts. In my case all this scripts failed. If this scripts are working for you than you don`t need jvpn 🙂 Reason of fail was a Host Checker – related Juniper KB contains “Launch Network Connect only through the Internet browser on the supported Linux platforms” text. But i was not satisfied with this and decided to emulate Java GUI to run client from command line, without web browser. Command line interface of ncsvc (see ncsvc -h) will not help in this case, because there is no possibility to pass DSID , and all other CLI options failing in my case. So i wrote a perl script – jvpn.pl, and hooray – i was able to establish connection.
jvpn.pl script – description
- To use this script you need Perl (with some modules) and openssl binary. Also unzip is required if client is not installed.
- jvpn.pl using configuration file jvpn.ini – before usage you will need to setup host name, login, password and realm. If you don`t know your realm – read HTML source for the login page – it will contain hidden “REALM” input element.
- If ncsvc client is not installed – jvpn will download it to the current directory automatically from your VPN host
- Then it logging in to the web site using your username/password and getting DSID. It handles some advanced scenarios like “active sessions found” and “additional code required” pages from VPN. It also getting md5 fingerprint of the SSL certificate using “openssl” binary.
- If Host Checker support is enabled in configuration it is also download and starts tncc.jar to get host checker authentication from the server
- After getting DSID it starts ncsvs and sending configuration commands to it using TCP protocol (port 4242). On this stage ncsvs establishing VPN connection. Then jvpn.pl entering statistic loop, like Java GUI.
- On Ctrl+C jvpn.pl sending disconnect command to the ncsvs and also logging out from the VPN web site, to make sure that DSID is invalidated.
Version 0.7.0 – samm.kiev.ua/jvpn/jvpn-0.7.0.tar.bz2. If you found some bugs or did some improvements – drop me a note.