VPNC and Mac OS X Lion, Mavericks (NOTE: Broken on Yosemite) – Tip of the Week

NOTE: Update 23 October 2014: This is broken on Yosemite because of tighter controls on unsigned kernel extensions. These are NO LONGER allowed to either load or run as unsigned extensions. This prevents the /dev/tun* or /dev/tap* devices from being created. More to follow …

Michael

===

How I got VPNC working in Mac OS X Lion (works in Mavericks too), without clobbering my /etc/resolv.conf file, while preserving my local, default gateway setting!

NOTE: These steps are best used to access your work laptop securely from Home, rather than your entire Office network.  Best to use the standard OS X VPN setup for that

Mac OS X Lion’s inbuilt Cisco IPSEC VPN client works a treat, except when you want to do two crucial things:

1.  Not forward all traffic through the Tunnel, and
2.  Preserve your DNS settings so that you can continue to roam freely outside the Tunnel

The canned options available to you in the Apple client do not let you configure it to this degree.

This is where VPNC comes in – I use it on my Ubuntu workstation in this exact way, so that I can access my Laptop within my Office Microsoft domain, while continuing to work as normal from Home.

Ubuntu’s VPNC package allows me to accomplish the two requirements mentioned earlier using the following two parameters in the .conf file:

Target networks 10.x.x.0/24
DNSUpdate no

The Target networks parameter basically tells VPNC I only want to access this particular private network – it effectively prevents all traffic from flowing through the tunnel interface, except for the given network address
And the DNSUpdate parameter, which is deprecated, preserves your local DNS settings by not allowing VPNC to clobber /etc/resolv.conf with the Tunnel’s server-side DNS settings

So much for the Ubuntu setup.  Now, on to OS X Lion!

In a nutshell, here are the steps needed to make this work in OS X:

1.  Install the Apple Xcode development system
2.  Install the Command Line Tools component in Xcode (just in case!)
3.  Install the MacPorts ecosystem from the wonderful people at www.macports.org
4.  Using the MacPorts ecosystem, install the VPNC port for OS X Lion
5.  Configure VPNC correctly

****

1.  The Xcode development system is available from the Mac OS X App Store

2.  Once installed, goto Applications in the Finder window, and double-click on Xcode – once open, goto Xcode Preferences -> Downloads -> Components
Select Command Line Tools and Install the component

3.  Goto www.macports.org and download and install their system

4.  Once MacPorts is installed, at a Terminal shell do:

sudo update selfupdate    <— This ensures you have the latest version of the MacPorts system
sudo port install vpnc

…this will automatically determine which dependencies are needed by VPNC, download and install them, and then download and install VPNC itself.

Among the VPNC dependencies is the tuntaposx Tunnel interface package – a crucial bit right here!

5.  The MacPorts system installs in /opt/local – very neat and tidy.  It will also auto-configure your PATH variable the next time you open a Terminal window to include the path to its own executables.  So for example to run vpnc, you only need to type ‘vpnc’ at the root command line.

You will find the VPNC conf files in the /opt/local/etc/vpnc directory.  For our purposes, here is a typical VPN conf file – taken from my Ubuntu system:

[michael@asus ~]$ sudo cat /etc/vpnc/EMC.conf

## generated by pcf2vpnc
IPSec ID <your group id>
IPSec gateway <your vpn gateway IP>
IPSec secret <yoursecret>

Xauth username DOMAIN\<username>
Xauth password <password>

IKE Authmode psk
Target networks 10.x.x.0/24
#
DNSUpdate no

…we simply should copy the conf file into the /opt/local/etc/vpnc directory, and run:

sudo vpnc EMC

…to get things going in Mac OS X – but there are some very crucial bits to do before this:

A)  The tuntaposx tunnel interfaces do not get automatically created, nor do the Kernel extensions get loaded, even though the tuntaposx package is properly installed.
I don’t know why this is – so here’s what we do:

