How should I use VPN on a Mac to prevent compromise before the VPN starts?

As most experienced users will have heard, using a Mac in a public untrusted Wi-Fi can be potentially harmful. A tool like Firesheep1 has made it very easy to intercept unencrypted communication.

Using a full tunnel VPN to encrypt all communication is as often mentioned as a magical solution to eavesdropping, but of course it's not that easy:

  • Depending on the protocol and configuration of the VPN connection, the connection may drop easier. (e.g. TLS vs UDP)
  • The VPN connection is not established instantly when you connect to a public network.

I think that the last two points matter a lot because whenever your network settings change the various applications immediately talk to their servers - I assume it's configd that informs them, right?

i.e. Before the VPN tunnel is established, most (running) processes that require internet will communicate.

I see two components to being a good VPN user:

  1. Making sure things don't get sent in the clear before it's established.
  2. Making sure things don't get sent in the clear later if the VPN fails.

How can I use VPN on a Mac in a public network to restrict unencrypted traffic before the VPN starts up?


Solution 1:

Let's set aside any solution where you bring a second piece of networking gear to the problem. Let's also let the problem of stopping traffic after the VPN fails to this related, but different question.

I look at this problem as a user centric solution and not something that's easily accomplished by modifying the OS X behavior.

Set up two accounts on your Mac (neither need be admin accounts, but if either is, you won't need a third account to change system settings).

  1. A shell account that exists to run nothing and only establish the VPN connection.
  2. A main account that will run the programs you wish to ensure only get access to the network once it has been properly secured with a VPN.

So, with fast user switching enabled, you can log out of the main account. This ensures that no programs or processes from that user will continue running in the background. Most OS X apps are well behaved, and suspend network access when they don't have an active window on-screen, but you'd have to monitor and test this forever to be sure nothing is happening - logging out is simpler to maintain.

Now, you could also replace "account" above with OS and run a virtualization system like Fusion (or Parallels or any other) and only start the guest OS once the host OS has secured everything on a VPN. Depending on the VM software you choose, you also may have control over the network and can turn on and off access even when the guest OS (or OSes) are running. This is basically simulating the extra hardware I initially said I wouldn't consider.

I hope this shows one way you could be more secure while traveling and using a network that you don't trust while minimizing the risk that this will always entail. If someone else owns the network - they own DNS, can log packets, can try man-in-the-middle (MITM) attacks as well as inspect all of your packets deeply to try to determine what is flowing inside the VPN tunnel.

Solution 2:

Here is an approach totally outside of the MacOS X GUI. Hence this approach of the problem won't interfere with any network or VPN setting.

Let's say I want to use an IPSEC VPN (based on the use of 500/udp == isakmp & 50/ip == esp).

Create an ipfw configuration file just allowing the required protocols to build the VPN:

/usr/bin/sudo cat <<____eof >/etc/ipfw.vpn.rules
# VPN trafic contention
#
# DHCP
add 00100 permit udp from any to any src-port bootpc dst-port bootps
# DNS
add 01000 permit udp from me to any dst-port domain
add 01010 permit udp from any to me dst-port domain
# isakmp
add 01050 permit udp from me to any dst-port isakmp
add 01060 permit udp from any to me dst-port isakmp
# esp
add 01100 permit esp from me to any
add 01110 permit esp from any to me
# all other ip go to the central black hole
add 20000 deny ip from any to any
____eof

Check that its syntax is OK:

/usr/bin/sudo /sbin/ipfw -n /etc/ipfw.vpn.rules

Install it in the kernel:

/usr/bin/sudo /sbin/ipfw /etc/ipfw.vpn.rules

Check that your OS can reboot, and get its IP address through the usual DHCP. Check that most of the IP protocols are blocked:

ping www.google.com

Of course, if you want to use a VPN on top of SSL, you will have to adapt this configuration file (isakmp + esp → https).