Tag Archive: network


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.

netschemaIn 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

I’ve recently purchased an Edgerouter PoE from Ubiquiti, which is a great deal regarding its price and performance. The only caveat was related to the lack of native support for load balancing and failover. This lack has been fixed with the release of the 1.4.0 firmware, which embeds a load balancing functionnality with native connection tracking.

For this example, I’ll take a generic scenario of a dual WAN setup, in a failover configuration with some policy routes, as we assume some ISP specific services are not available from the internet (e.g. administration interfaces, SMTP and DNS servers…)

Let’s also assume your ISP CPEs are configured in bridge mode.  To show all the potential of the router, the IP address we’ll get from ISP 1 is dynamic and the one from ISP 2 is static, but both are acquired from ISP’s DHCP server (yes, my ISP are serious people, and they don’t use PPPo[E|A] ^.^).

I also use an internal autonomous DNS server to avoid unreachability delays during failover, and to have a trusted DNSSEC anchor. You will find below the schema for this scenario. The fqdn and IP addresses in this scenario have been changed to protect the innocents.

Our sample topology.

Our sample topology.

To begin with, set up your 3 interfaces on the router, the dhcp on the inside part, and the DNAT rules.

interfaces {
    ethernet eth0 {
    address dhcp
        description ISP_1
        duplex auto
        poe {
            output off
        }
        speed auto
    }
    ethernet eth1 {
        address dhcp
        description ISP_2
        duplex auto
        poe {
            output off
        }
        speed auto
    }
    switch switch0 {
        address 192.168.0.254/24
        switch-port {
            interface eth2
            interface eth3
            interface eth4
        }
    }
}
service {
    dhcp-server {
        disabled false
        hostfile-update disable
        shared-network-name Home {
            authoritative disable
            subnet 192.168.0.0/24 {
                default-router 192.168.0.254
                dns-server 192.168.0.252
                lease 86400
                start 192.168.0.1 {
                    stop 192.168.0.50
                }
            }
        }
    }
}
nat {
    rule 5000 {
            description ISP_1_NAT
            log disable
            outbound-interface eth0
            protocol all
            type masquerade
    }
    rule 5001 {
            description ISP_2_NAT
            log disable
            outbound-interface eth1
            type masquerade
    }
}

Next, we’ll setup the load balancer to use ISP1 as our primary access and ISP2 as our failover access. I decided to change some of the check parameters to show you how powerful the tool is. As we are in a failover setup, I won’t use the weight command, which you would use for load balancing scenarios, to adjust the percentage of traffic you’d like to send to the corresponding interface.

load-balance {
    group lb-output {
        interface eth0 {
            route-test {
                count {
                    failure 3
                    success 4
                }
                interval 5
                type {
                    ping {
                        target 203.0.113.42
                    }
                }
            }
        }
        interface eth1 {
            failover-only
        }
    }
}

As told at the beginning of this article, the load balancer will take care of tracking and marking the connection, to avoid that a current session gets in and out by different IP addresses. This is especially useful if you decide to use SNAT rules. As shown above, I decided to check ISP 1 connectivity against a specific IP address, but by default, the equipment will run the check against « ping.ubnt.com ».

Next, we’ll configure the fwr-lbalance firewall modifier group to set the policy routes. This firewall modifier will be used to let the trafic through the load balancer « lb-output », expect for:

  • RFC1918 networks which we will route through the main routing table.
  • 192.0.2.129 which is only reachable via ISP 1 (we’ll set up the target VRF table 10 for this case).
  • 198.51.100.192/28 which is only reachable via ISP 2. (we’ll assume our gateway is 198.51.100.62, and we’ll set up another target VRF table 20 for this case).

Edit: ubnt-stig advised me to use a firewall group to define the RFC1918 in the comment, so you will find an updated version below.

And here is the associated configuration:

firewall {
    group {
        network-group RFC1918 {
            network 10.0.0.0/8
            network 172.16.0.0/12
            network 192.168.0.0/16
        }
    }
    modify fwr-lbalance {
        rule 1 {
            action modify
            destination {
                group {
                    network-group RFC1918
                }
            }
            modify {
                table main
            }
        }
        rule 100 {
            action modify
            destination {
                address 192.0.2.129
            }
            modify {
                table 10
            }
        }
        rule 200 {
            action modify
            destination {
                address 198.51.100.192/28
            }
            modify {
                table 20
            }
        }
        rule 500 {
            action modify
            modify {
                lb-group lb-output
            }
        }
    }
} 
protocols {
    static {
        table 10 {
            interface-route 0.0.0.0/0 {
                next-hop-interface eth0 {
                }
            }
        }
        table 20 {
            route 0.0.0.0/0 {
                next-hop 198.51.100.62 {
                }
            }
        }    
    }
}

Now, you need to tell the router to apply the firewall modifier instance to your internal interfaces:

interfaces {
    switch switch0 {
        address 192.168.0.254/24
        firewall {
            in {
                modify fwr-lbalance
            }
        }
        switch-port {
            interface eth2
            interface eth3
            interface eth4
        }
    }
}

And finally, you’re done! Your dual wan setup is operationnal. Now you can configure SNAT rules for your publicly available services. If you want to use different a different load balancing policy, create another load-balancer group with the appropriate settings, and add a new rule into the firewall modifier group. Before exiting configuration mode, don’t forget to commit the configuration, and to save the configuration if it fits your requirement.

Edit: On the following screenshot, you can see the output of the load-balancer status commands.

Load Balander status

Load Balander status