FreeS/WAN Opportunism HowTo
===========================

RCSID $Id: opportunism.howto,v 1.10 2002/02/04 23:26:48 dhr Exp $

D. Hugh Redelmeier


FreeS/WAN, the LINUX IPSEC implementation, is intended to allow
systems to connect through secure tunnels with or without prearrangement.
We use the term "Opportunism" to describe tunnels set up without
prearrangement.  This HowTo will show you how to set your system up
for Opportunism.

You are expected to already have built and used FreeS/WAN.  Much more
information about FreeS/WAN is provided at http://www.freeswan.org.
This document is only intended to describe the support for
opportunism.  The features described here are available in FreeS/WAN
version 1.91 or later (there were important bugs up until 1.95).

For a more complete description of the design of Opportunism, see our
paper "Opportunistic Encryption" (available as opportunism.spec in
the same directory as this document).


Steps
=====

- Understand what you are attempting.  Security requires care.
  Problems are hard to untangle.  Be sure to read the last section
  "Important Limitations".

- Install FreeS/WAN (version 1.91 or later).

- Add appropriate DNS records to your reverse-map domains.

- Add suitable conns to /etc/ipsec.conf.

- Try it out: start it, monitor it, fix it.

- Now you understand the system better, reread "Important Limitations"

These steps are also an outline of this document.


Theory
======

FreeS/WAN runs on a machine that we will call a "Security Gateway".
Usually this machine is a gateway to the internet.  It may be that the
only machine for which it provides gateway services is itself, but
that is just a special case -- we will still call it a Security
Gateway.

A FreeS/WAN Security Gateway implements secure tunnels to other
Security Gateways.  One problem is to arrange for these tunnels to be
created and used.  If opportunism is enabled, a Security Gateway
running FreeS/WAN will intercept the first outbound packet to a
particular destination (IP address), and try to negotiate a security
tunnel suitable for traffic to that destination.

To make this work going the other way, the Security Gateway must be
willing to negotiate with peers trying to protect traffic initiated
from their side.

The first novel problem is that our Security Gateway needs to discover
the IP address of the other Security Gateway for the packet that
prompted the negotiation.  Oh, and quickly discover if there is none
-- that negotiation will be impossible.

The second novel problem is that our Security Gateway needs to
authenticate the other Security Gateway.  This authentication needs to
ensure that the other Security Gateway is who it claims to be AND that
it is authorized to represent the client for which it claims to be the
gateway.

The roles in a particular negotiation are:
     Source----Initiator----...----Responder----Destination

The Source and Destination are endpoints of the traffic that is to be
protected.  The Source is the one that happened to send the first
packet of traffic.  Neither needs to be aware of IPSEC or FreeS/WAN.
That is the job of their respective Security Gateways, Initiator and
Responder.  The names "Initiator" and "Responder" match those used in
the IPSEC standards for IKE negotiation.  Remember that Source and
Initiator could be the same machine; similarly, Destination and
Responder could be the same.  All traffic from Source or Destination
must flow through their Security Gateways if it is to be considered
for protection.  These roles are fluid -- they can be different for
each negotiation.

We use the DNS (the Domain Name System) as a distributed database to
publish the required information.


DNS Records Required
====================

See section 2.3 of "Opportunistic Encryption" for a fuller
explanation.

Generally, we need to add records to the reverse-map DNS entries for
the client machine and its Security Gateway machine.  There are
special cases that are exceptions.

A Security Gateway that is going to initiate an Opportunistic
negotiation needs to provide a way for the Responding SG to find a
public key for the Initiator to allow authentication.  This is
accomplished by putting the public key in a KEY record in the
reverse-map of the Initiator.  Conveniently, the KEY record can
be generated by the ipsec_showhostkey(8) command.

	ipsec showhostkey

Here is an example of the output, with many characters of the key
itself left out:

	; RSA 2048 bits   xy.example.com   Sat Apr 15 13:53:22 2000
	xy.example.com.   IN   KEY   0x4200 4 1 AQOF8tZ2...+buFuFn/

