HOWTO: Simply Connect Mac OSX to a dd-wrt OpenVPN Server on TCP Port 443
If you find yourself on a really restrictive network but still want to connect to a remote VPN, consider this solution. It allows you to connect a Mac OS X OpenVPN client to an OpenVPN server using a static key. I figured it out using a combination of webistes, including dd-wrt's OpenVPN wiki, OpenVPN's documentation, and tinyapps.org.
This solution can probably be way more automated using tunnelblick, but I'm alright with running a couple scripts (for now) to get my VPN going. Here's what you'll need:
Network - No web proxy or a proxy that allows persistent connections.
Server - A Linksys WRT54GL router - dd-wrt.v24_vpn_generic.bin (follow instructions on the website to flash from scratch.)
Client - MacOS X Snow Leopard - OpenVPN v2.1.3 - tuntap_20090913.tar.gz - lzo 2.02
I downloaded all of these then compiled and installed them myself. Not because I'm leet, but because the network I was on blocked sync and I couldn't use MacPorts. So go download and compile these or use MacPorts.
First thing is first, I changed the subnet on my wireless router. I hate the 192.168 subnet; it's aesthetically unappealing and overused. Now 172.20.0.x is something pretty. Let's go with that.
We will not be using dd-wrt's GUI to enable or configure OpenVPN, but rather startup and firewall scripts in the /tmp directory. I also avoid using the default protocol and port (udp, 1194) and go with tcp port 443.
Here's a step by step
Server - Generate the static key: openvpn --genkey --secret static.key - Cat that key and place it in your clipboard - Open up dd-wrt's admin webpage, and go to Administration -> Commands. Paste the following:
openvpn --mktun --dev tap0 brctl addif br0 tap0 ifconfig tap0 0.0.0.0 promisc up echo " -----BEGIN OpenVPN Static key V1----- [Insert your static key here] -----END OpenVPN Static key V1----- "> /tmp/static.key ln -s /usr/sbin/openvpn /tmp/myvpn /tmp/myvpn --dev tap0 --secret /tmp/static.key --comp-lzo --port 443 --proto tcp-server --verb 3 --daemon
- Save that to Startup Scripts - Next, back in the blank box, we'll place the code for the firewall and NAT:
iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Client You will be creating 2 scripts and one key: openvpn.conf, startvpn.sh and secret.key. Place them in ~/Library/openvpn.
For your key, copy/paste your static.key from the dd-wrt router into a file named secret.key. Save the following two scripts as openvpn.conf and startvpn.sh, respectively. Don't forget to make startvpn.sh executable.
#openvpn.conf remote my.vpn.external.ip port 443 dev tap0 secret static.key proto tcp-client comp-lzo
Now this part is kinda ghetto. I want to route all my traffic through the VPN but I was unable to get route-gateway and redirect-gateway to work inside of openvpn.conf. I decided to save time and just do it through the startup script instead.
kill -9 `ps aux | grep openvpn.conf |grep config| awk '{ print $2 }'` openvpn2 --config openvpn.conf --script-security 2 & sleep 3
# Change your vpn server and internal subnet here vpnserver='my.external.vpn.ip' vpngw='172.20.0.1'
# If you use DHCP supplied DNS Servers, leave this as true changedns=true
previousgw=`cat ./gateway 2> /dev/null` currentgw=`netstat -nr | grep '^default' | awk '{ print $2 }'`
if [ -f ./gateway ] then # Set it back to the regular gateway route delete default route delete $vpnserver $previousgw route add default $previousgw rm ./gateway
echo gateway set back
if [ $changedns ]; then networksetup -setdnsservers Ethernet empty networksetup -setdnsservers Airport empty echo dns reset fi else # Set it to the VPN gw route add $vpnserver $currentgw sleep 7 route delete default route add default $vpngw echo $currentgw > ./gateway
# Tunnel your DNS Requests too. if [ $changdns ]; then networksetup -setdnsservers Ethernet $vpngw networksetup -setdnsservers Airport $vpngw echo new dns set fi fiCheck out this post on updating client-side DNS servers if you'd like to update all of your adapters instead of the ones most often used (Ethernet and Airport.)
Or something like that... Simple, right? ;)