Recently, I needed to interconnect two private networks using on one side, a SOHO Cisco 871 router (because it’s silent, and people don’t want a desktop appliance to be as loud as an aircraft), and on the other side, an existing linux box with some services we want to connect to.
The main purpose of this setup is not to get optimal performances nor security, but to test interoperability on the two involved IPSec stack.
NAT configuration on the cisco side will be given as a bonus, at the end of this article, as it might be tricky to deal with simultaneous NAT and VPN.
You will find below the schema of our example setup.
In our example, let’s assume our PSK is qFcOx72WVERsNobVsimx
Before we begin to overlook the configuration, let’s recall some points on IPSec.
IPSec is a quite complete protocol that can be used in a vast number of use cases: site to site VPNs, roadwarrior remote access, host to host security, with a focus on either integrity or integrity and confidentiality enforcement.
IPSec is thus commonly considered as a complex technology: its features are described and standardized by over 30 IETF RFCs, and it’s modularity reaches such a point that different implementations may not interoperate out of the box as we will see below. Some bonus features are not even standard (e.g. Opportunistic Encryption).
When two endpoints establish a security association (SA), the endpoint that attempt to establish the SA is called the initiator.
To summarize, the protocol works in two phases:
- Phase 1:the security association and key management, where the two IPSec endpoints mutually authenticate and exchange keys that will be used on phase 2.
- Phase 2: the security policy(ies) setup, where the two IPSec endpoints decide to do either encryption or authentication of the secured payload, and if they want to secure host to host, or network to network communications.
Here is the list of the different components that are involved in my sample setup:
- Debian wheezy with a stock 3.2.54-2 kernel and the racoon and ipsec-tools packages from the official repository (version 1:0.8.0-14 for both these packages).
- Cisco 871 with a Cisco IOS C870 Software (C870-ADVIPSERVICESK9-M), Version 12.4(15)T7, RELEASE (fc3)
Racoon configuration
To begin with, the configuration of racoon was not especially tricky until I experienced a strange issue: when the tunnel was initiated by the linux box, the phase 1 handshake worked properly, but the phase 2 failed to bring up, with a NO-PROPOSAL-CHOSEN error even if sa parameters were matching. If you have more feedback on this, you’re welcome to contribute in the comments. Edit: I have found what was the problem: I forgot to include the second sainfo section in racoon.conf, and I also made a mistake in the cisco configuration. Refer to the appropriate section for further details.
To avoid getting stuck in this case, I managed to make the linux box passive, and to bring up automatically the tunnel using a trick on the cisco side.
Racoon-issued dead peer detection also made my phase 2 die after timeout, as the cisco agent did not send appropriate replies. I addressed this issue by configuring racoon as a passive DPD responder.
/etc/racoon/racoon.conf
path pre_shared_key "/etc/racoon/psk.txt"; path certificate "/etc/racoon/certs"; log notify; listen { isakmp 198.51.100.37 [500]; } remote 192.0.2.13 { exchange_mode aggressive,main; generate_policy off; my_identifier address 198.51.100.37; peers_identifier address 192.0.2.13; lifetime time 3600 sec; passive on; proposal { encryption_algorithm 3des; authentication_method pre_shared_key; hash_algorithm sha1; dh_group 2; lifetime time 3600 sec; } } sainfo address 10.0.0.0/24[any] any address 10.224.9.0/24[any] any { { pfs_group modp1024; encryption_algorithm 3des; authentication_algorithm hmac_sha1; compression_algorithm deflate; lifetime time 3600 sec; } sainfo address 10.224.9.0/24[any] any address 10.0.0.0/24[any] any { { pfs_group modp1024; encryption_algorithm 3des; authentication_algorithm hmac_sha1; compression_algorithm deflate; lifetime time 3600 sec; }
/etc/racoon/psk.conf
192.0.2.13 qFcOx72WVERsNobVsimx
/etc/ipsec-tools.conf
#!/usr/sbin/setkey -f flush; spdflush; spdadd 10.0.0.0/24 10.224.9.0/24 any -P out ipsec esp/tunnel/198.51.100.37-192.0.2.13/require; spdadd 10.224.9.0/24 10.0.0.0/24 any -P in ipsec esp/tunnel/192.0.2.13-198.51.100.37/require;
Cisco 871 configuration
To get a nailed-up IPSec tunnel at boot time, I decided to set up a permanent ping probe using the ip sla feature of my IOS.
Edit: There was a mistake in the « crypto isakmp profile » section: when you use the match identity host directive, the identifier that follows is a fqdn, not an IP address. If you want to match IP addresses, use the match identity address directive. This is extremely important, as the phase 2 negociation might screw up because of this.
! version 12.4 no service pad service timestamps debug datetime msec service timestamps log datetime msec no service password-encryption ! hostname nettest ! boot-start-marker boot-end-marker ! ! no aaa new-model ! ! dot11 syslog ip cef ! ! no ip dhcp use vrf connected ip dhcp excluded-address 10.224.9.1 ! ip dhcp pool POOL_VLAN1 network 10.224.9.0 255.255.255.0 default-router 10.224.9.1 ! ! ip domain name example.local ! multilink bundle-name authenticated ! ! username admin privilege 15 secret 0 youradminpassword ! ! crypto isakmp policy 1 encr 3des authentication pre-share group 2 lifetime 3600 crypto isakmp key qFcOx72WVERsNobVsimx address 198.51.100.37 no-xauth crypto isakmp keepalive 10 3 periodic crypto isakmp profile 1 keyring default self-identity address match identity address 198.51.100.37 keepalive 25 retry 3 ! ! crypto ipsec transform-set MyTransformSet esp-3des esp-sha-hmac ! crypto map MyMap local-address FastEthernet4 crypto map MyMap isakmp-profile 1 crypto map MyMap 10 ipsec-isakmp set peer 198.51.100.37 set transform-set MyTransformSet set pfs group2 set isakmp-profile 1 match address 150 ! archive log config hidekeys ! ! ip tftp source-interface Vlan1 ! ! ! interface FastEthernet0 ! interface FastEthernet1 ! interface FastEthernet2 ! interface FastEthernet3 ! interface FastEthernet4 description WAN interface ip address 192.0.2.13 255.255.255.0 duplex auto speed auto crypto map MyMap ! interface Vlan1 description Internal interface ip address 10.224.9.1 255.255.255.0 no autostate ! ip forward-protocol nd ip classless ip route 0.0.0.0 0.0.0.0 192.0.2.13 ! ! no ip http server no ip http secure-server ! ip sla 10 icmp-echo 10.0.0.1 source-interface Vlan1 timeout 1000 frequency 1 ip sla schedule 10 life forever start-time now access-list 150 permit ip 10.224.9.0 0.0.0.255 10.0.0.0 0.0.0.255 ! ! ! ! control-plane ! banner motd ^C ************************************************************* $(hostname) - VPN tests cisco router Contact: Geoffroy GRAMAIZE ************************************************************* ^C ! line con 0 logging synchronous login local no modem enable line aux 0 line vty 0 4 logging synchronous login local ! scheduler max-task-time 5000 end
As promised, If you want your internal network, on the cisco side, to communicate with the internet, you should add the following commands to the above configuration:
interface FastEthernet4 ip nat outside ! interface Vlan1 ip nat inside ! ip access-list extended NAT_list deny ip 10.0.0.0 0.0.0.255 10.224.9.0 0.0.0.255 deny ip 10.224.9.0 0.0.0.255 10.0.0.0 0.0.0.255 permit ip 10.224.9.0 0.0.0.255 any ! ip nat inside source list NAT_list interface FastEthernet4 overload