=> Copy the output of the command into the zone information for the
   reverse-map of the Security Gateway's public interface.

Each client that is to be protected by Opportunistic Encryption must
include a special TXT record in its reverse-map.  The
ipsec_showhostkey(8) command can create this too.  Remember:  this
command must be run on the Security Gateway where the ipsec.secrets
file resides.  You must tell the command what IP address to put in the
TXT record.  The IP address is that of the Security Gateway.

	ipsec showhostkey --txt 10.11.12.13

This command might produce the output:

	; RSA 2048 bits   xy.example.com   Sat Apr 15 13:53:22 2000
	IN TXT  "X-IPsec-Server(10)=10.11.12.13 AQOF8tZ2...+buFuFn/"

- The quotes matter: this is a single string, as far as DNS is
  concerned.

- The X-IPsec-Server is a prefix that signifies that the TXT record
  contains Opportunism configuration information.

- The (10) specifies a precedence for this record.  This is similar
  to MX record preferences.  Lower numbers have stronger preference.

- 10.11.12.13 specifies the IP address of the Security Gateway for
  this machine.

- AQOF8tZ2...+buFuFn/ is the (shortened) encoding of the RSA Public
  key of the Security Gateway.

=> Added this output to the zone information for the reverse-map for
   each client machine.  This gets a bit dull and repetitive.

Unfortunately, not every administrator has control over the contents
of the reverse-map.  The only case where we can work around this is
where the Initiator has no suitable reverse map.  In this case, the
Source's TXT record gives @FQDN ("Fully Qualified Domain Name") in
place of its Security Gateway's IP address.  This FQDN must match the
ID-payload used by the Initiator.  Furthermore, a forward lookup for a
KEY record on the FQDN must yield the Initiator's public key.

If the Source's IP address is the same as the Initiator's IP address,
the Responder will assume that the Initiator is authorized to talk for
the Source (itself!).  In this case, the Responder won't try to fetch
the Source's TXT record from the reverse map for the Source's IP
address.

These two features can be combined.  If the Source and the Initiator
are the same (i.e. the Security Gateway is protecting itself), and the
Initiator uses a @FQDN ID (leftid=@example.com), then the
administrator of that machine need only have installed a KEY record in
the FQDN domain -- he need not control any reverse map.

Obscure fact: the forward lookup is only done by a Responder, and then
only when the Initiator's ID payload specifies the FQDN.  There is no
provision for a Responder with no control over its reverse-map.

Beware: DNS changes sometimes take a long time to propagate.


Configuring FreeS/WAN
=====================

To enable opportunism, you must include a suitable conn in
/etc/ipsec.conf and you must enable it.

A suitable conn looks roughly like an ordinary conn.  It more closely
resembles a Road Warrior conn (a Road Warrior conn is one that has a
wildcard %any specified as the other Security Gateway).  But in the
Opportunistic case, both the other Security Gateway AND its client are
unknown ahead of time.

conn client-to-anyone	# for our client subnet
	leftsubnet=10.3.2.1.0/24	# any single client in our subnet
	also=sg-to-anyone	# rest is same as for SG

conn sg-to-anyone	# for our Security Gateway
	left=%defaultroute	# our SG (defaults leftnexthop too)
	right=%opportunistic
	authby=rsasig	# almost always the right choice
	keyingtries=2	# don't be persistent -- peer might disappear
	auto=route	# enable at ipsec startup

(%defaultroute only works if you have specified
interfaces=%defaultroute.  Since this isn't the topic of the howto,
you will have to look at the other documentation to find out how to
handle other cases.)

You can have any number of opportunistic conns, but generally it only
makes sense to have one for each client subnet and one for the
Security Gateway itself.

Currently only one interface may be used for opportunism: Pluto knows
nothing about routing, so would be unable to choose amongst several.
Almost certainly our side's nexthop must be predetermined
(%defaultroute will do that).

