515 lines
27 KiB
Plaintext
515 lines
27 KiB
Plaintext
Implementing Opportunistic Encryption
|
|
|
|
Henry Spencer & D. Hugh Redelmeier
|
|
|
|
Version 4+, 15 Dec 2000
|
|
|
|
|
|
|
|
Updates
|
|
|
|
Major changes since last version: "Negotiation Issues" section discussing
|
|
some interoperability matters, plus some wording cleanup. Some issues
|
|
arising from discussions at OLS are not yet resolved, so there will almost
|
|
certainly be another version soon.
|
|
|
|
xxx incoming could be opportunistic or RW. xxx any way of saving unaware
|
|
implementations??? xxx compression needs mention.
|
|
|
|
|
|
|
|
Introduction
|
|
|
|
A major long-term goal of the FreeS/WAN project is opportunistic
|
|
encryption: a security gateway intercepts an outgoing packet aimed at a
|
|
new remote host, and quickly attempts to negotiate an IPsec tunnel to that
|
|
host's security gateway, so that traffic can be encrypted and
|
|
authenticated without changes to the host software. (This generalizes
|
|
trivially to the end-to-end case where host and security gateway are one
|
|
and the same.) If the attempt fails, the packet (or a retry thereof)
|
|
passes through in clear or is dropped, depending on local policy.
|
|
Prearranged tunnels bypass all this, so static VPNs can coexist with
|
|
opportunistic encryption.
|
|
|
|
xxx here Although significant intelligence about all this is necessary at the
|
|
initiator end, it's highly desirable for little or no special machinery
|
|
to be needed at the responder end. In particular, if none were needed,
|
|
then a security gateway which knows nothing about opportunistic encryption
|
|
could nevertheless participate in some opportunistic connections.
|
|
|
|
IPSEC gives us the low-level mechanisms, and the key-exchange machinery,
|
|
but there are some vague spots (to put it mildly) at higher levels.
|
|
|
|
One constraint which deserves comment is that the process of tunnel setup
|
|
should be quick. Moreover, the decision that no tunnel can be created
|
|
should also be quick, since that will be a common case, at least in the
|
|
beginning. People will be reluctant to use opportunistic encryption if it
|
|
causes gross startup delays on every connection, even connections which see
|
|
no benefit from it. Win or lose, the process must be rapid.
|
|
|
|
There's nothing much we can do to speed up the key exchange itself. (The
|
|
one thing which conceivably might be done is to use Aggressive Mode, which
|
|
involves fewer round trips, but it has limitations and possible security
|
|
problems, and we're reluctant to touch it.) What we can do, is to make the
|
|
other parts of the setup process as quick as possible. This desire will
|
|
come back to haunt us below. :-)
|
|
|
|
A further note is that we must consider the processing at the responder
|
|
end as well as the initiator end.
|
|
|
|
Several pieces of new machinery are needed to make this work. Here's a
|
|
brief list, with details considered below.
|
|
|
|
+ Outgoing Packet Interception. KLIPS needs to intercept packets which
|
|
likely would benefit from tunnel setup, and bring them to Pluto's
|
|
attention. There needs to be enough memory in the process that the same
|
|
tunnel doesn't get proposed too often (win or lose).
|
|
|
|
+ Smart Connection Management. Not only do we need to establish tunnels
|
|
on request, once a tunnel is set up, it needs to be torn down eventually
|
|
if it's not in use. It's also highly desirable to detect the fact that it
|
|
has stopped working, and do something useful. Status changes should be
|
|
coordinated between the two security gateways unless one has crashed,
|
|
and even then, they should get back into sync eventually.
|
|
|
|
+ Security Gateway Discovery. Given a packet destination, we must decide
|
|
who to attempt to negotiate a tunnel with. This must be done quickly, win
|
|
or lose, and reliably even in the presence of diverse network setups.
|
|
|
|
+ Authentication Without Prearrangement. We need to be sure we're really
|
|
talking to the intended security gateway, without being able to prearrange
|
|
any shared information. He needs the same assurance about us.
|
|
|
|
+ More Flexible Policy. In particular, the responding Pluto needs a way
|
|
to figure out whether the connection it is being asked to make is okay.
|
|
This isn't as simple as just searching our existing conn database -- we
|
|
probably have to specify *classes* of legitimate connections.
|
|
|
|
Conveniently, we have a three-letter acronym for each of these. :-)
|
|
|
|
Note on philosophy: we have deliberately avoided providing six different
|
|
ways to do each step, in favor of specifying one good one. Choices are
|
|
provided only when they appear to be necessary. (Or when we are not yet
|
|
quite sure yet how best to do something...)
|
|
|
|
|
|
|
|
OPI, SCM
|
|
|
|
Smart Connection Management would be quite useful even by itself,
|
|
requiring manual triggering. (Right now, we do the manual triggering, but
|
|
not the other parts of SCM.) Outgoing Packet Interception fits together
|
|
with SCM quite well, and improves its usefulness further. Going through a
|
|
connection's life cycle from the start...
|
|
|
|
OPI itself is relatively straightforward, aside from the nagging question
|
|
of whether the intercepted packet is put on hold and then released, or
|
|
dropped. Putting it on hold is preferable; the alternative is to rely on
|
|
the application or the transport layer re-trying. The downside of packet
|
|
hold is extra resources; the downside of packet dropping is that IPSEC
|
|
knows *when* the packet can finally go out, and the higher layers don't.
|
|
Either way, life gets a little tricky because a quickly-retrying
|
|
application may try more than once before we know for sure whether a
|
|
tunnel can be set up, and something has to detect and filter out the
|
|
duplications. Some ARP implementations use the approach of keeping one
|
|
packet for an as-yet-unresolved address, and throwing away any more that
|
|
appear; that seems a reasonable choice.
|
|
|
|
(Is it worth intercepting *incoming* packets, from the outside world, and
|
|
attempting tunnel setup based on them? Perhaps... if, and only if, we
|
|
organize AWP so that non-opportunistic SGs can do it somehow. Otherwise,
|
|
if the other end has not initiated tunnel setup itself, it will not be
|
|
prepared to do so at our request.)
|
|
|
|
Once a tunnel is up, packets going into it naturally are not intercepted
|
|
by OPI. However, we need to do something about the flip side of this too:
|
|
after deciding that we *cannot* set up a tunnel, either because we don't
|
|
have enough information or because the other security gateway is
|
|
uncooperative, we have to remember that for a while, so we don't keep
|
|
knocking on the same locked door. One plausible way of doing that is to
|
|
set up a bypass "tunnel" -- the equivalent of our current %passthrough
|
|
connection -- and have it managed like a real SCM tunnel (finite lifespan
|
|
etc.). This sounds a bit heavyweight, but in practice, the alternatives
|
|
all end up doing something very similar when examined closely. Note that
|
|
we need an extra variant of this, a block rather than a bypass, to cover
|
|
the case where local policy dictates that packets *not* be passed through;
|
|
we still have to remember the fact that we can't set up a real tunnel.
|
|
|
|
When to tear tunnels down is a bit problematic, but if we're setting up a
|
|
potentially unbounded number of them, we have to tear them down *somehow*
|
|
*sometime*. It seems fairly obvious that we set a tentative lifespan,
|
|
probably fairly short (say 1min), and when it expires, we look to see if
|
|
the tunnel is still in use (say, has had traffic in the last half of the
|
|
lifespan). If so, we assign it a somewhat longer lifespan (say 10min),
|
|
after which we look again. If not, we close it down. (This lifespan is
|
|
independent of key lifetime; it is just the time when the tunnel's future
|
|
is next considered. This should happen reasonably frequently, unlike
|
|
rekeying, which is costly and shouldn't be too frequent.) Multi-step
|
|
backoff algorithms probably are not worth the trouble; looking every
|
|
10min doesn't seem onerous.
|
|
|
|
For the tunnel-expiry decision, we need to know how long it has been since
|
|
the last traffic went through. A more detailed history of the traffic
|
|
does not seem very useful; a simple idle timer (or last-traffic timestamp)
|
|
is both necessary and sufficient. And KLIPS already has this.
|
|
|
|
As noted, default initial lifespan should be short. However, Pluto should
|
|
keep a history of recently-closed tunnels, to detect cases where a tunnel
|
|
is being repeatedly re-established and should be given a longer lifespan.
|
|
(Not only is tunnel setup costly, but it adds user-visible delay, so
|
|
keeping a tunnel alive is preferable if we have reason to suspect more
|
|
traffic soon.) Any tunnel re-established within 10min of dying should have
|
|
10min added to its initial lifespan. (Just leaving all tunnels open longer
|
|
is unappealing -- adaptive lifetimes which are sensitive to the behavior
|
|
of a particular tunnel are wanted. Tunnels are relatively cheap entities
|
|
for us, but that is not necessarily true of all implementations, and there
|
|
may also be administrative problems in sorting through large accumulations
|
|
of idle tunnels.)
|
|
|
|
It might be desirable to have detailed information about the initial
|
|
packet when determining lifespans. HTTP connections in particular are
|
|
notoriously bursty and repetitive.
|
|
|
|
Arguably it would be nice to monitor TCP connection status. A still-open
|
|
TCP connection is almost a guarantee that more traffic is coming, while
|
|
the closing of the only TCP connection through a tunnel is a good hint
|
|
that none is. But the monitoring is complex, and it doesn't seem worth
|
|
the trouble.
|
|
|
|
IKE connections likewise should be torn down when it appears the need has
|
|
passed. They should linger longer than the last tunnel they administer,
|
|
just in case they are needed again; the cost of retaining them is low. An
|
|
SG with only a modest number of them open might want to simply retain each
|
|
until rekeying time, with more aggressive management cutting in only when
|
|
the number gets large. (They should be torn down eventually, if only to
|
|
minimize the length of a status report, but rekeying is the only expensive
|
|
event for them.)
|
|
|
|
It's worth remembering that tunnels sometimes go down because the other
|
|
end crashes, or disconnects, or has a network link break, and we don't get
|
|
any notice of this in the general case. (Even in the event of a crash and
|
|
successful reboot, we won't hear about it unless the other end has
|
|
specific reason to talk IKE to us immediately.) Of course, we have to
|
|
guard against being too quick to respond to temporary network outages,
|
|
but it's not quite the same issue for us as for TCP, because we can tear
|
|
down and then re-establish a tunnel without any user-visible effect except
|
|
a pause in traffic. And if the other end does go down and come back up,
|
|
we and it can't communicate *at all* (except via IKE) until we tear down
|
|
our tunnel.
|
|
|
|
So... we need some kind of heartbeat mechanism. Currently there is none
|
|
in IKE, but there is discussion of changing that, and this seems like the
|
|
best approach. Doing a heartbeat at the IP level will not tell us about a
|
|
crash/reboot event, and sending heartbeat packets through tunnels has
|
|
various complications (they should stop at the far mouth of the tunnel
|
|
instead of going on to a subnet; they should not count against idle
|
|
timers; etc.). Heartbeat exchanges obviously should be done only when
|
|
there are tunnels established *and* there has been no recent incoming
|
|
traffic through them. It seems reasonable to do them at lifespan ends,
|
|
subject to appropriate rate limiting when more than one tunnel goes to the
|
|
same other SG. When all traffic between the two ends is supposed to go
|
|
via the tunnel, it might be reasonable to do a heartbeat -- subject to a
|
|
rate limiter to avoid DOS attacks -- if the kernel sees a non-tunnel
|
|
non-IKE packet from the other end.
|
|
|
|
If a heartbeat gets no response, try a few (say 3) pings to check IP
|
|
connectivity; if one comes back, try another heartbeat; if it gets no
|
|
response, the other end has rebooted, or otherwise been re-initialized,
|
|
and its tunnels should be torn down. If there's no response to the pings,
|
|
note the fact and try the sequence again at the next lifespan end; if
|
|
there's nothing then either, declare the tunnels dead.
|
|
|
|
Finally... except in cases where we've decided that the other end is dead
|
|
or has rebooted, tunnel teardown should always be coordinated with the
|
|
other end. This means interpreting and sending Delete notifications, and
|
|
also Initial-Contacts. Receiving a Delete for the other party's tunnel
|
|
SAs should lead us to tear down our end too -- SAs (SA bundles, really)
|
|
need to be considered as paired bidirectional entities, even though the
|
|
low-level protocols don't think of them that way.
|
|
|
|
|
|
|
|
SGD, AWP
|
|
|
|
Given a packet destination, how do we decide who to (attempt to) negotiate
|
|
a tunnel with? And as a related issue, how do the negotiating parties
|
|
authenticate each other? DNSSEC obviously provides the tools for the
|
|
latter, but how exactly do we use them?
|
|
|
|
Having intercepted a packet, what we know is basically the IP addresses of
|
|
source and destination (plus, in principle, some information about the
|
|
desired communication, like protocol and port). We might be able to map
|
|
the source address to more information about the source, depending on how
|
|
well we control our local networks, but we know nothing further about the
|
|
destination.
|
|
|
|
The obvious first thing to do is a DNS reverse lookup on the destination
|
|
address; that's about all we can do with available data. Ideally, we'd
|
|
like to get all necessary information with this one DNS lookup, because
|
|
DNS lookups are time-consuming -- all the more so if they involve a DNSSEC
|
|
signature-checking treewalk by the name server -- and we've got to hurry.
|
|
While it is unusual for a reverse lookup to yield records other than PTR
|
|
records (or possibly CNAME records, for RFC 2317 classless delegation),
|
|
there's no reason why it can't.
|
|
|
|
(For purposes like logging, a reverse lookup is usually followed by a
|
|
forward lookup, to verify that the reverse lookup wasn't lying about the
|
|
host name. For our purposes, this is not vital, since we use stronger
|
|
authentication methods anyway.)
|
|
|
|
While we want to get as much data as possible (ideally all of it) from one
|
|
lookup, it is useful to first consider how the necessary information would
|
|
be obtained if DNS lookups were instantaneous. Two pieces of information
|
|
are absolutely vital at this point: the IP address of the other end's
|
|
security gateway, and the SG's public key*.
|
|
|
|
(* Actually, knowledge of the key can be postponed slightly -- it's not
|
|
needed until the second exchange of the negotiations, while we can't even
|
|
start negotiations without knowing the IP address. The SG is not
|
|
necessarily on the plain-IP route to the destination, especially when
|
|
multiple SGs are present.)
|
|
|
|
Given instantaneous DNS lookups, we would:
|
|
|
|
+ Start with a reverse lookup to turn the address into a name.
|
|
|
|
+ Look for something like RFC-2782 SRV records using the name, to find out
|
|
who provides this particular service. If none comes back, we can abandon
|
|
the whole process.
|
|
|
|
+ Select one SRV record, which gives us the name of a target host (plus
|
|
possibly one or more addresses, if the name server has supplied address
|
|
records as Additional Data for the SRV records -- this is recommended
|
|
behavior but is not required).
|
|
|
|
+ Use the target name to look up a suitable KEY record, and also address
|
|
record(s) if they are still needed.
|
|
|
|
This gives us the desired address(es) and key. However, it requires three
|
|
lookups, and we don't even find out whether there's any point in trying
|
|
until after the second.
|
|
|
|
With real DNS lookups, which are far from instantaneous, some optimization
|
|
is needed. At the very least, typical cases should need fewer lookups.
|
|
|
|
So when we do the reverse lookup on the IP address, instead of asking for
|
|
PTR, we ask for TXT. If we get none, we abandon opportunistic
|
|
negotiation, and set up a bypass/block with a relatively long life (say
|
|
6hr) because it's not worth trying again soon. (Note, there needs to be a
|
|
way to manually force an early retry -- say, by just clearing out all
|
|
memory of a particular address -- to cover cases where a configuration
|
|
error is discovered and fixed.)
|
|
|
|
xxx need to discuss multi-string TXTs
|
|
|
|
In the results, we look for at least one TXT record with content
|
|
"X-IPsec-Server(nnn)=a.b.c.d kkk", following RFC 1464 attribute/value
|
|
notation. (The "X-" indicates that this is tentative and experimental;
|
|
this design will probably need modification after initial experiments.)
|
|
Again, if there is no such record, we abandon opportunistic negotiation.
|
|
|
|
"nnn" and the parentheses surrounding it are optional. If present, it
|
|
specifies a priority (low number high priority), as for MX records, to
|
|
control the order in which multiple servers are tried. If there are no
|
|
priorities, or there are ties, pick one randomly.
|
|
|
|
"a.b.c.d" is the dotted-decimal IP address of the SG. (Suitable extensions
|
|
for IPv6, when the time comes, are straightforward.)
|
|
|
|
"kkk" is either an RSA-MD5 public key in base-64 notation, as in the text
|
|
form of an RFC 2535 KEY record, or "@hhh". In the latter case, hhh is a
|
|
DNS name, under which one Host/Authentication/IPSEC/RSA-MD5 KEY record is
|
|
present, giving the server's authentication key. (The delay of the extra
|
|
lookup is undesirable, but practical issues of key management may make it
|
|
advisable not to duplicate the key itself in DNS entries for many
|
|
clients.)
|
|
|
|
It unfortunately does appear that the authentication key has to be
|
|
associated with the server, not the client behind it. At the time when
|
|
the responder has to authenticate our SG, it does not know which of its
|
|
clients we are interested in (i.e., which key to use), and there is no
|
|
good way to tell it. (There are some bad ways; this decision may merit
|
|
re-examination after experimental use.)
|
|
|
|
The responder authenticates our SG by doing a reverse lookup on its IP
|
|
address to get a Host/Authentication/IPSEC/RSA-MD5 KEY record. He can
|
|
attempt this in parallel with the early parts of the negotiation (since he
|
|
knows our SG IP address from the first negotiation packet), at the risk of
|
|
having to abandon the attempt and do a different lookup if we use
|
|
something different as our ID (see below). Unfortunately, he doesn't yet
|
|
know what client we will claim to represent, so he'll need to do another
|
|
lookup as part of phase 2 negotiation (unless the client *is* our SG), to
|
|
confirm that the client has a TXT X-IPsec-Server record pointing to our
|
|
SG. (Checking that the record specifies the same key is not important,
|
|
since the responder already has a trustworthy key for our SG.)
|
|
|
|
Also unfortunately, opportunistic tunnels can only have degenerate subnets
|
|
(/32 subnets, containing one host) at their ends. It's superficially
|
|
attractive to negotiate broader connections... but without prearrangement,
|
|
you don't know whether you can trust the other end's claim to have a
|
|
specific subnet behind it. Fixing this would require a way to do a
|
|
reverse lookup on the *subnet* (you cannot trust information in DNS
|
|
records for a name or a single address, which may be controlled by people
|
|
who do not control the whole subnet) with both the address and the mask
|
|
included in the name. Except in the special case of a subnet masked on a
|
|
byte boundary (in which case RFC 1035's convention of an incomplete
|
|
in-addr.arpa name could be used), this would need extensions to the
|
|
reverse-map name space, which is awkward, especially in the presence of
|
|
RFC 2317 delegation. (IPv6 delegation is more flexible and it might be
|
|
easier there.)
|
|
|
|
There is a question of what ID should be used in later steps of
|
|
negotiation. However, the desire not to put more DNS lookups in the
|
|
critical path suggests avoiding the extra complication of varied IDs,
|
|
except in the Road Warrior case (where an extra lookup is inevitable).
|
|
Also, figuring out what such IDs *mean* gets messy. To keep things simple,
|
|
except in the RW case, all IDs should be IP addresses identical to those
|
|
used in the packet headers.
|
|
|
|
For Road Warrior, the RW must be the initiator, since the home-base SG has
|
|
no idea what address the RW will appear at. Moreover, in general the RW
|
|
does not control the DNS entries for his address. This inherently denies
|
|
the home base any authentication of the RW's IP address; the most it can
|
|
do is to verify an identity he provides, and perhaps decide whether it
|
|
wishes to talk to someone with that identity, but this does not verify his
|
|
right to use that IP address -- nothing can, really.
|
|
|
|
(That may sound like it would permit some man-in-the-middle attacks, but
|
|
the RW can still do full authentication of the home base, so a man in the
|
|
middle cannot successfully impersonate home base. Furthermore, a man in
|
|
the middle must impersonate both sides for the DH exchange to work. So
|
|
either way, the IKE negotiation falls apart.)
|
|
|
|
A Road Warrior provides an FQDN ID, used for a forward lookup to obtain a
|
|
Host/Authentication/IPSEC/RSA-MD5 KEY record. (Note, an FQDN need not
|
|
actually correspond to a host -- e.g., the DNS data for it need not
|
|
include an A record.) This suffices, since the RW is the initiator and
|
|
the responder knows his address from his first packet.
|
|
|
|
Certain situations where a host has a more-or-less permanent IP address,
|
|
but does not control its DNS entries, must be treated essentially like
|
|
Road Warrior. It is unfortunate that DNS's old inverse-query feature
|
|
cannot be used (nonrecursively) to ask the initiator's local DNS server
|
|
whether it has a name for the address, because the address will almost
|
|
always have been obtained from a DNS name lookup, and it might be a lookup
|
|
of a name whose DNS entries the host *does* control. (Real examples of
|
|
this exist: the host has a preferred name whose host-controlled entry
|
|
includes an A record, but a reverse lookup on the address sends you to an
|
|
ISP-controlled name whose entry has an A record but not much else.) Alas,
|
|
inverse query is long obsolete and is not widely implemented now.
|
|
|
|
There are some questions in failure cases. If we cannot acquire the info
|
|
needed to set up a tunnel, this is the no-tunnel-possible case. If we
|
|
reach an SG but negotiation fails, this too is the no-tunnel-possible
|
|
case, with a relatively long bypass/block lifespan (say 1hr) since
|
|
fruitless negotiations are expensive. (In the multiple-SG case, it seems
|
|
unlikely to be worthwhile to try other SGs just in case one of them might
|
|
have a configuration permitting successful negotiation.)
|
|
|
|
Finally, there is a sticky problem with timeouts. If the other SG is down
|
|
or otherwise inaccessible, in the worst case we won't hear about this
|
|
except by not getting responses. Some other, more pathological or even
|
|
evil, failure cases can have the same result. The problem is that in the
|
|
case where a bypass is permitted, we want to decide whether a tunnel is
|
|
possible quickly. It gets even worse if there are multiple SGs, in which
|
|
case conceivably we might want to try them all (since some SGs being up
|
|
when others are down is much more likely than SGs differing in policy).
|
|
|
|
The patience setting needs to be configurable policy, with a reasonable
|
|
default (to be determined by experiment). If it expires, we simply have
|
|
to declare the attempt a failure, and set up a bypass/block. (Setting up
|
|
a tentative bypass/block, and replacing it with a real tunnel if remaining
|
|
attempts do produce one, looks attractive at first glance... but exposing
|
|
the first few seconds of a connection is often almost as bad as exposing
|
|
the whole thing!) Such a bypass/block should have a short lifespan, say
|
|
10min, because the SG(s) might be only temporarily unavailable.
|
|
|
|
The flip side of IKE waiting for a timeout is that all other forms of
|
|
feedback, e.g. "host not reachable", should be *ignored*, because you
|
|
cannot trust them! This may need kernel changes.
|
|
|
|
Can AWP be done by non-opportunistic SGs? Probably not; existing SG
|
|
implementations generally aren't prepared to do anything suitable, except
|
|
perhaps via the messy business of certificates. There is one borderline
|
|
exception: some implementations rely on LDAP for at least some of their
|
|
information fetching, and it might be possible to substitute a custom LDAP
|
|
server which does the right things for them. Feasibility of this depends
|
|
on details, which we don't know well enough.
|
|
|
|
[This could do with a full example, a complete packet by packet walkthrough
|
|
including all DNS and IKE traffic.]
|
|
|
|
|
|
|
|
MFP
|
|
|
|
Our current conn database simply isn't flexible enough to cover all this
|
|
properly. In particular, the responding Pluto needs a way to figure out
|
|
whether the connection it is being asked to make is legitimate.
|
|
|
|
This is more subtle than it sounds, given the problem noted earlier, that
|
|
there's no clear way to authenticate claims to represent a non-degenerate
|
|
subnet. Our database has to be able to say "a connection to any host in
|
|
this subnet is okay" or "a connection to any subnet within this subnet is
|
|
okay", rather than "a connection to exactly this subnet is okay". (There
|
|
is some analogy to the Road Warrior case here, which may be relevant.)
|
|
This will require at least a re-interpretation of ipsec.conf.
|
|
|
|
Interim stages of implementation of this will require a bit of thought.
|
|
Notably, we need some way of dealing with the lack of fully signed DNSSEC
|
|
records. Without user interaction, probably the best we can do is to
|
|
remember the results of old fetches, compare them to the results of new
|
|
fetches, and complain and disbelieve all of it if there's a mismatch.
|
|
This does mean that somebody who gets fake data into our very first fetch
|
|
will fool us, at least for a while, but that seems an acceptable tradeoff.
|
|
|
|
|
|
|
|
Negotiation Issues
|
|
|
|
There are various options which are nominally open to negotiation as part
|
|
of setup, but which have to be nailed down at least well enough that
|
|
opportunistic SGs can reliably interoperate. Somewhat arbitrarily and
|
|
tentatively, opportunistic SGs must support Main Mode, Oakley group 5 for
|
|
D-H, 3DES encryption and MD5 authentication for both ISAKMP and IPsec SAs,
|
|
RSA digital-signature authentication with keys between 2048 and 8192 bits,
|
|
and ESP doing both encryption and authentication. They must do key PFS
|
|
in Quick Mode, but not identity PFS.
|
|
|
|
|
|
|
|
What we need from DNS
|
|
|
|
Fortunately, we don't need any new record types or suchlike to make this
|
|
all work. We do, however, need attention to a couple of areas in DNS
|
|
implementation.
|
|
|
|
First, size limits. Although the information we directly need from a
|
|
lookup is not enormous -- the only potentially-big item is the KEY record,
|
|
and there should be only one of those -- there is still a problem with
|
|
DNSSEC authentication signatures. With a 2048-bit key and assorted
|
|
supporting information, we will fill most of a 512-byte DNS UDP packet...
|
|
and if the data is to have DNSSEC authentication, at least one quite large
|
|
SIG record will come too. Plus maybe a TSIG signature on the whole
|
|
response, to authenticate it to our resolver. So: DNSSEC-capable name
|
|
servers must fix the 512-byte UDP limit. We're told there are provisions
|
|
for this; implementation of them is mandatory.
|
|
|
|
Second, interface. It is unclear how the resolver interface will let us
|
|
ask for DNSSEC authentication. We would prefer to ask for "authentication
|
|
where possible", and get back the data with each item flagged by whether
|
|
authentication was available (and successful!) or not available. Having
|
|
to ask separately for authenticated and non-authenticated data would
|
|
probably be acceptable, *provided* both will be cached on the first
|
|
request, so the two requests incur only one set of (non-local) network
|
|
traffic. Either way, we want to see the name server and resolver do this
|
|
for us; that makes sense in any case, since it's important that
|
|
verification be done somewhere where it can be cached, the more centrally
|
|
the better.
|
|
|
|
Finally, a wistful note: the ability to do a limited form of inverse
|
|
queries (an almost forgotten feature), to ask the local name server which
|
|
hostname it recently mapped to a particular address, would be quite
|
|
helpful. Note, this is *NOT* the same as a reverse lookup, and crude
|
|
fakes like putting a dotted-decimal address in brackets do not suffice.
|