Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I've been able to deny all connections to external networks unless my OpenVPN connection is active using pf.conf. However, I lose Wi-Fi connectivity if the connection is broken by closing and opening the laptop lid or toggling Wi-Fi off and on again.

  • I'm on Mac OS 10.8.1.
  • I connect to the Web via Wi-Fi (from varying locations, including Internet cafés).
  • The OpenVPN connection is set up with Viscosity.

I have the following packet filter rules set up in /etc/pf.conf

# Deny all packets unless they pass through the OpenVPN connection
wifi=en1
vpn=tun0

block all

set skip on lo
pass on $wifi proto udp to [OpenVPN server IP address] port 443
pass on $vpn

I start the packet filter service with sudo pfctl -e and load the new rules with sudo pfctl -f /etc/pf.conf.

I have also edited /System/Library/LaunchDaemons/com.apple.pfctl.plist and changed the line <string>-f</string> to read <string>-ef</string> so that the packet filter launches at system startup.

This all seems to works great at first: applications can only connect to the web if the OpenVPN connection is active, so I'm never leaking data over an insecure connection.

But, if I close and reopen my laptop lid or turn Wi-Fi off and on again, the Wi-Fi connection is lost, and I see an exclamation mark in the Wi-Fi icon in the status bar. Clicking the Wi-Fi icon shows an "Alert: No Internet connection" message:

No Internet connection message

To regain the connection, I have to disconnect and reconnect Wi-Fi, sometimes five or six times, before the "Alert: No Internet connection" message disappears and I'm able to open the VPN connection again. Other times, the Wi-Fi alert disappears of its own accord, the exclamation mark clears, and I'm able to connect again. Either way, it can take five minutes or more to get a connection again, which can be frustrating.

Removing the line block all resolves the problem (but allows insecure connections), so it seems there's a service I'm blocking that Apple requires in order to regain and confirm a Wi-Fi connection. I have tried:

  • Enabling icmp by adding pass on $wifi proto icmp all to pf.conf
  • Enabling DNS resolution by adding pass on $wifi proto udp from $wifi to any port 53
  • Trying to learn more by logging blocked packets (by changing block all to block log all), but logging seems to be disabled under OS X, because doing sudo tcpdump -n -e -ttt -i pflog0 to see the log results in "tcpdump: pflog0: No such device exists".

None of this helps re-establish a Wi-Fi connection any faster.

What else can I do to determine what service needs to be available to regain Wi-Fi connectivity, or what rule should I add to pf.conf to make Wi-Fi reconnections more reliable?

share|improve this question
add comment

2 Answers

up vote 6 down vote accepted

By monitoring network connections using Little Snitch, I've found that Apple uses the mDNSResponder app in the background to check if the Wi-Fi connection is available. mDNSResponder sends UDP packets to nameservers to check connectivity and resolve hostnames to IPs.

Changing the UDP rule I had previously to allow all UDP packets over Wi-Fi allows mDNSResponder to connect, which means Wi-Fi now reconnects first time after a disconnection. In case it helps others in future, my final pf.conf including Apple's default rules for Mountain Lion looks like this:

#
# com.apple anchor point
#
scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"as
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"

#
# Allow connection via Viscosity only
#
wifi=en1 #change this to en0 on MacBook Airs and other Macs without ethernet ports
vpn=tun0
vpn2=tap0

block all

set skip on lo          # allow local traffic

pass on p2p0            #allow AirDrop
pass on p2p1            #allow AirDrop
pass on p2p2            #allow AirDrop
pass quick proto tcp to any port 631    #allow AirPrint

pass on $wifi proto udp # allow only UDP packets over unprotected Wi-Fi
pass on $vpn            # allow everything else through the VPN (tun interface)
pass on $vpn2           # allow everything else through the VPN (tap interface)

This means that data can now be leaked over Wi-Fi by the small number of applications that use the UDP protocol, unfortunately, such as ntpd (for time synchronisation) and mDNSResponder. But this still seems better than allowing data to travel unprotected over TCP, which is what the majority of applications use. If anyone has any suggestions to improve on this setup, comments or further answers are welcome.

share|improve this answer
    
This is something I've casually been interested in, seeing your results has inspired me to go home and try it! thanks! –  jakev Sep 5 '12 at 22:52
    
@SixSlayer It seems to work pretty well! I have Viscosity set up to autoconnect on startup and on dropped connections, which makes the whole thing pretty much seamless. Main thing to note is that pf.conf and com.apple.pfctl.plist get reset to the default after OS updates, apparently, so it's worth keeping a backup of both. –  Nick Sep 5 '12 at 22:53
    
IMHO the UDP thing is kind of a bummer. I'm not a network guy but this kinda thing helps me learn, and I have a fascination with having control over these kinds of details. I'll spend some time looking for a work around, but if anyone beats me to it, just as well. –  jakev Sep 6 '12 at 1:51
    
this is awesome - exactly what I was looking for. Thank you! –  keo Sep 7 '12 at 19:04
    
Have you maybe managed to have many OpenVPN connections open at the same time, and routing through them in parallel? (to gain and add up bandwidth) –  keo Sep 7 '12 at 19:04
show 5 more comments

This gave me sufficient background info to make the big leap and use pf.conf. Here's what I use on my 10.8 to make it reconnect after the VPN connection drops :

(I only use ethernet but you can change $lan for $wifi and it should work)

lan=en0
wifi=en1
vpn=tun0
block all
set skip on lo
pass on $lan proto { udp,tcp } to 8.8.8.8
pass on $lan proto tcp to vpn.btguard.com port 1194
pass on $vpn
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.