The return of the Linux router... (from pfSense to Debian, part 8: IPSec VPN betwen Cisco and Debian)
Hi again... yet another IT article on the way.
Today I'm going to summarize on this article all my config snippets and notes that I gathered as I struggled to setup VPN tunnels from CISCO routers against a Debian virtual routers running StrongSwan.
To my taste, CISCO IPsec VPN, when compared with OpenVPN, is way too complex to setup, somehow troublesome or unstable, and definitely not as flexible... but Cisco is Cisco, and the ability to stablish VPN tunnels between Cisco devices and Debian virtual routers became a must.
The example, configuration and snippets I'll share here are the ones that allowed me to 'break through', to get 'something that just works', from where eventually evolve into more complex or specific setups where needed.
So, consider this when facing a real scenario, due to the extreme simplicity of this setup...
So, essentially, what I'm going to show here is how to create an IPSec tunnel, between a local/branch office/home office Cisco router (the labs were done with 1841 and 2801 routers running IOS 12.4) and a virtual Debian router, running at the datacenter, allowing me to interconnect the local LAN with the remote virtual/physical resources, in the most simple way (that I'm aware of): through a pre-shared key.
Sure, there're way better, way more modern, secure (and waaaay expensive) ways to do all this with todays Cisco stuff ... but we do also can switch to Debian and use OpenVPN ;-)
For the sake of better understanding the configuration files, let's first put in place some asserts about the situation:
- We have a virtual network, a Broadcast domain or virtual LAN (not to be confused with a swhitch vLAN although both can be inter-connected), running on our Hypervisor cluster environment, with our virtual Debian router having a virtual interface connected to it, lets say its address is LAN: 10.1.1.0/24, and we got our virtual router having also a WAN interface, receiving traffic to/from public fixed address WAN: 18.104.22.168, rosolved by DNS name debian-router.example.com.
- We do have two remote branch sites, having each one a Cisco ISR G2 Router.
Those sites may have a public fixed IP address but, in this case, they don't, since, instead, they handle a DynDNS dynamic IP automatic DNS update (you may be interested on my article about setting up DynDNS on Cisco devices here).
- One remote site has two separate LANs, let's say LAN1: 192.168.1.0/26 and LAN2: 192.168.1.64/26, and its public IP address is always resolvable through site-one.example.com.
- The other side has just the typical single LAN, let's say LAN1: 192.168.2.0/24, with its DynDNS name site-two.example.com always resolving its public IP address.
Some points about Strongswan/IPSec setup
OK, let's suppose that, like me, after using GUI based routers such as pfSense to handle IPSec connections, we do not know anything about Strongswan/IPSec setup mechanics... if so, the following advices may certainly help you, if not, you may entirelly omit this section of the article :-) ... here we go:
- We will need to explicitly define and setup a connection in the configuration file for every pair of networks we want to tunnel traffic.
- In this case, although there are two remote routers, since I want to inter-connect all the three remote LANs (one remote Cisco router has two LANs), with the local Debain router LAN, this makes three connections to configure.
- I will setup yet another connection (a bypass connection) to tell the Strongswan IPSec process to don't bother about traffic going from/to the local LAN itself.
Would the Debian router had two, three, four LANs... then two, three, four... baypass connections had to be put in place in the configuration file.
So, three connections plus the LAN bypass connection, makes a total of four connections that will make up the main body of this example setup.
- From the Debian router perspective, regarding Strongswan way of understanding the configuration file, It, the router itself, is the LEFT side of every defined connection.
- The remote side af a connection, the Cisco router in this scenario, is therefore the RIGHT side on every defined connection.
- The configuration file
/etc/ipsec.confis the place that contains the configuration of IPSec used here and, along with some general configuration options, is organized as a set of, you may guess, connections!
- On every connection, the local, public IP, is defined by the right stanza, while the left stanza will define the remote public IP address or (in this example) the full host dns name.
- On every connection, the inter-connected local networks (each side's LAN) will be defined by rightsubnet (the LAN connected to de Debian reouter) and leftsubnet (the LAN behind the remote Cisco router)
- On every connection, both left (local) and right (remote) sides do get an identifier, a kind of email-like string format id, defined by the leftid and rightid stanzas, that would be used to check Pre-shared key.
- Nothing prevents us to re-use ids, so, multiple connections, may have the same configured ids.
- A file named
/etc/ipsec.secretswill contain a set of lines, where every line defines a valid combination of left-side id, right-side id, and the pre-shared key both endpoints know/agree to use for mutual authentication.
- By reusing ids on the connections, a single pre-shared key may be used for multiple connections.
OK... that's enough I think ... Neverthless, I would add some comments within this example configuration file, but, altoghether, I think that all toghether may make the whole picture clearer... let's see how it looks!
Setting up Debian Router side
First install Strongswan package with apt, so every needed dependency is automatically installed... you guessed it
apt-get install strongswan
And now let's go for te configuration.
As pointed earlier, the configuration takes place at
/etc/ipsec.conf, most of it consist of connection definitions, that start with the conn word, along with some general settings... here we go:
# ipsec.conf - strongSwan IPsec configuration file #### basic configuration #### config setup charondebug="cfg 2, dmn 2, ike 2, net 2" uniqueids = yes #### Connections #### # Bypass connections do match traffic going to/from local subnets # We state them as passthrough to kinda ignore them. # The naming of the connections is entirely up to you. # Bypass for local LAN conn bypassLAN leftsubnet = 10.1.1.0/24 rightsubnet = 10.1.1.0/24 authby = never type = passthrough auto = route # Tunnel connections go next. # Every connection matches traffic from/to remote LAN endpoints # The first connection has relevant parts separated and commented # tunnel with site-one LAN1 conn siteoneLAN1 fragmentation = yes keyexchange = ikev1 reauth = yes forceencaps = no mobike = no rekey = yes installpolicy = yes type = tunnel dpdaction = restart dpddelay = 10s dpdtimeout = 60s auto = route # Local is left, and here's public IP address left = 22.214.171.124 # Remote is right, and here's the dns name resolving public IP right = site-one.example.com # Tayloring a left id to be used in IPSec PSK in an email-like fashion leftid = email@example.com ikelifetime = 14400s lifetime = 3600s ike = 3des-sha1-modp1024! esp = 3des-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1024! # Note both sides agree to use PSK for auth leftauth = psk rightauth = psk # Next is the right id as we expect to be sent by Cisco router. # Cisco router will assemble the id from hostname plus domain. # So, ensure this string matches what Cisco will send. rightid = r1.site-one.example.com aggressive = no # Finally declare traffic to be matched by this connection # This is done by declaring both endpoint LAN subnets. rightsubnet = 192.168.1.0/26 leftsubnet = 10.1.1.0/24 # tunnel with site-one LAN2 conn siteoneLAN2 fragmentation = yes keyexchange = ikev1 reauth = yes forceencaps = no mobike = no rekey = yes installpolicy = yes type = tunnel dpdaction = restart dpddelay = 10s dpdtimeout = 60s auto = route left = 126.96.36.199 right = site-one.example.com leftid = firstname.lastname@example.org ikelifetime = 14400s lifetime = 3600s ike = 3des-sha1-modp1024! esp = 3des-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1024! leftauth = psk rightauth = psk rightid = r1.site-one.example.com aggressive = no rightsubnet = 192.168.1.64/26 leftsubnet = 10.1.1.0/24 # tunnel with site-two LAN1 conn sitetwoLAN1 fragmentation = yes keyexchange = ikev1 reauth = yes forceencaps = no mobike = no rekey = yes installpolicy = yes type = tunnel dpdaction = restart dpddelay = 10s dpdtimeout = 60s auto = route left = 188.8.131.52 right = site-two.example.com leftid = email@example.com ikelifetime = 14400s lifetime = 3600s ike = 3des-sha1-modp1024! esp = 3des-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1024! leftauth = psk rightauth = psk rightid = r1.site-two.example.com aggressive = no rightsubnet = 192.168.2.0/24 leftsubnet = 10.1.1.0/24 ### End connections add includes include /var/lib/strongswan/ipsec.conf.inc
Ok, that was enough for this very basic setup (but also gives an idea on how this technology can get really tricky to setup when a mix of more demanding specifications are needed in different connections).
Now let's take a look to the
It basically depicts a kind of map of id-to-id pre-shared key assignment:
# This file holds shared secrets or RSA private keys for authentication. # RSA private key for this host, authenticating it to any other host # which knows the public part. # this file is managed with debconf and will contain the automatically created private key include /var/lib/strongswan/ipsec.secrets.inc # PSK id pairs go next firstname.lastname@example.org r1.site-one.example.com : PSK "SECRETONE" email@example.com r1.site-two.example.com : PSK "SECRETTWO"
Essentially, connections against a single remote router do share the same PSK, by reusing the same leftid, that's why only two lines are enough for three conns.
Cisco router at site-one will have to be configured with 'SECRETONE' as PSK, whilst site-two Cisco router will have to be configured with 'SECRETTWO'.
So let's jump onto Cisco part of the game...
Setting up Cisco Router side
Ok, since, essentially, both configurations on Cisco routers are the same, I'll depict only one, the one for site-one, just because due to the fact that it tunnels two local subnets.
I'll split the configuration in sections, to explain them better, and note that here I will not deal with anything unrelated to the actual IPSec tunneling topic...
So, let's dive into configuration details.
First, just by appearance in Cisco start/run config, I'll mention that we need to have hostname and domain set up on the routers, since they'll be used as peer id during PSK handshake.
So, r1, at site-one, will include the following within its config:
hostname r1 ip domain name site-one.example.com
Next comes the bulk of IPSec related configuration.
First we are defining the usage of PSK as policy for isakmp, along with defining a pre-shared key to use when connecting against 184.108.40.206 (our debian-router IP) along with some isakmp settings.
A ciphering suite is defined after this.
And finally, we setup a crypto map, named 'debianRouterVPN', that will be afterwards assigned to the WAN router interface.
Note how we define 220.127.116.11 as peer, we select the created transform set, and we declare which ACL (ACL 111 in the example) will this map use to discriminate which traffic passing through the afected interface will be intercepted and undergo tunneling.
crypto isakmp policy 10 encr 3des authentication pre-share group 2 crypto isakmp key SECRETONE address 18.104.22.168 no-xauth crypto isakmp identity hostname crypto isakmp aggressive-mode disable ! ! crypto ipsec transform-set 3DES-SHA esp-3des esp-sha-hmac ! crypto map DebianRouterVPN 10 ipsec-isakmp set peer 22.214.171.124 default set security-association idle-time 60 default set transform-set 3DES-SHA set pfs group2 match address 111
Next step is to assign the crypto map to the interesting interface.
Here I depict as a WAN interface a Dialer0 interface.
interface Dialer0 crypto map DebianRouterVPN
Now, traffic passing through this interface is candidate for tunneling... but just candidate, we must specify which one... this is where an ACL (a numbered 111 ACL in this example) comes into play.
In this ACL 111 we will ensure that just the traffic going to/from local LANs 192.168.1.0/26 192.168.1.64/26 and remote LAN 10.1.1.0/24 will match.
By doing so, this traffic will be selected and undergo tunneling.
access-list 111 permit ip 192.168.1.0 0.0.0.63 10.1.1.0 0.0.0.255 access-list 111 permit ip 10.1.1.0 0.0.0.255 192.168.1.0 0.0.0.63 access-list 111 permit ip 192.168.1.64 0.0.0.63 10.1.1.0 0.0.0.255 access-list 111 permit ip 10.1.1.0 0.0.0.255 192.168.1.64 0.0.0.63
Now, at this point, although the configuration, from the IPSec perspective, is complete, in a typical scenario where the router is our gateway towards the internet for the local LANs, we would find this setup is still no working.... why? ... because of NAT.
Since this router is acting as the branch gateway, any traffic forwarded from the LANs to the Internet through the WAN interface has its source IP address changed by the router's WAN interface IP address, and this happens BEFORE ACL 111 is applied... so, it never matches!
To avoid this we have to tune the ACL that rules NAT/overload to never match (and thus trigger natting) the traffic we intend to tunnel.
So, if our r1 router at site-one has this very typical NAT rule:
ip nat inside source list 101 interface Dialer0 overload
Then, in the NAT ACL (numbered ACL 101 in this example), we will explicty deny our target traffic:
access-list 101 deny ip 192.168.1.0 0.0.0.63 10.1.1.0 0.0.0.255 access-list 101 deny ip 192.168.1.64 0.0.0.63 10.1.1.0 0.0.0.255 access-list 101 permit ip any any
Note that, comparing NAT ACL 101 with crypto ACL 111, since NAT happens as traffic goes LAN to WAN (ip nat inside / ip nat outside), only the traffic from local LANs towards remote LANs has to be rejected, while on the crypto ACL 111, both to/from traffic had to be specified for tunneling in/out.
And that's it for the day... I found tricky to combine all this with Cisco DynDNS implementation and Zone Based Firewall... but once get it correctly set up, it works consistently and is a quite good starting point.
Hope someone finds this useful!