Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

OpenVPN VPN Server on OS X Server with Mavericks, pfctl, and Tunnelblick

Here are notes on how to build an OpenVPN VPN server on OS X Server with Mavericks, pfctl, and Tunnelblick. Previous OpenVPN server configurations on OS X Server rely upon using the now deprecated natd and ipfw to route VPN traffic, and this solution no longer works. This post describes a replacement using the now preferred pfctl OpenBSD packet filter, which comes with its own NAT. This setup will provide a TLS-based VPN server using 4096-bit certificates and UDP port 443, accessible by any OpenVPN client, especially iOS with the OpenVPN app.


Why would you want to build your own VPN server when OS X server already comes with a VPN service? First, the latest Server.app version 3 breaks VPN to mobile devices. This problem is known and will undoubtedly be fixed soon; however, the VPN technology used by OS X Server is broken and should be avoided altogether (Microsoft’s PPTP: ("PPTP traffic should be considered unencrypted"), or is under a cloud (L2TP/Ipsec with pre-shared keys and MS-CHAPv2 authentication: "IPSEC-PSK is arguably worse than PPTP ever was for a dictionary-based attack vector"). So if you’re going to use OS X Server’s native VPN service, make sure that you use a really long *random* PSK. If you want secure certificate-based VPN between OS X Server and iOS, OpenVPN is the only option.


Furthermore, OS X Server has its firewall turned off by default, assuming that the server lives behind the router's firewall and NAT. Integrating OpenVPN access within a working OS X Server firewall provides greater security than OS X Server's default configuration.


Here’s how to build a VPN Server on OS X Mavericks:


Step 1. Get OpenVPN on OSX and configure it.


1A. I like Macports, so assuming that you've downloaded and installed Xcode from the App Store, installed Macports, run:


sudo port selfupdate

sudo port install openvpn


Step 2. Get Tunnelblick on OS X and configure it.


2A. <http://code.google.com/p/tunnelblick/>


2B. Create your certificates with Easy-RSA


mkdir -p ~/Backups/OpenVPN/easy-rsa-tunnelblick

sudo rsync -va /Applications/Tunnelblick.app/Contents/Resources/easy-rsa-tunnelblick/ ~/Backups/OpenVPN/easy-rsa-tunnelblick

cd ~/Backups/OpenVPN/easy-rsa-tunnelblick

su root

# edit script defaults like KEY_CN == Common Name

vi ./vars


export KEY_SIZE=4096

export KEY_EMAIL="admin@domainname.com"

export KEY_CN=Domainname


mkdir -m go-rwx ./keys

touch ./keys/index.txt

echo 1 > ./keys/serial

. ./vars

./clean-all

./build-ca --pass

./build-key-server server-domainname

# choose a unique Common Name (CN) for each client

./build-key client-domainname

./build-dh

openvpn2 --genkey --secret ./keys/ta.key


# Notes:

# Use the domain name "domainname.com" for the common name

# Contact email "admin@domainname.com" must match name in CA;

# otherwise, there will be some X509 error.


# For the server-domainname cert, use the default common name

# "server-domainname".This must also match the client configuration

# setting:

# tls-remote domainname.com


# Unnecessary if you already signed with ./build-key[-server]

# ./sign-req server-domainname

# ./sign-req client-domainname


cd keys

openssl verify -CAfile ca.crt ca.crt

openssl verify -CAfile ca.crt server-domainname.crt

openssl verify -CAfile ca.crt client-domainname.crt

exit # root


2C. Create a .tblk directory for your VPN server with all the necessary files. I'll demo a tun setup. The LAN here looks like a router on 10.0.1.1 and a OS X Server on 10.0.1.3.


mkdir ~/Desktop/Domainname_tun.tblk

cd ~/Backups/OpenVPN/easy-rsa-tunnelblick/keys

sudo cp -p ca.crt dh4096.pem server-domainname.crt server-domainname.key ta.key ~/Desktop/Domainname_tun.tblk

sudo chown -R username ~/Desktop/Domainname_tun.tblk

cd ~/Desktop/Domainname_tun.tblk

vi config.ovpn


local 10.0.1.3

port 443

proto udp


dev tun

;dev tap


ca ca.crt

cert server-domainname.crt

key server-domainname.key


tls-auth ta.key 0


dh dh4096.pem


server 10.2.0.0 255.255.255.0


;server-bridge 10.0.1.3 255.255.255.0 10.0.1.50 10.0.1.90


;topology subnet


# Push routes to the client to allow it

# to reach other private subnets behind

# the server. Remember that these

# private subnets will also need

# to know to route the OpenVPN client

# address pool (10.2.0.0/255.255.255.0)

# back to the OpenVPN server.

;push "route 10.0.1.0/255.255.255.0"


push "redirect-gateway def1"

push "dhcp-option DNS 8.8.8.8"

;push "dhcp-option DNS 10.0.1.3”

;push "dhcp-option DOMAIN domainname.com."


client-to-client


keepalive 10 120


;cipher BF-CBC


comp-lzo


max-clients 10


user nobody

group nobody


persist-key

persist-tun


ifconfig-pool-persist ipp.txt


verb 3



2D. Forward UDP port 443 from your router to you server at 10.0.1.3. (You may also wish to forward the default OpenVPN port 1194 as well to test other configurations.)


2E. Doubleclick on ~/Desktop/Domainname_tun.tblk within Finder, which should start Tunnelblick and import your configuration. Then,


Tunnelblick>VPN Details ... >Configuration>Settings>Set Nameserver (3.1)


You may also wish to launch this service at boot.


Hit connect and Tunnelblick should launch your OpenVPN server on UDP port 443.


2F. Get OpenVPN from the iOS App store and securely transfer a client.ovpn file to it:


client.ovpn:


####

## Domain Mac UDP client configuration version 2.0

####

client

dev tun

proto udp

remote server.domainname.com 443

redirect-gateway def1

resolv-retry infinite

nobind

;user nobody

;group nobody

persist-key

persist-tun

;ca ca.crt

;cert iPad-domainname.crt

;key iPad-domainname.key

<ca>

-----BEGIN CERTIFICATE-----

MY CERT from ca.crt

-----END CERTIFICATE-----

</ca>

ns-cert-type server

;tls-auth ta.key 1

key-direction 1

<tls-auth>

#

# 4096 bit OpenVPN static key

#

-----BEGIN OpenVPN Static key V1-----

MY CERT from ta.key

-----END OpenVPN Static key V1-----

</tls-auth>

;auth-user-pass

;tls-remote server-domainname

tls-ciphe

r DHE-RSA-AES256-SHA

;cipher BF-CBC

;client-http-proxy 10.0.1.3 3128

comp-lzo

verb 3



Step 3. Configure pfctl on OS X to route your VPN packets correctly.


3.A. Set up sysctl variables at boot:


sudo mkdir -p /Library/Application\ Support/vpn

sudo vi /Library/Application\ Support/vpn/enable-vpn-forward-nat.sh


#!/bin/bash

#

# References: The Book of PF, p. 21; https://forums.openvpn.net/topic11401.html

#

# Sleep is necessary cause network has to be up at the time of following commands

# Otherwise the network will not work at all

#

sleep 15

#

/usr/sbin/sysctl -w net.inet.ip.fw.enable=1

/usr/sbin/sysctl -w net.inet.ip.forwarding=1

/usr/sbin/sysctl -w net.inet6.ip6.forwarding=1


# natd and ipfw are DEPRECATED. Use pfctl(8) instead with nat, e.g.

# nat on en0 from 10.0.0.0/8 to any -> (en0)

###/usr/sbin/natd -interface en0

###/sbin/ipfw add divert natd ip from any to any via en0


sudo vi /Library/LaunchDaemons/net.openvpn.enable-vpn-forward-nat.plist


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >

<plist version="1.0">

<dict>

<key>Label</key>

<string>net.openvpn.enable-vpn-forward-nat</string>

<key>ProgramArguments</key>

<array>

<string>/Library/Application Support/vpn/enable-vpn-forward-nat.sh</string>

</array>

<key>RunAtLoad</key>

<true/>

</dict>

</plist>


sudo launchctl load -w /Library/LaunchDaemons/net.openvpn.enable-vpn-forward-nat.plist


3.B. Integrate a NAT within the existing OS X Server pfctl rules in /etc/pf.conf and set up a launch daemon for pf. The essential pfctl NAT and filter rules are


nat on en0 from 10.0.0.0/8 to any -> (en0)

pass from { lo0, 10.0.0.0/8 } to any keep state


sudo vi /etc/pf.conf


# References for modifications:

# The Book of PF by Peter N.M. Hansteen

# http://hints.macworld.com/article.php?story=20121011004626997

# http://blog.scottlowe.org/2013/05/15/using-pf-on-os-x-mountain-lion/

# http://krypted.com/mac-security/a-cheat-sheet-for-using-pf-in-os-x-lion-and-up/


# Options

set block-policy drop

set fingerprints "/etc/pf.os"

set ruleset-optimization basic

set skip on lo0


# Normalization

# Scrub incoming packets

scrub in all no-df


#

# com.apple anchor point

#

scrub-anchor "com.apple/*"


# Queueing


# Translation


# OpenVPN Server NAT

#

# The Book of PF, p. 21

int_if = "en0" # macro for internal interface

localnet = "10.0.0.0/8"

nat on $int_if from $localnet to any -> ($int_if)


nat-anchor "com.apple/*"

rdr-anchor "com.apple/*"

dummynet-anchor "com.apple/*"

anchor "com.apple/*"

load anchor "com.apple" from "/etc/pf.anchors/com.apple"


# Filtering

lan_server = 10.0.1.3


# Antispoof

antispoof log quick for { lo0 en0 }


# Block by default

block in log


# Allow outgoing traffic from NAT'd { lo0, $localnet }

# The Book of PF, p. 21

pass from { lo0, $localnet } to any keep state


# Block to/from illegal destinations or sources

block in log quick from no-route to any


# Allow critical system traffic

pass in quick inet proto udp from any port 67 to any port 68


# Allow ICMP from home LAN

pass in log proto icmp from $lan_server:network


# Allow outgoing traffic

pass out inet proto tcp from any to any keep state

pass out inet proto udp from any to any keep state


# Internet services

internet_udp_services = "{ https, 500, 1194, 1701, 4500, 5060, 5190, 5297, 5298, 5678, 16384 }"

internet_tcp_services = "{ ssh, smtp, https, 143, 587, 993, 995, 1640, 2170, 2195, 2196, 4190,\

5218, 5223, 5190, 5220, 5222, 5298, 8008, 8443, 8800, 8843 }"

