VPN on PlayBook

I want to be able to access my files on the move, wherever I am. Whilst cloud services such as dropbox (www.dropbox.com) are fantastic, I have a few too many files to use these exclusively.

Also, many websites don’t use SSL for all their data, only for authentication. Whilst this protects your password, it doesn’t protect your session token after login. Thus anyone can sniff and steal it.

So, I decided to try to get my new toy – a BlackBerry PlayBook – working on my VPN. Until now I have been using my Cisco ASA as a VPN endpoint, but I don’t like how VPNs and ACLs work together on the ASA, and so decided to roll a new VPN in my DMZ. I used strongswan, and it was fantastically easy.

So my network looks like this:-

internet -- ASA -- extranet -- PIX -- dmz
                 |
             internal network

The extranet is a network which allows pretty-much unfettered access through the ASA, whereas the DMZ has a lot of controls put on it by both the PIX and the ASA. Note that the PIX is oriented so the external interface is facing the DMZ. IP address assignments are (all /24 subnets):-

  • ASA: outside=public static IP(outside_ip2), internal=10.1.1.1, extranet=10.1.98.1
  • PIX: extranet=10.1.98.2, dmz=10.1.99.2
  • ipsec server in dmz at: 10.1.99.10
  • pool of virtual IPs for ipsec clients: 10.1.100.0
  • dns server in internal at: 10.1.1.53

The VPN endpoint is on the dmz.

