Setting up OpenVPN for Android phone (NAT & ZBFW on Cisco 1801)
I’ve been looking to get a decent “native” VPN setup on my android phone for a while. There doesn’t seem to be native support for IPSEC VPNs terminating on Cisco routers. Long request topic for it [here] although ASA8.4(1) supposedly has support I haven’t had a chance to test it yet.
For the following I used:
- Rooted HTC Desire
- CyanogenMod 7.0 (built in OpenVPN support 😀 ) http://www.cyanogenmod.com/
- Ubuntu 10.10
- OpenVPN 2.1.0
- Cisco 1801 running 15.0(1)M using zone based firewall
Setup the OpenVPN server
Since I was new to OpenVPN I followed the Ubuntu wiki found [here]. One really cool feature of OpenVPN is tls-auth you can read a bit more about it [here]. Basically if the OpenVPN server receives a packet that doesn’t have a HMAC generated by the ta.key it will just drop the packet. Makes it pretty difficult to port scan for 🙂
For the most part it worked perfectly but I added a couple of extra lines to the server config below. I found it useful to run the server via
sudo openvpn --config server.conf --script-security 2 when I was doing the initial testing.
My server.conf file:
local 10.1.1.10 ## ip/hostname of server
port 12345 ## My Custom port
dev tap0 ## If you need multiple tap devices, add them here
up “/etc/openvpn/up.sh br0”
down “/etc/openvpn/down.sh br0”
#certificates and encryption
key server.key # This file should be kept secret
tls-auth ta.key 0 # This file is secret
cipher BF-CBC # Blowfish (default)
server-bridge 10.1.1.10 255.255.255.0 10.1.1.240 10.1.1.250
push “dhcp-option DNS 184.108.40.206”
push “dhcp-option DOMAIN m00nie.com”
max-clients 10 ## set this to the max number of clients that should be connected at a time
#log and security
keepalive 10 120
script-security 2 ## This needed added
verb 4 ##Changed the logging level
Setup the OpenVPN client on the phone
Create the client cert
cd /etc/openvpn/easy-rsa/ ## move to the easy-rsa directory
source ./vars ## execute the vars file
./pkitool client ## create a cert and key named “client”
Android only seems to accept .p12 filetype certificates. You can either generate .p12 certs using this command below then copy them to your sdcard and then use the Location & Security settings > Install from SD card option to install them or just put the .crt files on a webserver and browse to them (the browser seems to accept .crt files) and it will add them to the secure store for you.
To make .p12 cert
openssl pkcs12 -export -in client.crt -inkey client.key -certfile ca.crt -out client.p12
When you copy the files to your sdcard be sure to copy the ta.key file too and note is location. If its on the sdcard its final location will be /mnt/sdcard/”somefolder”/ta.key
Now we can configure the VPN as follows. (Click for larger images)
The main config:
Menu > Advanced OpenVPN Settings:
At the moment there is no gui setting to configure tls-auth but they did give us the Extra arguments option 😀 In here I added
–tls-auth /mnt/sdcard/VPN/ta.key 1 –explicit-exit-notify 2
When testing I had this error logged on the OpenVPN server:
read UDPv4 [ECONNREFUSED]: Connection refused (code=111)
I had to use the tap device rather than the tun to make the VPN connect and stop this error
Port forward & ZBFW on the router
Since at the moment we still have NAT we have to forward ports.
ip nat inside source static udp <ubuntu server IP> <server port> interface <outside address> <some port>
so mine was
ip nat inside source static udp 10.1.1.10 12345 interface dialer 0 12345
Now we can see the static translation:
Moons-Router#show ip nat translations
Pro Inside global Inside local Outside local Outside global
udp 192.168.1.1:12345 10.1.1.10:12345 — —
Now the port is forwarding to the OpenVPN server but my zone based firewall config is dropping the packets.
Apr 13 18:14:04.136: %FW-6-DROP_PKT: Dropping udp session 172.16.1.1 10.1.1.10:12345 on zone-pair out-in class class-default due to DROP action found in policy-map with ip ident 0
At the moment there is no explicit zone-pair for outside to inside so the default is deny all. Lets define one
Enter configuration commands, one per line. End with CNTL/Z.
m00nies_router(config)#access-list 199 permit udp any any eq 12345
m00nies_router(config)#class-map type inspect match-all OPENVPN
m00nies_router(config-cmap)# match access-group 199
m00nies_router(config)#policy-map type inspect OPENVPN_POLICY
m00nies_router(config-pmap)#class type inspect OPENVPN
m00nies_router(config)#zone-pair security out-in source out-zone destination in-zone
m00nies_router(config-sec-zone-pair)# service-policy type inspect OPENVPN_POLICY
First off we classify the traffic we want the allow it to pass but log it. Next we apply that policy to a zone pair. Theres more info about configuring ZBFW [here]. Below we can see the default that catches all other traffic is still drop.
m00nies_router#show policy-map type inspect OPENVPN_POLICY
Policy Map type inspect OPENVPN_POLICY
Now we can try our VPN access.
It passes the router ok
Apr 13 18:31:00.085: %FW-6-PASS_PKT: (target:class)-(out-in:OPENVPN) Passing udp pkt 172.16.1.1:52585 => 10.1.1.10:12345 with ip ident 0
And the OpenVPN server logs confirm it works ok too. Its been very stable on both 2 and 3G.