pass in quick inet proto tcp from any to { lo0, $lan_server } port $internet_tcp_services

pass in quick inet proto udp from any to { lo0, $lan_server } port $internet_udp_services


# LAN services: block access, except from localnet

lan_udp_services = "{ 5001 }"

lan_tcp_services = "{ domain, auth, nntp, www, 311, 3128, 5001, 5900:5909, 8118, 8123 }"

pass in quick inet proto tcp from { lo0, $localnet } to { lo0, $lan_server } port $lan_tcp_services

pass in quick inet proto udp from { lo0, $localnet } to { lo0, $lan_server } port $lan_udp_services


sudo vi /Library/LaunchDaemons/net.openbsd.pf.plist


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>Label</key>

<string>net.openbsd.pf.plist</string>

<key>Program</key>

<string>/sbin/pfctl</string>

<key>ProgramArguments</key>

<array>

<string>/sbin/pfctl</string>

<string>-e</string>

<string>-f</string>

<string>/etc/pf.conf</string>

</array>

<key>RunAtLoad</key>

<true/>

<key>ServiceDescription</key>

<string>OpenBSD Packet Filter (pf)</string>

<key>StandardErrorPath</key>

<string>/var/log/pf.log</string>

<key>StandardOutPath</key>

<string>/var/log/pf.log</string>