Step 1: Install and setup strongswan
I won’t cover installation, as it’s very distro-specific, however a few pointers:-

  1. Make sure you get the right kernel modules. I had a problem with this for a while. You need the following:-
    • PF_KEY sockets
    • IP: AH transformation
    • IP: ESP transformation
    • IP: IPComp transformation
    • IP: IPsec transport mode
    • IP: IPsec tunnel mode
    • IP: IPsec BEET mode
    • Network packet filtering framework (Netfilter)
      • Advanced netfilter configuration [Note: If you set this to N, you’ll get lots of the below for free – may be an easier way to do things]
      • Core Netfilter Configuration [M]
      • Netfilter connection tracking support [M]
      • (you may want to add all the protocols you’ll want to support) [M]
      • Netfilter Xtables support [M]
      • “esp” match support [M]
      • IPsec “policy” match support [M]
      • “state” match support [M]
    • IP: Netfilter Configuration
      • IPv4 connection tracking support [M]
      • IP tables support [M]
      • Packet filtering [M]
      • REJECT target support [M]
      • LOG target support [M]
  2. Install strongswan. I shall assume the /etc files go in the normal places.
  3. /etc/ipsec.conf
    config setup
    	# Some standard settings. We're not going to use certs, so I don't care about CRLs
    	crlcheckinterval=180
    	strictcrlpolicy=no
    	plutostart=no
    
    conn %default
    	ikelifetime=60m
    	keylife=20m
    	rekeymargin=3m
    	keyingtries=1
    	keyexchange=ikev2
    	dpdaction=clear           #What to do in the event of a dead peer
    	dpddelay=300s
    
    conn rem
    	left=10.1.99.10           #The IP of my IPSec endpoint
    	leftsubnet=0.0.0.0/0    #This will tell the client to send everything through me
    	leftauth=psk               #The server will auth to the client with a PSK
    	#leftfirewall=yes          #This could be set to auto modify iptables rules
    	right=%any
    	rightsourceip=10.1.100.0/24  #A pool of IPs to assign the client
    	rightauth=eap-mschapv2      #The client will auth with EAP-MSCHAPv2
    	righsendcert=never
    	eap_identity=%any
    	auto=start
  4. /etc/strongswan.conf [generally standard, but I added a couple of lines, as shown]
    charon {
    	dns1 = 10.1.1.53
    	dns2 = 87.194.255.154
    ...
  5. /etc/ipsec.secrets The PSK is for the server to auth to the client (but also IIRC needs to be known by the client even if it’s not being used for server auth), the EAP is the plaintext password of the user. They’ll need to supply domain, username, and password. Note: chmod 600 this file to root, as it contains plaintext passwords.
    : PSK longstring1
    domain\user : EAP "longstring2"
  6. A little gotcha here – I tried testing the PB at this point, but there seems to be some issue when it’s sat on the same net as the strongswan, so I moved straight to the next step…
  7. Firewalls. Both the ASA and PIX needed acl changes to allow the IPsec traffic through, and to allow the ipsec clients access to the internet. We are going to nat the ipsec endpoint onto outside_ip2.
    ASA:

    access-list outside_access_in remark Allow IPSec to ipsec server
    access-list outside_access_in extended permit esp any host outside_ip2
    access-list outside_access_in extended permit ah any host outside_ip2
    access-list outside_access_in extended permit udp any eq isakmp host outside_ip2 eq isakmp
    access-list outside_access_in extended permit udp any eq 4500 host outside_ip2
    eq 4500
    ; We want to allow anything from (inside, external) through (outside) to be nat'ed
    ; but traffic between inside and external shouldn't be. nat_exempt has a list of ACEs
    ; which will not be nat'ed
    global (outside) 1 interface
    nat (inside) 0 access-list nat_exempt
    nat (inside) 1 0.0.0.0 0.0.0.0
    nat (external) 0 access-list nat_exempt
    nat (external) 1 0.0.0.0 0.0.0.0
    access-group outside_access_in in interface outside
    ; Both the DMZ and VPN virtual IPs are on the other side of the PIX
    route external 10.1.99.0 255.255.255.0 10.1.98.2 1
    route external 10.1.100.0 255.255.255.0 10.1.98.2 1
    ; Finally, NAT the IPSec server onto outside_ip2
    static (external,outside) outside_ip2 10.1.99.10 netmask 255.255.255.255

    PIX:

    ; acl_int_inbound applies to any traffic going to the DMZ
    access-list acl_int_inbound remark Allow IPSec to ipsec host
    access-list acl_int_inbound permit ah any host 10.1.99.10
    access-list acl_int_inbound permit esp any host 10.1.99.10
    access-list acl_int_inbound permit udp any eq isakmp host 10.1.99.10 eq isakmp
    access-list acl_int_inbound permit udp any eq 4500 host 10.1.99.10 eq 4500
    access-list acl_int_inbound remark Allow remote administration
    access-list acl_int_inbound permit tcp 10.1.1.0 255.255.255.0 any eq ssh
    access-list acl_int_inbound remark Allow inbound useful ICMP
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 echo-reply
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 echo
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 source-quench
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 unreachable
    access-list acl_int_inbound permit icmp any 10.1.99.0 255.255.255.0 time-exceeded
    ; acl_ext_inbound applies to any traffic coming from the DMZ
    access-list acl_ext_inbound remark Allow ipsec back out
    access-list acl_ext_inbound permit ah host 10.1.99.10 any
    access-list acl_ext_inbound permit esp host 10.1.99.10 any
    access-list acl_ext_inbound permit udp host 10.1.99.10 eq isakmp any eq isakmp
    access-list acl_ext_inbound permit udp host 10.1.99.10 eq 4500 any eq 4500
    access-list acl_ext_inbound remark Allow Access to some internal services
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 eq www
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 eq ssh
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 eq https
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 eq 8022
    access-list acl_ext_inbound remark Reserved to allow streaming in future
    access-list acl_ext_inbound permit tcp 10.1.100.0 255.255.255.0 host 10.1.1.11 range 6000 6500
    access-list acl_ext_inbound remark Allow DNS
    ; note: this could cause problems for large DNS (e.g. DNSSEC) queries, as tcp will be used
    ;     to fix, just add two more rules to add 53/tcp
    access-list acl_ext_inbound permit udp 10.1.100.0 255.255.255.0 host 10.1.1.53 eq domain
    access-list acl_ext_inbound permit udp 10.1.99.0 255.255.255.0 host 10.1.1.53 eq domain
    ; we want to allow the DMZ unfettered access to the internet, but not to our internal network
    ; the easiest way to do this is explicitly deny access to the internal, and then allow everything else
    access-list acl_ext_inbound remark Deny access to any other internal network
    access-list acl_ext_inbound deny ip any 10.1.0.0 255.255.0.0
    access-list acl_ext_inbound remark But allow browsing of internet from ipsec
    access-list acl_ext_inbound permit ip 10.1.100.0 255.255.255.0 any
    access-list acl_ext_inbound permit ip 10.1.99.0 255.255.255.0 any
    ; PIX firewalls are predisposed to NAT from the internal to external interfaces.
    ; The global() and nat() rules stop that - I just want the PIX as a firewall.
    access-list nat_exempt permit ip any any
    global (outside) 1 interface
    global (inside) 2 interface
    nat (outside) 0 access-list nat_exempt outside
    nat (inside) 0 access-list nat_exempt
    access-group acl_ext_inbound in interface outside
    access-group acl_int_inbound in interface inside
    ; And finally, how to get out
    route inside 0.0.0.0 0.0.0.0 10.1.98.1 1
    route outside 10.1.100.0 255.255.255.0 10.1.99.10 1
  8. Pray. And test. This should be working now, once all the services are started etc. A trick for the debugging is follow the packets through your system. If it’s not working, use a packet capture in the ASA and PIX to see if you’re seeing the IKE traffic in _and_out. If you’re not, then it’s either a firewall or routing issue. To check both, use the packet-tracer command (on the ASA, PIX doesn’t have it). Also set up logging to a syslog server from both firewalls (note: make sure you do a “logging trap warnings” else you won’t see much). Finally, have “tail -f /var/log/messages” going to catch any messages from strongswan as well.
  9. On the PlayBook (and these instructions should generally apply to any client):-
    1. Go to “Options”->”Security”
    2. Scroll down to “VPN”
    3. Press “Add New” at the bottom
    4. Populate the fields:
      • Profile Name: [whatever you want]
      • Server Address: outside_ip2 [external IP of server]
      • Gateway Type: Generic IKEv2 VPN Server
      • Authentication Type: EAP-MSCHAPv2
      • Authentication ID Type: IPv4
      • MSCHAPv2 EAP Identity: [whatever you want]
      • MSCHAPv2 Username: domain\user [from above example (ipsec.secrets)]
      • MSCHAPv2 Password: longstring2 [from above example (ipsec.secrets)]
      • Gateway Auth Type: PSK
      • Gateway Auth ID Type: IPv4
      • Gateway Preshared Key: longstring1 [from above example (ipsec.secrets)]
      • Automatically Determine IP: checked
      • Dynamically Determine DNS: checked
      • Perfect Forward Secrecy: empty
      • Manual Algorithm Selection: empty
    5. Click “Save and Connect”, and cross your fingers…
    6. On the VPN page, you should see your new VPN profile added. If you click on the cog button on the bottom left, you should be able to see the nicely populated VPN details.
  10. And finally, enjoy.

5 thoughts on “VPN on PlayBook

  1. Hi, I’m following through your instructions how ever the playbook is timing out during vpn connection setup. I have validated that it’s not a firewall issue and I my config matches yours as much as possible but the playbook fails to complete the connection.

    It seems to me that the PSK authentication on the playbook isn’t happening or is failing but I have no way to confirm this. Any suggestions what I could be doing wrong?

    Here are the last few logs from syslog (I changed the IP to x.x.x.x on purpose.)

    Jul 18 15:09:40 nas charon: 14[MGR] checkin IKE_SA
    Jul 18 15:09:40 nas charon: 14[MGR] check-in of IKE_SA successful.
    Jul 18 15:10:00 nas charon: 01[JOB] got event, queuing job for execution
    Jul 18 15:10:00 nas charon: 01[JOB] next event in 9s 971ms, waiting
    Jul 18 15:10:00 nas charon: 15[MGR] checkout IKE_SA
    15:10:00.098692 IP nas.4500 > test.4500: isakmp-nat-keep-alive
    Jul 18 15:10:00 nas charon: 15[MGR] IKE_SA successfully checked out
    Jul 18 15:10:00 nas charon: 15[IKE] sending keep alive
    Jul 18 15:10:00 nas charon: 15[NET] sending packet: from 172.16.1.39[4500] to x.x.x.x[4500]
    Jul 18 15:10:00 nas charon: 15[MGR] checkin IKE_SA
    Jul 18 15:10:00 nas charon: 15[MGR] check-in of IKE_SA successful.
    Jul 18 15:10:00 nas charon: 07[NET] sending packet: from 172.16.1.39[4500] to x.x.x.x[4500]
    Jul 18 15:10:00 nas charon: 01[JOB] next event in 9s 971ms, waiting
    Jul 18 15:10:10 nas charon: 01[JOB] got event, queuing job for execution
    Jul 18 15:10:10 nas charon: 01[JOB] next event in 10s 28ms, waiting
    Jul 18 15:10:10 nas charon: 16[MGR] checkout IKE_SA
    Jul 18 15:10:10 nas charon: 16[MGR] IKE_SA successfully checked out
    Jul 18 15:10:10 nas charon: 16[JOB] deleting half open IKE_SA after timeout
    Jul 18 15:10:10 nas charon: 16[MGR] checkin and destroy IKE_SA
    Jul 18 15:10:10 nas charon: 16[IKE] IKE_SA rem[2] state change: CONNECTING => DESTROYING
    Jul 18 15:10:10 nas charon: 16[MGR] check-in and destroy of IKE_SA successful
    Jul 18 15:10:20 nas charon: 01[JOB] got event, queuing job for execution
    Jul 18 15:10:20 nas charon: 01[JOB] no events, waiting
    Jul 18 15:10:20 nas charon: 09[MGR] checkout IKE_SA

  2. Hmmm. Okay, first things first, check your log and make sure it’s loading both the IKE and EAP secrets. Next, issue the following command to set a higher logging level:-
    # ipsec stroke loglevel any 1
    Then try the connection again. Pretty much the first lines should say:-
    received packet: from x.x.x.x[500] to y.y.y.y[500]
    parsed IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) ]

    If you’re not seeing those, I think there may be a firewall in the way or something.

  3. After enabling the logging and trying it again here is what I get. I don’t see the issue.

    Jul 19 09:36:46 nas charon: 05[NET] received packet: from [500] to 172.16.1.39[500]
    Jul 19 09:36:46 nas charon: 05[ENC] parsed IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) ]
    Jul 19 09:36:46 nas charon: 05[IKE] is initiating an IKE_SA
    Jul 19 09:36:46 nas charon: 05[IKE] local host is behind NAT, sending keep alives
    Jul 19 09:36:46 nas charon: 05[IKE] remote host is behind NAT
    Jul 19 09:36:46 nas charon: 05[ENC] generating IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(MULT_AUTH) ]
    Jul 19 09:36:46 nas charon: 05[NET] sending packet: from 172.16.1.39[500] to [500]
    Jul 19 09:36:46 nas charon: 11[NET] received packet: from [4500] to 172.16.1.39[4500]
    Jul 19 09:36:46 nas charon: 11[ENC] parsed IKE_AUTH request 1 [ IDi CP N(INIT_CONTACT) N(MOBIKE_SUP) N(ESP_TFC_PAD_N) N(NON_FIRST_FRAG) SA TSi TSr ]
    Jul 19 09:36:46 nas charon: 11[CFG] looking for peer configs matching 172.16.1.39[%any]…[10.42.162.208]
    Jul 19 09:36:46 nas charon: 11[CFG] selected peer config ‘rem’
    Jul 19 09:36:46 nas charon: 11[IKE] initiating EAP-Identity request
    Jul 19 09:36:46 nas charon: 11[IKE] peer supports MOBIKE
    Jul 19 09:36:46 nas charon: 11[IKE] authentication of ‘172.16.1.39’ (myself) with pre-shared key
    Jul 19 09:36:46 nas charon: 11[ENC] generating IKE_AUTH response 1 [ IDr AUTH EAP/REQ/ID ]
    Jul 19 09:36:46 nas charon: 11[NET] sending packet: from 172.16.1.39[4500] to [4500]
    Jul 19 09:37:06 nas charon: 15[IKE] sending keep alive
    Jul 19 09:37:06 nas charon: 15[NET] sending packet: from 172.16.1.39[4500] to [4500]
    Jul 19 09:37:16 nas charon: 10[JOB] deleting half open IKE_SA after timeout

  4. Good blog you’ve got here.. It’s hard to find high-quality writing like yours
    nowadays. I truly appreciate people like you! Take care!
    !

Leave a reply to Claudette Cancel reply