|<< Previous Entry||Main||Next Entry >>|
|« It's (was) the holiday season||Replacing ugly Helvetica fonts in Xorg »|
This is a quick mini-howto on how to get IPSec working between an OpenWRT (or any linux gateway) box and a Cisco IOS router, where both are also doing NAT for their networks. I'll also describe how to get the Linux gateway talking IPSec to a standalone Linux host elsewhere on the net. Last but not least, you'll also see how to get an IPV6 over IPv4 tunnel working across this.
I was recently rebuilding my home network topology, and part of that rebuild involved some IPSec tunnels across the Internet. I though I'd share my documentation on this to assist anyone else attempting a similar setup. The setup is built around Linux and Cisco IOS NAT gateways, as well as one standalone host, and the challenge faced here is to have IPSec running between the Linux NAT box and the other two devices.
The basic network topology is shown below. It consists of two NATed networks (Amsterdam and Sydney) and one standalone host (San Jose), all with static public IP addresses. These networks have significant communication between them, and with a desire for privacy and bypassing of ISP filters (eg port 25), tunnels have been built between the devices to give transparency across the network. The use of NAT adds to some of the challenges in building this.
The devices here consist of one standalone Linux host, one OpenWRT-Linux based router and one Cisco 827 ADSL router. The routers are NATting for the networks behind them, and some port redirection is enabling outside access to services on those networks. All networks have global IPv6 connectivity via tunnels (not shown here), and there are IPv6 tunnels directly connecting them. The internal networks behind the NAT gateways will be reachable from each other via IPSec tunnels.
My IPSec daemon of choice is OpenSwan, and a package is available for OpenWRT. There's a reasonable amount of documentation on it, but strangely I found only a few references to getting it working with a Cisco IOS box, and even fewer in combination with NAT.
The Cisco is an 827 ADSL router, running a 12.3 IOS with IPSec features. Conveniently, it also has support for IPv6, however IPSec on IPv6 is not supported, hence the use of tunneling IPv6 over the IPv4 IPSec.IPSec and tunnel topology
For the Amsterdam to Sydney connection, I decided to build various tunnels linking the possible communication paths over IPv4. One of the niggles with IPSec is that you've got to define all source and destination combinations as separate tunnels. The IPv6 addresses are tunnelled over an IPv4 IPSec tunnel, using standard 6-in-4. I had to use this for IPv6 anyway, given that the devices don't support IPv6 IPSec.
Between Amsterdam and San Jose, IPv4 is tunnelled with IPSec, but IPv6 would is routed over an IPv6 in IPv4 tunnel, for the same reasons - limited device support.
The configuration of OpenSwan is handled within two files. The file /etc/ipsec.conf is the main config file and describes the settings for each IPSec connection. Configuration of crypto keys are in /etc/ipsec.secrets, and if simple preshared keying is used, this is all that needs to be touched. In the following examples, the key will be "SecretKey" but of course you should use something much longer and more obscure.Amsterdam to Sydney
The following is the OpenSwan configuration for the Amsterdam to Sydney connection. It contains four tunnel definitions, defining all possible traffic flows:
And here is the IOS configuration for Sydney:
We will now configure the IPv6 tunnel to complete the tunnel config for this connection.
First the Amsterdam configuration:And the Cisco configuration:
Does the connection work yet?
No it doesn't. The problem is related to NAT and firewalling configuration on both ends.
On the Cisco side, the router will attempt to NAT the outgoing packets from the internal hosts before encrypting them with IPSec, and thus mangle the source address of the packet. Ingress traceroutes to an internal address will terminate on the public address, not the internal address. To solve this, we need to exclude IPSec-handled packets from the NAT processing. Somewhere in your IOS configuration will be a line similar to this:The source-list referred to will need to be added to so that packets out via IPSec are excluded. So access-list 101 becomes:
On the OpenWrt box, NAT doesn't mangle with the IPSec packets, due to the rule processing order in iptables. NAT only affects packets leaving the WAN interface, but IPSec processing occurs before this, and by the time they're encrypted, the source address of the IPSec packets won't match the NAT rule any more.
However, the FORWARD table of the OpenWrt box will be default drop all packets that it can't establish as being related to an existing connection (ie anything not NAT or port forwarded) and so will drop any not destined for the local machine, ie IPSec traffic for any inside host.
Thus, to fix this, we put in a forwarding rule that allows all IPSec traffic through the box. In addition, we'll add a rule that ensures port 500 UDP traffic (IPSec key management aka ISAKMP) is handled locally:
At this point, there should be full connectivity between the internal networks of both ends on both IPv4 and IPv6. Traceroute from an internal host at one end to any IP address of the other end should reveal only one WAN hop.
That completes the configuration for the Amsterdam to Sydney link.Amsterdam to San Jose
Between Amsterdam and San Jose, we'll also configure OpenSwan at both ends. There will be two IPSec tunnels configured here - one will carry traffic between the public addresses, and the other will carry traffic between the Amsterdam internal network and San Jose. So one tunnel will carry traffic between 126.96.36.199 and 188.8.131.52, whilst the other will carry it from 184.108.40.206 to 192.168.0.0/24. The rules for this configuration are quite simple:
San Jose config:
When be bring these connections up, we see that all traffic is successful, and this tunnel works. The forwarding rule for the ipsec0 interface above is important and allows reachability to the inside hosts. Note that you don't need to put an equivalent forwarding rule on the Linux host, as nothing is forwarded through the box. But you may need to configure general input and output rules to allow IPSec packets.
Lastly, we configure an IPv6 tunnel across this IPSec link. It's quite straight forward and this is the configuration:
San Jose end:
A quick ping will show the IPv6 tunnel up and there should be reachability to all hosts on the inside of the Amsterdam network. It's also a good idea to configure firewalling rules on the IPv6 side - anyone breaching the public host has full IPv4 and IPv6 access to the Amsterdam network, so be smart and build that firewall.
Last but not least...the IPSec connection between San Jose and Sydney....is left as an excercise to the reader.Conclusion
IPSec is often seen as a mysterious protocol in the IP world, difficult to setup and hard to maintain. But a look into a basic configuration with it reveals it to be not that hard at all. The configurations above should be a good solution for many common network topologies, and with a clear understanding as to what it all does, adapting it to other networks should be relatively painless.Posted by Ben at July 6, 2006 10:02 PM