</dict>

</plist>


sudo launchctl load -w /Library/LaunchDaemons/net.openbsd.pf.plist


3.C. Finally, turn on OS X Server’s adaptive firewall if you like:


sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/serverctl enable service=com.apple.afctl

sudo /Applications/Server.app/Contents/ServerRoot/usr/libexec/afctl -f

Mac mini Server (Mid 2010), OS X Mountain Lion (10.8.2), OS X Server, EyeTV HD, Turbo.264 HD

Posted on Nov 8, 2013 6:44 AM

Reply
71 replies

Nov 8, 2013 8:52 PM in response to essandess

I've discovered that a default block all policy breaks too many services on OS X Server, and the pass rules above are inadequate, so I've reverted to this bare-bones, much more permissive firewall, which still accomplishes NAT for OpenVPN.


# References for modifications:

# http://hints.macworld.com/article.php?story=20121011004626997

# http://blog.scottlowe.org/2013/05/15/using-pf-on-os-x-mountain-lion/

# http://krypted.com/mac-security/a-cheat-sheet-for-using-pf-in-os-x-lion-and-up/


# Options

set block-policy drop

set fingerprints "/etc/pf.os"

set ruleset-optimization basic

set skip on lo0


# Normalization

# Scrub incoming packets

scrub in all no-df


#

# com.apple anchor point

#

scrub-anchor "com.apple/*"

# Queueing


# Translation


# OpenVPN Server NAT

#

# The Book of PF, p. 21

int_if = "en0" # macro for internal interface

localnet = "10.0.0.0/8"

nat on $int_if from $localnet to any -> ($int_if)


nat-anchor "com.apple/*"

rdr-anchor "com.apple/*"

dummynet-anchor "com.apple/*"

anchor "com.apple/*"

load anchor "com.apple" from "/etc/pf.anchors/com.apple"


# Filtering

pass all