sudo rsync -av /opt/local/Library/Extensions/* /Library/Extensions/      <— This copies the tap.kext and tun.kext Kernel extension bundles into the System Extensions directory
sudo rsync -av /opt/local/Library/StartupItems/* /Library/StartupItems/  <— This copies the tun and tap initialisation services into the System StartupItems directory

Reboot once this is done, and confirm you can see the following:

bash-3.2#  ls /dev/tun*
/dev/tun0       /dev/tun10      /dev/tun12      /dev/tun14      /dev/tun2       /dev/tun4       /dev/tun6       /dev/tun8
/dev/tun1       /dev/tun11      /dev/tun13      /dev/tun15      /dev/tun3       /dev/tun5       /dev/tun7       /dev/tun9

(…we are only interested in tun devices, not tap devices)

…and also check that the Kernel extensions have been loaded too:

bash-3.2# kextstat |grep foo
109    0 0xffffff7f81afd000 0x8000     0x8000     foo.tun (1.0) <7 5 4 1>
110    0 0xffffff7f81b07000 0x7000     0x7000     foo.tap (1.0) <7 5 4 1>

B)  Comment out the two superfluous parameters from the conf file:

# Target networks 10.x.x.0/24
# DNSUpdate no

…these two parameters are not needed anymore

C)  Use the VPNC vpnc-script to emulate what the two parameters effectively did:

cd /opt/local/etc/vpnc
cp vpnc-script vpnc-script_ORIG

…and make the following changes using vi to vpnc-script:

#* INTERNAL_IP4_DNS             — list of dns serverss
INTERNAL_IP4_DNS=

#* CISCO_SPLIT_INC              — number of networks in split-network-list
#* CISCO_SPLIT_INC_%d_ADDR      — network address
#* CISCO_SPLIT_INC_%d_MASK      — subnet mask (for example: 255.255.255.0)
#* CISCO_SPLIT_INC_%d_MASKLEN   — subnet masklen (for example: 24)
CISCO_SPLIT_INC=1
CISCO_SPLIT_INC_0_ADDR=10.x.x.0
CISCO_SPLIT_INC_0_MASK=255.255.255.0
CISCO_SPLIT_INC_0_MASKLEN=24

The INTERNAL_IP4_DNS=

…parameter effectively says do not clobber /etc/resolv.conf, and the

CISCO_SPLIT*

…parameters effectively setup a private connection through the tunnel to the 10.x.x.0 network

The default vpnc-script above is always called when vpnc is run, and with the above changes made, we can now make a connection:

[michael@air ~]$ sudo vpnc EMC

add net 10.x.x.0: gateway 10.x.x.8
add host x.x.x.x : gateway 192.x.x.1
add net 10.x.x.0: gateway 10.x.x.8
VPNC started in background (pid: 800)…

[michael@air ~]$ netstat -rn
Routing tables

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            192.x.x.1      UGSc           45        0     en0
10.x.x/26       10.x.x.8        UGSc            0        0    tun0
10.x.x.8        10.x.x.8        UH              2        0    tun0
10.x.x/24       10.x.x.8        UGSc            0        0    tun0
.
.
.
…I can still resolve external hostnames, using my local DNS settings:

[michael@air ~]$ cat /etc/resolv.conf
#
# Mac OS X Notice
#
# This file is not used by the host name and address resolution
# or the DNS query routing mechanisms used by most processes on
# this Mac OS X system.
#
# This file is automatically generated.
#
domain theabbouds.lan
nameserver 192.x.x.1

[michael@air ~]$ ping http://www.google.com
PING http://www.l.google.com (74.125.237.112): 56 data bytes
64 bytes from 74.125.237.112: icmp_seq=0 ttl=56 time=10.193 ms
64 bytes from 74.125.237.112: icmp_seq=1 ttl=56 time=13.795 ms
64 bytes from 74.125.237.112: icmp_seq=2 ttl=56 time=13.579 ms

I can now ping the IP of my Office Laptop:

[michael@air ~]$ ping 10.x.x.33
PING 10.x.x.33 (10.x.x.33): 56 data bytes
64 bytes from 10.x.x.33: icmp_seq=0 ttl=122 time=18.259 ms
64 bytes from 10.x.x.33: icmp_seq=1 ttl=122 time=30.517 ms
64 bytes from 10.x.x.33: icmp_seq=2 ttl=122 time=23.366 ms
64 bytes from 10.x.x.33: icmp_seq=3 ttl=122 time=22.495 ms
64 bytes from 10.x.x.33: icmp_seq=4 ttl=122 time=20.989 ms

…and run an RDP session to it – at the same time

About Michael Abboud

Linux / Unix Technical Specialist
This entry was posted in Mac OS X and tagged , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

29 Responses to VPNC and Mac OS X Lion, Mavericks (NOTE: Broken on Yosemite) – Tip of the Week

  1. Ben says:

    I just completed the installation of vpnc using the steps above. I couldn’t have found a clearer or more accurate site documenting this task. Thank you.

  2. Amlan says:

    Kudos .. worked like a charm

  3. nipunaroran says:

    Thank you this helped immensly

  4. Joe D says:

    VPNC up and running. This couldn’t be any clearer. So helpful. Thanks for the post.

  5. alexR says:

    Finally a solution that works exactly how i need it! Thanks!

  6. f4cl3y says:

    Thanx man, pretty straight forward.

  7. mcgreal says:

    Excellent guide – works right out of the box, on Mavericks too. Thanks a million – now I can ditch the Ubuntu VM that takes too long to boot up each time I need fast access

  8. Thanks mcgreal, appreciate you feedback! I’ll update the article heading I think, to include Mavericks

  9. Pingback: vpnc | gegorguly's

  10. James Ward says:

    Hello, your article is awesome, but my needs are a bit more complex…

    I regularly need to connect to 3 VPNs at the same time. AND I need to forward DNS requests to DNS servers on each of these VPNs. In Linux, team mates have solved this problem by installing bind9, custom configuring it to forward DNS requests and making resolv.conf immutable. Is there a better way?

    Hoping for an answer…

  11. tdy says:

    RE: Part 5A

    You can use launchd to manage the tun/tap services:

    % sudo launchctl load -w /Library/LaunchDaemons/org.macports.tuntaposx.plist

    This command is needed because all ports have their startup items disabled by default. You only have to run it once to enable tuntaposx’s plist, and then launchd will start managing it transparently.

  12. Sanchez says:

    On Mavericks works fine, bu not work on OS X 10.10 (Yosemite).
    ls /dev/tun* return no rows,
    kextstat |grep foo
    extensions have not been loaded 😦
    I try clean macports installation and install vpnc again, but not helped…

  13. Thanks you guys! Appreciate the feedback, as always 🙂

    Just checking on this issue now, and can confirm Emil’s findings – the people at Homebrew have flagged this is as a known bug:

    https://github.com/Homebrew/homebrew/issues/31153

    Basically, Yosemite no longer allows unsigned kernel extensions to either load or run (see DomT4’s comment from July 28 in the above thread)

    The workaround at the moment seems to disable all kext checking, which is unacceptable

    Let’s see what we can find by looking al little deeper …

    • Sanchez says:

      can’t be used this homebrew solution ?

      sormy commented 3 days ago

      Also, autoloading for kexts via StartupItems didn’t work anymore. Need to rework to use LaunchDaemons.

      I think formula can be fixed to show solution for kext-dev-mode and also need to remove StratupItems and replace with LaunchDaemons solution.”

  14. …I think you’ll find that kext-dev-mode=1 means to completely disable kext sign checking for ALL kexts. That is a bad workaround. There is another workaround I have seen, where the Google signed Tunnelblick *.kext extensions are used, instead of the ones supplied by Macports. That is worth investigating, but you’ll need to make sure that the Tunnelblick licence permits this …

  15. routerdark says:

    thanks for this post…. you’re god!!!!

  16. routerdark says:

    @mabboud123 you know if this could be applied to IOS devices ( ipads or iphones ) ?

Leave a comment