Note: the routing done for outbound Opportunism will catch any packets
not covered by a more specific route.  This is what you want for
packets that are also covered by an eroute.  But packets caught by the
route and not an eroute will be subject to the no-eroute policy of
KLIPS, which defaults to %drop.  Remember that routing ignores the
packet's source address, but erouting pays attention to it.  So if
Opportunism is enabled, it is best to provide for it covering all IP
addresses behind or on the Security Gateway.

To enable these conns for inbound opportunistic negotiation, they must be
--added.  auto=add would accomplish this at ipsec startup, but if you cannot
wait:
	ipsec auto --add sg-to-anyone
	ipsec auto --add client-to-anyone

To enable these conns for outbound opportunistic negotiation, they must
be both --added and --routed.  Outbound packets will then be trapped
and will trigger negotiation.  auto=route would cause this to happen
at startup, but if you wish to do this at another time:
	ipsec auto --add sg-to-anyone
	ipsec auto --add client-to-anyone
	ipsec auto --route sg-to-anyone
	ipsec auto --route client-to-anyone


Getting DNS Through
===================

There is a serious chicken-and-egg problem.  Outbound Opportunism blocks
communication with an IP address until Pluto discovers whether that IP
address can have an IPSEC connection negotiated.  This discovery takes
DNS queries.  These DNS queries might involve communicating with
arbitrary IP addresses.  Thus we require DNS queries to succeed before
any communication succeeds, including those same DNS queries!  The way
out of this conundrum is to exempt at least some DNS query IP traffic
from Opportunism.

There are several possible solutions, all of which have advantages and
disadvantages.

1. If you use a single machine, outside your Security Gateway, as DNS
server, you can build a clear path (or even an IPSEC tunnel, but not
opportunistically) directly to that machine.

- you could use a type=passthrough conn to provide a clear path
  between your machine and the DNS machine.

- better still, you could explicitly create an IPSEC connection to
  your DNS server.  Just be sure that Pluto does not need to access
  DNS to find the IP addresses or RSA public keys for that connection!

- you could install an explicit route to the DNS machine through
  your public interface (not ipsecN).  This will bypass KLIPS
  processing.  You might have to adjust your firewall.  For example:

  	route add host -net ns.example.com gw gw.example.com dev eth1

2. Generally, it is better to run DNS on your Security Gateway.  This
leads to a need for non-opportunistic paths to an arbitrary number of
DNS servers in the internet.  One way to accomplish this is to NOT
have outbound opportunism cover the SG itself, but only the subnet
behind it.  In other words, leave out the
	ipsec auto --route sg-to-anyone
You must also add a type=passthrough eroute specifically for
sg-to-anyone (without this, the traffic will be handled by the KLIPS
no-eroute policy).

3. It is actually possible to use a single machine inside your client
subnet as a DNS server.  The techniques listed in 1 could be used to
let it communicate with other DNS servers without interference.  This
might have advantages over 1 if the DNS machine *only* did DNS.
Another technique (not often possible or reasonable) is to give this
machine another route to the internet, one that avoids the SG.

4. DNS queries will eventually time out and then Pluto will give up
and establish %pass eroutes.  So communications should start flowing.

We would like to have better solutions.  Perhaps we will in the
future.  Suggestions are welcome.


Figuring out what is going on
=============================

Since Opportunism lets your SG operate with less supervision, you may
be puzzled by what it is up to.  The usual tools exist, but their use
is more important.  To look at what Pluto is doing, use:
	ipsec auto --status
To look at what KLIPS is doing, use
	ipsec look

To just see the kernel's eroute table, look at the "file"
/proc/net/ipsec_eroute.  It contains a description of all the eroutes
in the kernel.  Here is an example:

10         10.2.1.0/24      -> 0.0.0.0/0          => %trap
259        10.2.1.115/32    -> 10.19.75.161/32    => tun0x1002@10.19.75.145
71         10.44.73.97/32   -> 0.0.0.0/0          => %trap
4119       10.44.73.97/32   -> 10.114.121.41/32   => %pass