If someone knows how to get a reliable "block all" default firewall, please post the pf.conf. You can see the blocked packets using the commands


sudo ifconfig pflog0 create

sudo tcpdump -n -e -ttt -i pflog0

Nov 11, 2013 6:38 AM in response to Kakky07

Still some issues getting packets between VPN clients and services on the VPN Server. Any pointers would be appreciated. IceFloor is a really nice GUI, but also has this issue, so this approach is missing some basic ingredient.


For example, hitting a VNC server while running tcpdump shows VNC packets going to the server on interface tun0, and leaving the VNC server on interface en0. I'm not sure if packets are correctly crossing over between tun0 and en0 -- the result is that services are not available to VPN clients.


More details for those who'd be able to suggest a fix:


I can ping my server from VPN clients, but nmap fails, and VNC clients fail to hit 10.0.1.3:5900. Yet tcpdump shows traffic on port 5900 associated with the VPN client. All this stuff works fine when not on VPN and sitting on the LAN.


ping from VPN:


iPad$ ping -c 3 10.0.1.3

PING 10.0.1.3 (10.0.1.3): 56 data bytes

64 bytes from 10.0.1.3: icmp_seq=0 ttl=64 time=38.303 ms

64 bytes from 10.0.1.3: icmp_seq=1 ttl=64 time=37.200 ms

64 bytes from 10.0.1.3: icmp_seq=2 ttl=64 time=36.507 ms

--- 10.0.1.98 ping statistics ---

3 packets transmitted, 3 packets received, 0% packet loss

round-trip min/avg/max/stddev = 36.507/37.337/38.303/0.740 ms


nmap from VPN client:


iPad$ nmap -p 5900 10.0.1.3

