Subject: Re: On dynamic NSEC

From: Paul Vixie <[email-masked]>
Date: Fri, 12 Nov 2004 17:34:37 +0000

> > ...
> > (not that a synthetic rr would have a nonzero ttl in the first place.)
> 
> OK. Let me simplify a bit, drop the caching nameservers:
> 
> Take a zone example.com:
> *		MX	foo
> bar		MX	baz
> dummy		NULL
> dummy2	TXT	"fred"
> 
> It uses NSEC epsilon.  That means for every possible label, there is a
> synthetic NSEC record, and per Rob's proposal, also a synthetic NULL
> record.  Synthetic I am taking to mean "not in the original zone
> loaded into the nameserver, but created algorithmically so it appears
> under all other circumstances to be in the zone"

with the proviso that i didn't understand the need for a NULL RR, i'm
tracking you so far.

> I then make the following queries:
> 1. type=NSEC, label=xxx.example.com
> 2. type=MX, label=xxx.example.com
> 3. type=ANY, label=xxx.example.com
> 4. type=MX, label=dummy.example.com
> 5. type=MX, label=dummy2.example.com
> 
> What do I get?
> 
> Surely type 1 HAS to return (at least)
> 	xxx	IN	NSEC	S(xxx)
> or the whole epsilon NSEC stuff doesn't work

given that there is a wildcard, there will be no NXDOMAINs for this zone.
therefore every NSEC will have a real owner name.  so, i'm with you so far.

each of queries (1), (2), and (3) will produce the same NSEC result, but
with different RRtypes claimed at the ownername.  which is another very fine
reason why client-side negative caching based on previously cached NSEC RRs
won't work, and thus i renew my claim that wildcarding should be done on the
client side rather than the server side.  (but that's a different windmill.)

> Surely (2) is indistinguishable from (4) if there is a NULL record
> synthesized?

i don't know why you'd ever synthesize a NULL RR.  i don't like NULL RRs at
all, but in your example you made the NULL RR a real RR, not a synthetic one.
therefore query (4) would get a NOERROR/NODATA reply and the wildcard would
not be part of the choice of what to return -- because the qname actually
does exist.

> Surely (2) is indistinguishable from (4) and (5) unless NSECs are
> processed differently from NULL's in the wildcard algorithm?

response to (5) would be NOERROR/NODATA as with (4).  i appear to be lost.
can we have this discussion over again, except this time can you do it without
the synthetic NULL RRs, and can you explain the non-dnssec parts of each reply
so i'll know what covering dnssec metadata will be applied?

--
to unsubscribe send a message to [email-masked] with
the word 'unsubscribe' in a single line as the message text body.
archive: <http://ops.ietf.org/lists/namedroppers/>

--
to unsubscribe send a message to [email-masked] with
the word 'unsubscribe' in a single line as the message text body.
archive: <http://ops.ietf.org/lists/namedroppers/>

---

From: Alex Bligh <[email-masked]>
Date: Thu, 11 Nov 2004 20:47:44 +0000

--On 11 November 2004 14:29 -0500 Rob Austein <[email-masked]> wrote:

> At Thu, 11 Nov 2004 16:56:49 +0000, Alex Bligh wrote:
>>
>> >> This text imply to me that you cannot invent new owner names for NSEC.
>> >
>> > Um, no, at worst it means that when you synthesize an NSEC RR you also
>> > have to synthesize something else, eg, a NULL RR.
>>
>> Nope don't think so - that changes wildcard behaviour.
>
> In what way does the existance of a synthetic NULL RRset change the
> wildcard behavior compared to the behavior if only the synthetic NSEC
> were present?  At least one of us is confused.

Yes.

I am assuming that the reason for the assumption Simon Josefsson mentioned:
under section 2.3 of protocol-09:

   Each owner name in the zone which has authoritative data or a
   delegation point NS RRset MUST have an NSEC resource record.
...
   An NSEC record (and its associated RRSIG RRset) MUST NOT be the only
   RRset at any particular owner name.  That is, the signing process
   MUST NOT create NSEC or RRSIG RRs for owner names nodes which were
   not the owner name of any RRset before the zone was signed.

is that NOT doing so would require a change to wildcard behaviour,
and thus that in order to support epsilon NSECs, wildcard behaviour
would be changed so presence of an NSEC record "only" would not
"count" for the purposes of determining whether a wild-card was
applicable. If this is the case (i.e. if the appropriate change
is made to the wildcard treatment algorithm), then the restrictions
in 2.3 can be lifted.

However, if NO change to the wildcard processing stuff is made,
then as you point out they are equivalent, and (as far as I can
see) NSEC epsilons break wildcards. I seem to remember greater
minds than mine pointed this out at the time when we were considering
NSEC 'white lies' which is why the requirement in section 2.3 never
got removed at the time (because we didn't want to fiddle with
wildcard processing at that late stage).

The reason for the breakage is quite simple: Under NSEC epsilon,
every label must have an associated record returned on a query -
either it "really" exists (in which case by definition there is
a record), or it "really" does not (in which case by assumption - NSEC
epilson) there is an epsilon record pointing to the records successor.
Under such circumstances, the wildcard record is never the closest
encloser of anything (as the closest encloser is either an epsilon
NSEC or a real record).

So I'd been working under the assumption the wildcard lookup would
be changed to exclude NSEC only labels (hence NULL and NSEC aren't
equivalent). If my assumption is wrong, then you are indeed right,
NULL and NSEC *will* break wildcards - in exactly the same way,
and, AFAICT, completely.

But I may have missed something here.

>> I think that's even trivially exploitable, EG
>>
>> $ORIGIN example.com
>>
>> foo	IN	MX	mail-1.evilempire.com
>> *	IN	MX	mail-2.goodempire.com
>>
>> Two users (Evil Ed, and User Ursula), share the same caching resolver.
>>
>> Ursula wants to send mail to [email-masked]
>>
>> Ed works out P(fred.example.com), S(fred.example.com), and queries for
>> them
>
> Queries with what QTYPE?

Not sure it particularly matters, but let's say ANY.

>> and for fred.example.com. example.com's nameserver returns an NSEC record
>> that mentions fred.example.com, and by your assumption synthesizes not
>> only the NSEC record but also a NULL RR, for fred.example.com. The NULL
>> RR is then cached by the caching nameserver.
>
> Given suitable definitions of the P() and S() functions and a suitable
> choice of RR type (something that is very unlikely to occur in normal
> use, eg, NULL), the name server in the above scenario has several
> hints that something evil is going on, and might choose to return
> RCODE 5 (refused) rather than participating in the attack. :)

How does that work algorithmically? I can only see heuristic solutions
to this, and it's a reasonable attack vector as far as I can see,
with potentially disastrous results.

If you are trying to change the use of NULL above in wildcard processing,
you might as well just change the wording and the wildcard algorithm for
NSEC instead and drop 2.3. NULL is actually USEFUL to indicate an
exception to a wildcard, as someone (Ed Lewis I think) pointed out to
me here not so long ago.

> If for some reason it seems reasonable to return a synthetic NULL RR
> in such a case (unlikely) it should probably have a TTL of zero.
>
> In practice, the only real difference between this and the epsilon
> solution as already described is that the bit corresponding to the
> NULL RR type would be turned on in the NSEC bitvector.

Why not just except NSECs from the wildcard algorithm, and drop the
text in 2.3? That's useful for both NSEC epsilon and NSEC' hashes.

Alex