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

RCSID $Id: opportunism.howto,v 1.8 2001/06/15 02:38:09 dhr Exp $

D. Hugh Redelmeier


FreeS/WAN, the LINUX IPSEC implementation, is intended to allow
systems to connect through secure tunnels without prearrangement.
This HowTo is intended to be a guide to setting up a system to enable
this feature, which we call opportunism.  Much more information about
FreeS/WAN is provided at http://www.freeswan.org.

You are expected to already have built and used FreeS/WAN.  This
document is only intended to describe the support for opportunism
after release 1.9.

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
======

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.  Note that throughout this document, the term
"Security Gateway" is meant to include a machine that is protecting
its own traffic.

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.  It is quite possible for Source and Initiator to
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
hold 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 the 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.  All you need to
do is copy the output of the command
	ipsec showhostkey
into the zone information for the reverse-map.  Here is an example,
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/

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 is willing to do this too.  Remember:
this command must be run on the Security Gateway where the
ipsec.secrets file resides.  In this case, you must tell the command
what IP address to in the TXT record:
	ipsec showhostkey --txt 10.11.12.13
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.

This output must be added 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 (but the Source
must!).  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.  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.

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 like an ordinary conn.  It more closely resembles
a Road Warrior conn (one that has a wildcard %any specified as the
other Security Gateway).  But in this case, both the other Security
Gateway AND its client are unknown.

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

conn us-to-anyone	# for our Security Gatway
	left=%defaultroute	# our SG (defaults leftnexthop too)
	right=%opportunistic

(%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.

To enable these conns for inbound opportunistic negotiation, it must be
--added:
	ipsec auto --add us-to-anyone
	ipsec auto --add ours-to-anyone
If you want this automatically done on startup, put
	auto=add
in the us-to-anyone conn.

To enable these conns for outbound opportunistic negotiation, it must
be both --added and --routed.  Outbound packets will then be trapped
and will trigger negotiation:
	ipsec auto --add us-to-anyone
	ipsec auto --add ours-to-anyone
	ipsec auto --route us-to-anyone
	ipsec auto --route ours-to-anyone
If you want this automatically done on startup, put
	auto=route
in the us-to-anyone conn (this feature may be renamed in the future).


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

There is a serious chicken-and-egg problem.  Outbound Opportunism blocks
communication with an IP address until it 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.

- you could explicitly create an IPSEC connection to your DNS server.
  Just be sure that it need not access DNS to find the IP addresses
  or RSA public keys.

- 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 us-to-anyone
You must also add a type=passthrough eroute specifically for
us-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.

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.  I like to use
	ipsec auto --status
and also to examine the kernel's eroute table.

The "file" /proc/net/ipsec_eroute contains a description of all the
eroutes in the kernel (see also ipsec_look(8)).  Here is an example:

10         10.3.2.1.0/24    -> 0.0.0.0/0          => %trap
259        10.3.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.3.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.3.2.1.115/32  -> 10.19.75.161/32    => tun0x1002@10.19.75.145

	This is a tunnel eroute: packets from 10.3.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.

If one side of a Security Tunnel restarts, but doesn't initiate
negotiation with the other side, the other side will not be able to
communicate with it until it thinks the tunnel needs rekeying due to
lifetime.

KLIPS does not check that packets coming in through a tunnel have
source and destination addresses suitable for that tunnel.  This part
of "inbound policy checking" is not implemented.  A message from one
peer could have been forged by another peer.  It is even possible to
forge the addresses so that it looks as if the packet came from inside
your net and is to go out, possibly through another tunnel!  So you
ought not to trust information more just because it appears to have
come from a source covered by a Security Tunnel.  This makes it
difficult to safely combine a VPN with Opportunism.

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