Starting Nmap 5.00 ( http://nmap.org ) at 2013-11-10 11:00 EST

Note: Host seems down. If it is really up, but blocking our ping probes

, try -PN

Nmap done: 1 IP address (0 hosts up) scanned in 3.28 seconds


tcpdump on server interfaces en0 and tun0 during VPN client access:


server$ sudo tcpdump -n -e -ttt -i en0 port 5900

tcpdump: verbose output suppressed, use -v or -vv for full protocol dec

ode

listening on en0, link-type EN10MB (Ethernet), capture size 65535 bytes

00:00:00.000000 c4:2f:03:0b:01:9d > b8:37:5d:de:dc:24, ethertype IPv4 (

0x0800), length 78: 10.0.1.3.5900 > 10.8.0.10.52892: Flags [S.], seq 5

00616894, ack 2287587651, win 65535, options [mss 1460,nop,wscale 4,nop

,nop,TS val 922913452 ecr 546523456,sackOK,eol], length 0

00:00:05.881495 c4:2f:03:0b:01:9d > b8:37:5d:de:dc:24, ethertype IPv4 (

0x0800), length 78: 10.0.1.3.5900 > 10.8.0.10.52892: Flags [S.], seq 5

00616894, ack 2287587651, win 65535, options [mss 1460,nop,wscale 4,nop

,nop,TS val 922918265 ecr 546523456,sackOK,eol], length 0

00:00:04.620650 c4:2c:03:0b:51:9d > b8:c7:5d:d0:dc:14, ethertype


server$ sudo tcpdump -n -e -ttt -i tun0 port 5900


00:00:00.142140 AF IPv4 (2), length 68: 10.8.0.10.53295 > 10.0.1.3.5900: Flags [S], seq 2223347580, win 65535, options [mss 1368,nop,wscale 4,nop,nop,TS val 566298513 ecr 0,sackOK,eol], length 0

Nov 17, 2013 1:55 PM in response to essandess

Thanks to this thread, <http://serverfault.com/questions/478058/routing-traffic-from-vpn-to-different-ne twork-device>, I'm closer to a solution. The server's TCP services ARE all available via the OpenVPN Server's IP, e.g. "ssh user@10.8.0.1" works, as does hitting http://10.8.0.1/, and every other TCP service.


The remaining trick is to set up the routing tables (somewhere—client? server? both?) so that TCP access like "ssh user@10.0.1.3" will just work.


I'd be grateful to any network guru's opinion on the way to do this for OpenVPN clients.

Nov 24, 2013 4:04 AM in response to essandess

Update: I've got this working using the OpenVPN server's IP at 10.8.0.1 with a robust set of pf.conf rules. This is good because VPN on Server.app 3.0.1 remains broken. The following will work if you duplicate client settings to point at 10.8.0.1 while on VPN.


I haven't been able to determine a fix for the problem of being unable to access the server directly from VPN on LAN address 10.0.1.3. This would be very nice, as it would allow transparent access to services (especially LAN DNS) whether on VPN or not. If anyone can solve this issue, please post. In the meantime, simply access services via 10.8.0.1 while on the VPN.


Because NAT now operates within a set of pf.conf rules, I'll just post a full working pf.conf file. This may be useful in its own right, as it contains rules to adaptively block bruteforce attacks, and uses block tables downloaded from EmergingThreats.net Open rulesets. The pf.conf is used with three launch daemons: net.openbsd.pf.plist (above) to enable PF, net.openbsd.pf.brutexpire.plist to expire bruteforce table entries older than one week, and net.emergingthreats.blockips.plist to download EmergingThreats.net database twice a day. Here's a working example. The basic NAT required for OpenVPN on Mavericks is:


nat on en0 inet from { tun0/24 en0:network } to any -> (en0)


I've found that I've had to be somewhat permissive on the LAN so as not to break things like bonjour, DNS, AirPlay, and so forth. This is okay, as I'm located on a NAT behind a router firewall. Be careful if the server has direct inernet access. If anyone has a working Mavericvks ruleset that locks things down tighter, please post.


sudo vi /etc/pf.conf


# References for modifications:

# The Book of PF by Peter N.M. Hansteen, p. 21

# http://ikawnoclast.com/security/mac-os-x-pf-firewall-avoiding-known-bad-guys/

# http://support.apple.com/kb/HT5519?viewlocale=en_US&locale=en_US

# http://blog.scottlowe.org/2013/05/15/using-pf-on-os-x-mountain-lion/

# http://krypted.com/mac-security/a-cheat-sheet-for-using-pf-in-os-x-lion-and-up/


# Options

set block-policy drop

set fingerprints "/etc/pf.os"

set ruleset-optimization basic

set skip on lo0


# Normalization

# Scrub incoming packets

scrub in all no-df


#

# com.apple anchor point

#

scrub-anchor "com.apple/*"


# Queueing


# Translation


# OpenVPN Server NAT

#

# The Book of PF, p. 21

int_if = "en0"

tun_if = "tun0"

nat on $int_if inet from { $tun_if/24 $int_if:network } to any -> ($int_if)



nat-anchor "com.apple/*"

rdr-anchor "com.apple/*"

dummynet-anchor "com.apple/*"

anchor "com.apple/*"

load anchor "com.apple" from "/etc/pf.anchors/com.apple"


# Filtering



# Pass by default

pass all



# Antispoof

# This breaks ping, DNS on OS X Server

#antispoof log quick for { lo0 $int_if } inet



# Block to/from illegal destinations or sources

block in log quick from no-route to any

block in log quick from urpf-failed to any

# This is observed on OS X

#block in log quick on $int_if from any to 255.255.255.255



# Local net

pass quick from { lo0 $int_if } to any



# Whitelist

#table <whitelist> const { }

#pass in quick from <whitelist>



# Block brute force attacks

table <bruteforce> persist

block in log quick from <bruteforce>


# Emerging Threats Open Ruleset, http://rules.emergingthreats.net/fwrules/


# http://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt

table <emerging_threats> persist file "/usr/local/etc/emerging-Block-IPs.txt"

block log quick from <emerging_threats> to any


# http://rules.emergingthreats.net/blockrules/compromised-ips.txt

table <compromised_ips> persist file "/usr/local/etc/compromised-ips.txt"

block log quick from <compromised_ips> to any


# http://rules.emergingthreats.net/blockrules/rbn-ips.txt

table <rbn_ips> persist file "/usr/local/etc/rbn-ips.txt"

block log quick from <rbn_ips> to any


# http://rules.emergingthreats.net/blockrules/rbn-malvertisers-ips.txt

table <rbn_malvertisers_ips> persist file "/usr/local/etc/rbn-ips.txt"

block log quick from <rbn_malvertisers_ips> to any



# ICMP

icmp_types = "echoreq"

pass inet proto icmp from $int_if:network to any icmp-type $icmp_types

pass inet proto icmp from any to $int_if icmp-type $icmp_types



# allow out the default range for traceroute(8):

# "base+nhops*nqueries-1" (33434+64*3-1)

pass out on $int_if inet proto udp from any to any port 33433 >< 33626



# Allow critical system traffic

pass in quick inet proto udp from any port bootps to any port bootpc



# LAN services: block access, except from localnet

lan_udp_services = "{ domain, 5001, postgresql }"

lan_tcp_services = "{ domain, auth, nntp, www, \

311, 3128, 5001, 5900:5909, privoxy, postgresql, \

8123, 8180, 8181 }"

block in inet proto tcp from any to { lo0 $int_if } port $lan_tcp_services

block in inet proto udp from any to { lo0 $int_if } port $lan_udp_services