You read each line as: a packet from within the first subnet, destined
for the second subnet, will be processed by the Security Association
Identity (SAID) specified last.  The first column is the number of
(outbound) packets processed by this eroute.

For shunt eroutes, the SAID is printed as just the type of shunt:
%pass	pass the packet through with no processing
%drop	discard the packet
%reject	discard the packet and notify sender
%hold	keep the last packet; discard others
%trap	cause any trapped packet to generate a PF_KEY ACQUIRE
	to request negotiation; install a corresponding %hold
	shunt and attach this packet to the %hold

For other eroutes, the SAID is printed as a triple: protocol (three
letters), SPI (32-bit number in hex), and destination IP address.
Protocols include:

tun	IP in IP encapsulation (used for most tunnels)
esp	ESP encapsulation -- part of an IPSEC SA group
ah	AH packet authentication -- part of an IPSEC SA group

So, looking at our sample eroutes:

10         10.2.1.0/24      -> 0.0.0.0/0          => %trap

	This is a TRAP (int0x104) shunt eroute.  It was installed by
	Pluto so that it can catch all traffic from its client subnet
	to the world at large.  Ten outbound packets have been trapped.

259        10.2.1.115/32    -> 10.19.75.161/32    => tun0x1002@10.19.75.145

	This is a tunnel eroute: packets from 10.2.1.115 (within
	our client subnet) going to 10.19.75.161 will be encrypted
	and sent to the peer SG 10.19.75.145.  This was the product
	of an Opportunistic negotiation (a hint is that each client
	subnet has only one member).  259 packets have been sent
	through this tunnel.

71         10.44.73.97/32   -> 0.0.0.0/0          => %trap

	This is another TRAP shunt eroute.  It is to catch traffic
	from the Security Gateway to the world.  It has caught
	71 outbound packets.

4119       10.44.73.97/32   -> 10.114.121.41/32   => %pass

	This is a %pass (0x100) shunt eroute.  It was installed when an
	attempted Opportunistic negotiation failed because the reverse
	domain of 10.114.121.41 had no suitable TXT record.  4119
	outbound packets have been passed.


Important Limitations
=====================

Pluto's DNS lookup is synchronous (single-threaded).  Not only does
this slow things down, but it turns out that in extreme cases where
there are a lot of ACQUIRE messages from KLIPS at once, some of those
messages can be lost and communications will be blocked by the %hold
eroute that Pluto doesn't know about.  Pluto now looks every 2 minutes
for any %holds that it missed.

DNS lookup is not verified -- we don't use Secure DNS.  A spoofed DNS
could compromise Opportunism.

There are several new opportunities for Denial of Service attacks.
For example, a Bad Guy could spray our system with pings with forged
source addresses.  For each unique source address, our system would do
a (synchronous!) DNS lookup.

Once a %pass eroute is added for a failed negotiation, it will stay
until it has been inactive for about 15 minutes.  The only activity
that counts is outbound -- not surprising since a %pass only affects
outbound traffic.

If a destination's DNS entry specifies the information we need for
negotiation, Pluto will not let communications proceed without
negotiating a Security Tunnel.

There is currently no way to tear down a tunnel that is no longer in
use.  To add insult to injury, when the lifetime is about to be
exceeded, the initiating Pluto will rekey!  Restarting will clear
these out.  rekey=no doesn't solve this since SA expiry would be
uncoordinated and hence cause packets to be lost.

If one side of a Security Tunnel restarts, but doesn't initiate
negotiation with its peer, the peer will not be able to communicate
with it until the peer thinks the tunnel needs rekeying due to
lifetime, or the restarted Security Gateway decides to negotiate for
its own reasons.

It isn't clear what firewall policies make sense with Opportunism.

If VPN and Opportunism connections coexist, security policies
implemented via a firewall can only distinguish traffic by IP address.
