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:-
- 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]
- Install strongswan. I shall assume the /etc files go in the normal places.
- /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
- /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 ...
- /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"
- 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…
- 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
- 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.
- On the PlayBook (and these instructions should generally apply to any client):-
- Go to “Options”->”Security”
- Scroll down to “VPN”
- Press “Add New” at the bottom
- 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
- Click “Save and Connect”, and cross your fingers…
- 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.
- And finally, enjoy.
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
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.
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
What I should have said, I don’t see the issue so I’m not sure why it’s not working.
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!
!