pass in quick inet proto udp from { lo0 $tun_if/24 $int_if:network } to { lo0 $int_if } port $lan_udp_services

pass in quick inet proto tcp from { lo0 $tun_if/24 $int_if:network } to { lo0 $int_if } port $lan_tcp_services



# Internet services

internet_udp_services = "{ https, 500, openvpn, \

1701, 4500, 5060, 5190, 5297, 5298, 5678 }"

internet_tcp_services = "{ 995, 1640, eyetv, 2195, \

2196, 4190, 5218, 5223, 5190, 5220, 5222, 5298, \

8008, 8443, 8800, 8843 }"

pass in inet proto udp from any to { lo0 $int_if } port $internet_udp_services

pass in inet proto tcp from any to { lo0 $int_if } port $internet_tcp_services


# ssh really restrictive

pass in inet proto tcp from any to { lo0 $int_if } port ssh \

keep state (max-src-conn 5, max-src-conn-rate 5/2, \

overload <bruteforce> flush global)


# web, mail more restrictive

pass in inet proto tcp from any to { lo0 $int_if } \

port { smtp, https, imap, submission, imaps } \

keep state (max-src-conn 100, max-src-conn-rate 15/5, \

overload <bruteforce> flush global)


sudo vi /Library/LaunchDaemons/net.openbsd.pf.brutexpire.plist


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>Label</key>

<string>net.openbsd.pf.brutexpire.plist</string>

<key>Program</key>

<string>/sbin/pfctl</string>

<key>ProgramArguments</key>

<array>

<string>/sbin/pfctl</string>

<string>-t</string>

<string>bruteforce</string>

<string>-T</string>

<string>expire</string>

<string>604800</string>

</array>

<key>RunAtLoad</key>

<true/>

<key>StartInterval</key>

<integer>604800</integer>

<key>ServiceDescription</key>

<string>OpenBSD Packet Filter bruteforce table expiration</string>

<key>StandardErrorPath</key>

<string>/var/log/pf.log</string>

<key>StandardOutPath</key>

<string>/var/log/pf.log</string>

</dict>

</plist>


sudo vi /Library/LaunchDaemons/net.emergingthreats.blockips.plist


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>Label</key>

<string>net.emergingthreats.blockips.plist</string>

<key>Program</key>

<string>/bin/bash</string>

<key>ProgramArguments</key>

<array>

<string>/bin/bash</string>

<string>-c</string>

<string>/usr/bin/curl http://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt -o /tmp/emerging-Block-IPs.txt &amp;&amp; /usr/bin/install -m 644 -g admin -S /tmp/emerging-Block-IPs.txt /usr/local/etc/emerging-Block-IPs.txt &amp;&amp; /bin/rm /tmp/emerging-Block-IPs.txt ; /usr/bin/curl http://rules.emergingthreats.net/blockrules/compromised-ips.txt -o /tmp/compromised-ips.txt &amp;&amp; /usr/bin/install -m 644 -g admin -S /tmp/compromised-ips.txt /usr/local/etc/compromised-ips.txt &amp;&amp; /bin/rm /tmp/compromised-ips.txt ; /usr/bin/curl http://rules.emergingthreats.net/blockrules/rbn-ips.txt -o /tmp/rbn-ips.txt &amp;&amp; /usr/bin/install -m 644 -g admin -S /tmp/rbn-ips.txt /usr/local/etc/rbn-ips.txt &amp;&amp; /bin/rm /tmp/rbn-ips.txt ; /usr/bin/curl http://rules.emergingthreats.net/blockrules/rbn-malvertisers-ips.txt -o /tmp/rbn-malvertisers-ips.txt &amp;&amp; /usr/bin/install -m 644 -g admin -S /tmp/rbn-malvertisers-ips.txt /usr/local/etc/rbn-malvertisers-ips.txt &amp;&amp; /bin/rm /tmp/rbn-malvertisers-ips.txt ; /sbin/pfctl -f /etc/pf.conf</string>

</array>

<key>RunAtLoad</key>

<true/>

<key>StartInterval</key>

<integer>43200</integer>

<key>ServiceDescription</key>

<string>Emerging Threats PF Update</string>

<key>StandardErrorPath</key>

<string>/var/log/pf.log</string>

<key>StandardOutPath</key>

<string>/var/log/pf.log</string>

</dict>

</plist>


As usual, load the pf rules and load for for launch at boot using:


sudo pfctl -f /etc/pf.conf

sudo launchctl load -w /Library/LaunchDaemons/net.openbsd.pf.brutexpire.plist

sudo launchctl load -w /Library/LaunchDaemons/net.emergingthreats.blockips.plist


