Copyright © 2005 jsd

Fun with iproute2 and FreeS/WAN

John Denker

1  Introduction

I rely on iproute2 to solve a lot of routing problems. The FreeS/WAN documents say that iproute2 is for wizards only – but in my experience, it has been a big help and no hindrance at all. If you asked me to set up a FreeS/WAN box without iproute2 I wouldn’t know how to do it.

1.1  Routing

In the current (first-generation) FreeS/WAN system, the routing is a bit of a kludge. It is hard to get a clear picture of how a packet moves through the kernel routing, the FreeS/WAN eroutes, the encryption, et cetera.

There are no good reasons, only lame historical reasons, why each ipsec virtual interface is tied to a particular physical interface, sharing its IP address. One of the objectives for the next-generation KLIPS is to fix this. Fortunately, we can more-or-less fix it using the first-generation system plus iproute2.

One reason why this is complicated is that our theoretical understanding has changed since the days when FreeS/WAN was created.

In particular, the original theory was that encryption was just a transformation applied to a packet that was going to be sent anyway. In this view,

The new theory goes like this:

Creating a new IPsec tunnel is almost equivalent to stringing a new physically-private wire from point to point, as discussed at e.g. ./ipsec+routing.htm

The FreeS/WAN team says they are “committed” to doing this, according to the design/requirements document, but there hasn’t been much discernible progress.

For more information you could try searching the design archives for the discussion of MAST devices.

1.2  Security Policy Database

Another important concept: Real-world reliability is what we want. Reliability is always a tradeoff between safety and functionality. You can make your computer completely safe against network hackers by disconnecting it from the network, but alas that reduces the functionality in ways that you may find unacceptable.

In these terms, an IPsec tunnel is good because it creates new functionality. It creates a new route between point A and point B. It also advances a subset of the safety objectives, by protecting the traffic in the tunnel against snooping and tampering. However, we must keep in mind that the tunnel by itself leaves some important safety objectives unmet: The existence of a new good connection from A to B does not by itself preclude the existence of bad old connections from A and/or to B.

This is why every instance of IPsec must have a Security Policy Database (SPD) in addition to whatever tunneling it provides. This is mandatory according to rfc2401, which effectively defines IPsec. The SPD is required to have power over all the machine’s network traffic, and is required to have enough expressive power so that you can regulate what goes in and out via the encrypted tunnels, and what (if anything) is allowed to go in and out through non-encrypted connections.

Non-experts very commonly make the mistake of fixating on the tunnels to the exclusion of the SPD.

Therefore we must recognize an important difference between FreeS/WAN and linux-ipsec. The software that you download from freeswan.org implements IPsec tunnels but does not by itself implement an RFC-compliant SPD. Therefore FreeS/WAN is not by itself a complete IPsec implementation. You can create a much more nearly complete IPsec by combining FreeS/WAN plus iproute2 plus iptables (the Linux built-in firewalling system).

To repeat: Creating a tunnel is not sufficient. You need safety as well as functionality, and safety requires meticulous routing and firewalling.

2  Installing iproute2

Start by reading the Advanced Routing Howto.

The “policy routing” kernel configuration option needs to be turned on. If necessary, turn it on. While you’re there, turn on support for dummy network devices (especially if you are setting up a laptop or other non-gateway machine). Then recompile and re-install your kernel. You will also need to download, build, and install the userland utilities associated with iproute2. A terse but useful “commands reference” is included in that download.

3  Using iproute2

Let’s discuss the basic VPN telecommuter “extruded subnet” situation:

      Chumash            ipsec0~~~~~~~~~~~~~~ipsec0
         |              /            .            \
     (Sunset)       West             .             East         Pequot
         |         /    \            .            /    \          |
      router===eth0      eth1-----\  .  /-----eth1      eth0===(Sunrise)
           \                      (cloud)
        firewall------------------/     \
Figure 1: Typical Extruded-Subnet Configuration

Consider a packet that starts out on Pequot, which is a simple (IPsec-unaware) host on Sunrise-net. The packet is destined for foo.net which is some generic host on the wild internet. The desired behavior is that the packet is encrypted by the IPsec gateway East, forwarded to West, and decrypted there. The plaintext is then routed via the firewall and via the cloud to foo.net.

You may be asking why East didn’t route the plaintext directly to foo.net, bypassing the encryption process entirely. Well,

a) sometimes that would be good, but
b) sometimes that would violate corporate policy that all traffic from telecommuters such as Pequot must go through the corporate firewall.

So let’s suppose we are in the latter situation. That evidently means that West needs a default route that goes out West:eth0 and thence through the firewall.

3.1  Separating Local Traffic from Customer Traffic

Giving West a default route via eth0 doesn’t solve all the world’s problems. We face two challenges:

3.2  Separating Local Wild-side versus Private-side

Now suppose somebody on West itself wants to make a host-to-host connection to East itself.

There is no way the routing system can read your mind. If you just ssh to the wild-side address of East, you cannot expect the routing system to know whether you want superencryption or not.

So let’s start with the system outlined in section 3.1. That means that traffic from West to the wild-side address of East will bypass all the KLIPS machinery and go straight out West:eth1. So you can ssh to this address and it makes sense, if that’s what you want. You can telnet to this address if you dare, but it will be totally unencrypted.

Now, if you want to go through the IPsec tunnel, you can utter the private-side address of East, namely East:eth0. That means that even though this is truly a host-to-host communication, it will be handled as something more like a host-to-subnet connection, where East is serving as a gateway to itself: East (the gateway) is connecting you to East (the host on Sunrise-net).