Anyone wunning OS X Server will also want to enable the adaptive firewall using the commands describes here, http://support.apple.com/kb/HT5519?viewlocale=en_US&locale=en_US


sudo pfctl -f /etc/pf.conf

sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/serverctl enable service=com.apple.afctl

sudo /Applications/Server.app/Contents/ServerRoot/usr/libexec/afctl -c

sudo /Applications/Server.app/Contents/ServerRoot/usr/libexec/afctl -f

Dec 13, 2013 2:59 AM in response to essandess

Thanks for posting this.


Question: Is it really necessary to "get and configure OpenVPN" (step 1)?


Unless I'm missing something, OpenVPN is only used for "openvpn2 --genkey --secret ./keys/ta.key"


Otherwise, OpenVPN is invoked from Tunnelblick. Tunnelblick includes binaries of two or more versions of OpenVPN and uses them (not "openvpn2").


After Tunnelblick has been installed (by double-clicking the Tunnelblick icon in the disk image), you can find the OpenVPN binaries in subfolders of

/Applications/Tunnelblick.app/Contents/Resources/openvpn


For example, in Tunnelblick 3.4beta16, there are two folders:

/Applications/Tunnelblick.app/Contents/Resources/openvpn/openvpn-2.2.1

and

/Applications/Tunnelblick.app/Contents/Resources/openvpn/openvpn-2.3.2


Each of those folders has a (32/64/Intel/PPC) binary of OpenVPN named "openvpn" that is the version indicated by the name of its enclosing folder.


So you could use

/Applications/Tunnelblick.app/Contents/Resources/openvpn/openvpn-2.2.1/openvpn --genkey --secret ./keys/ta.key

Dec 13, 2013 5:33 AM in response to jkbull

jkbull, Thank you for pointing this out, and also thanks for all your work on Tunnelblick. Another factor to point out is that the OpenVPN Macport stopped distributing EasyRSA to mirror that same practice with the OpenVPN distro (not sure why). That makes it important that EasyRSA continued to be included with the Tunnelblick download.


Do you know if Mavericks includes kernel support for TAP a interface? This may (?) solve the issue I've identified above with VPN clients not receiving return packets addressed to the server via its LAN IP address. I'm still not sure if this is a configuration issue or a bug with OpenVPN on Mavericks. If you or others stand up your own OpenVPN server, I'd be very curious to hear if you also see this problem.


It would be nice if Apple just upgraded their VPN service to a secure certificate-based technology. I'm constantly shut out of Apple's native VPN either because some upgrade breaks it, or the necessary L2TP ports are blocked on the client network. Streaming everything over TLS on https port 443 have never broken or been blocked.

Dec 13, 2013 5:47 AM in response to essandess

Here's a bandwidth-efficient plist that uses wget -N to only download the Emerging Threats blocklist if they've updated them, rather than blindly doing a download whether needed or not. You need wget from macports. I'll post related plists in another thread that lock down the kernel, OS, and clients from trackers, malware, spammers, and attackers using a regularly updated hosts file and proxy.pac file. This protection extends to VPN clients, another reason to stand up a VPN server.


$ sudo port install wget


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>Label</key>

<string>net.emergingthreats.blockips.plist</string>

<key>Program</key>

<string>/bin/bash</string>

<key>ProgramArguments</key>

<array>

<string>/bin/bash</string>

<string>-c</string>

<string>/bin/mkdir -p /usr/local/etc ; /opt/local/bin/wget -N -P /usr/local/etc http://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt ; /opt/local/bin/wget -N -P /usr/local/etc http://rules.emergingthreats.net/blockrules/compromised-ips.txt ; /opt/local/bin/wget -N -P /usr/local/etc http://rules.emergingthreats.net/blockrules/rbn-ips.txt ; /opt/local/bin/wget -N -P /usr/local/etc http://rules.emergingthreats.net/blockrules/rbn-malvertisers-ips.txt ; /sbin/pfctl -f /etc/pf.conf</string>

</array>

<key>RunAtLoad</key>

<true/>

<key>StartInterval</key>

<integer>43200</integer>

<key>ServiceDescription</key>

<string>Emerging Threats PF Update</string>

<key>StandardErrorPath</key>

<string>/var/log/pf.log</string>

<key>StandardOutPath</key>

<string>/var/log/pf.log</string>

</dict>

</plist>

Dec 13, 2013 6:14 AM in response to essandess

As far as I know, Mavericks does not include support for tap devices.


OS X 10.6.8 and higher do include a "utun" tun device. When it is released, OpenVPN version 2.3 will include support for it, and will use the "utun" device instead of the tun device by default. For now, Tunnelblick will continue to load the tun driver dynamically when a tun connection is specified in a configuration, but that tun device will be unused. At some point I will check and not load the tun driver if a "utun" device will be used.


I intend to include "easy-rsa" in Tunnelblick; the idea is to have Tunnelblick include everything you need except the OpenVPN configuration and encryption info.


By the way, Tunnelblick's "Utilities" panel includes a button to open a Terminal window and cd to the easy-rsa folder.


Separately, the next release of Tunnelblick will probably include a consistently-named link to the "default" OpenVPN folder (the folder containing the earliest version of OpenVPN) so scripts such as yours can use a consistent path to get to the default binary of OpenVPN, independent of the versions of OpenVPN that are included in Tunnelblick.

Dec 13, 2013 6:53 AM in response to jkbull

Thanks again. Speaking of interfaces, is there an easy way for Tunnelblick to bring up tun0 at boot, thereby avoiding hardcoding the network 10.8.0/24 in pf.conf? Right now, referring to "tun0" in pf.conf causes pfctl -e to fail at boot because tun0 hasn't yet been created. Hardcoding the tun0 network isn't too bad, but it would be nice to tell the firewall at boot time that we intend to use tun0.

Dec 13, 2013 7:09 AM in response to essandess

Loading the tun driver "at boot" is tricky.


The normal way to do it is to put the tun kext into a system folder (and even that is tricky; where you put it depends on what version of OS X you have -- Mavericks changed things a bit). However, that means that you can't load other (competing) drivers -- such as Cisco's tun driver.


Tunnelblick does not do it that way; instead, Tunnelblick loads the tun and tap drivers dynamically, as needed, just before starting OpenVPN. (This is done by Tunnelblick's "openvpnstart" helper".) After a disconnection, Tunnelblick unloads the drivers. If you have Tunnelblick set to connect a configuration when the system starts, it adds a launchd item to run Tunnelblick's "openvpnstart" helper. That program then loads the tun and/or tap drivers dynamically.


Be careful loading tun/tap kexts: there are three different versions of each kext included in Tunnelblick: one for OS X 10.4 and 10.5 (named "XXX-20090913.kext", one for 10.6 through 10.8 named "XXX.kext", and one for OS X 10.9 and up (named "XXX-signed.kext"). (The XXX is either "tun" or "tap".) You need to use the right one for the version of OS X that is running.

Dec 19, 2013 5:06 AM in response to jkbull

Thanks for all this! i have now a running server setup. But I also have the problem, that I have to access the services of the server by the VPN's IP (10.2.0.1) and not the IP of the local LAN (10.0.1.10). I am also not able to access another server in the LAN (10.0.1.11). Should this be supposed to work with the config described here?

Dec 19, 2013 1:48 PM in response to essandess

Hi essandess, this looks very interesting (your post here about emergingthreats.net firewire rules.


But I don't see how that script is doing anything to actually incorporate that info from
http://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt
into the active pfctl rules.



essandess wrote:


Here's a bandwidth-efficient plist that uses wget -N to only download the Emerging Threats blocklist if they've updated them, rather than blindly doing a download whether needed or not. You need wget from macports. I'll post related plists in another thread that lock down the kernel, OS, and clients from trackers, malware, spammers, and attackers using a regularly updated hosts file and proxy.pac file. This protection extends to VPN clients, another reason to stand up a VPN server.


$ sudo port install wget


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>Label</key>

<string>net.emergingthreats.blockips.plist</string>

<key>Program</key>

<string>/bin/bash</string>

<key>ProgramArguments</key>

<array>

<string>/bin/bash</string>

<string>-c</string>

<string>/bin/mkdir -p /usr/local/etc ; /opt/local/bin/wget -N -P /usr/local/etc http://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt ; /opt/local/bin/wget -N -P /usr/local/etc http://rules.emergingthreats.net/blockrules/compromised-ips.txt ; /opt/local/bin/wget -N -P /usr/local/etc http://rules.emergingthreats.net/blockrules/rbn-ips.txt ; /opt/local/bin/wget -N -P /usr/local/etc http://rules.emergingthreats.net/blockrules/rbn-malvertisers-ips.txt ; /sbin/pfctl -f /etc/pf.conf</string>

</array>

<key>RunAtLoad</key>

<true/>

<key>StartInterval</key>

<integer>43200</integer>

<key>ServiceDescription</key>

<string>Emerging Threats PF Update</string>

<key>StandardErrorPath</key>

<string>/var/log/pf.log</string>

<key>StandardOutPath</key>

<string>/var/log/pf.log</string>

</dict>

</plist>

OpenVPN VPN Server on OS X Server with Mavericks, pfctl, and Tunnelblick

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.