Watch out for a booby trap here: If you’re not careful, the networking machinery on West will set the source address of such traffic according to the default source address of the interface that was used. This will be the wild-side address of West, West:eth1. That means, alas, that when East replies, it will reply in the clear. This is a very common mistake. Traffic will flow in one direction through the IPsec tunnel, but replies will come back in the clear. Yeccccchhhhhh!

This is the penalty for the ancient design mistake that gave the ipsec0 device the same address as the associated physical device.

To understand what happens next, let’s think for a moment how an “alias” device works. Call it eth1:1 for concreteness. Alias devices are not separate devices; eth1:1 is truly not much more than an alias for the eth1 device. In particular, eth1:1 and plain eth1 both put packets onto the same ether.

For present purposes, the important thing is that the alias device has its own default source address, independent of the underlying unaliased device. We would like to create an alias on the ipsec0 device. We can do that in all but name using iproute2, just by defining a new route with the appropriate “src” attribute. It will not show up in the output of the “ipconfig” command the way a full-fledged alias device would, but it will work the same.

Specifically, you will need to define a new table (let’s call it from.this.host) and add a line like

2 from.this.host

to your /etc/iproute2/rt_tables file. The commands on West will include things like

ip rule add iif lo table from.this.host priority 500
ip route add $SunriseNet table from.this.host \
    dev ipsec0 src $WestPrivateIfcAddr

Also, don’t forget to do

ip route flush cache

at the end of your setup script; otherwise changes will take effect only after some maddeningly irreproducible delay.

Note “iif lo” is a documented idiom that triggers the rule for all traffic originating locally; I wouldn’t have thought of such traffic as going anywhere near the “lo” interface, but the rule performs the desired function, and that’s what counts.

Call this the “iproute2 alias” solution. It is not a documented feature of FreeS/WAN, but we use it and we’ve never had a problem with it. I can’t guarantee its functionality or security, but it seems so elegant and straightforward that it’s hard to see what could go wrong with it.

Digression: Suppose East is a laptop or something like that, meaning that it is not really a gateway and doesn’t have a real interface corresponding to the eth1 device shown in figure 1. In this case you can define a dummy device or perhaps an eth1:1 alias and assign it an address, namely the address you want to use as East’s private-side address. This is the address that people on Sunset-net and everywhere else will use when they want to talk to East via the IPsec tunnel.

Let us contrast the iproute2 alias solution with something we can call the “old” solution, which is suggested in the FreeS/WAN documentation. The old solution is to bring up four different tunnels:

The iproute2 alias solution is certainly easier than configuring all those tunnels, but that’s not the main argument.

The main point is that the iproute2 solution gives you the flexibility of connecting to the wild side (East:eth1) if/when you don’t want to go through the IPsec tunnel, and connecting to the private side (East:eth0) if/when you do want to go through the tunnel.

In the “old” solution, if any traffic to East flows through the IPsec machinery, then almost all such traffic must flow through the IPsec machinery. (I say “almost” all, because KLIPS makes a special exception for UDP port 500, but everything else will get the treatment.) You will have no way to let your ssh traffic or pings or anything else bypass the IPsec stuff. You simply don’t have enough expressive power.

The essential problem is that without iproute2, the FreeS/WAN system requires that if you send any IPsec traffic to East, you have to send it to East’s wild-side address. The system just wasn’t designed to handle the case where East (the gateway) is connecting you to East itself (the host on Sunrise-net).

3.3  Decoupling Inner Headers

Here’s is another reason why the new “iproute2 alias” solution is preferred over the “old” solution.

The old solution forces you into having the private-side address of your peer be equal to its wild-side address. Therefore, if the wild-side address changes, it forces the private-side address to change also, breaking things at the application layer. One of the nice features of a tunnel is that it decouples the applications from wild-side address changes.

Wild-side address changes can happen for various reasons. Your wild-side ISP might change things every so often via DHCP. In various mobility scenarios, you might want to move to a completely new wild-side ISP while keeping your same old private-side address.

To deal with such situations, we once again want the situation where East (the gateway) is connecting us to East (the host on the protected subnet). This is easy to do using iproute2.

3.4  ip route get ...

Everybody agrees that having “nexthop=” settings in the .conf file is an abomination. What we do in my shop is to have a template file, plus a bunch of scripts that read the template and automagically generate the .conf file. We use the command

ip route get ....

to help find the routing information in a very natural way. Without using iproute2, it is unbelievably painful to extract this information from the routing tables. So this is yet another reason why we like iproute2.

3.5  Other Security Policy Selectors

Another thing iproute2 enables you to do is to make the routing more selective, making it sensitive to things like destination port, source port, or interface. These “selectors” are considered mandatory features of the IPsec SPD according to rfc2401, as discussed in section 1.2.

For example, you might want to send telnet traffic through the IPsec tunnel, but allow ssh traffic to bypass the tunnel.

The process is somewhat roundabout, because iproute2 is not by itself sensitive to port number. You have to use the firewall, which is sensitive to port number. You use it to set the “firewall mark” (fwmark) and then install a routing rule that is sensitive to the fwmark.

3.6  Load Sharing and Failover

The iproute2 package also provides for GRE devices, which can be combined with IPsec transport mode in interesting ways, as discussed on the routing page.

The load-balancing features themselves are part of iproute2, as discussed in the howto.

4  References


Copyright © 2005 jsd