Re: Use of New Mask Mechanism
2005-03-26 10:00:48
Radu Hociung wrote:
David MacQuigg wrote:
The DNS Load Research thread is getting way to long with too many
topics. Let's start a new thread to work out the details of how the
new mask mechanism should be used. Radu has a good start with his
procedural outline below. I inserted one added condition, based on my
current understanding of DNS, which may be flawed.
Great idea. Thank you! :)
SPF users should be urged to keep their compiled records simple (list
of IPs only) and shorter than 450 bytes. Our Best Practices document,
and some good examples of large domains like rr.com, should show that
this is possible. The advanced mechanisms should be documented in an
appendix, to be used only for the rare cases where they are truly
needed, like an "SPF Obfuscation Contest" :>)
Yes, Andy has volunteered to kick-start the Best Practices documentation
based on available sources and ideas we have discussed already (If I
understood his offer correctly).
I would suggest that once he's done a first path, including as much info
as he can find, then we all can offer text that has not already been
addressed, or improve the existing text.
I would almost make the 450-byte limit an implementation requirement for
compilers. It is already in the draft.
We might want to consider a different syntax for the mask mechanism,
considering how difficult it has been to explain, even to the experts
on this list. I suggest a simple "not" operator, which complements
whatever follows. -!ip4:65.122.44.0/24 means reject any IP *outside*
of the given block. This term would be evaluated in the normal
sequence, like any other. To be useful, the compiler would always
place it at the beginning of the record.
I'm ok with changing the syntax, but it looked to me that it wasn't the
name of the *modifer* that caused confusion, but functional differences
between it and the existing ip *mechanisms*.
Also. Whatever syntax we chose, it has to be compatible with the current
draft, else existing SPF implementations would break instantly.
The ! between the prefix and the mechanism is not legal according to
current syntax. Also, since we do need a *modifier*, not a *mechanism*,
the syntax for the modifier name is alphanumeric characters only,
followed by '='. Anything can follow the = except space :
modifier = redirect / explanation / unknown-modifier
unknown-modifier = name "=" macro-string
name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )
macro-string = *( macro-expand / macro-literal )
macro-expand = ( "%{" macro-letter transformer *delimiter "}" )
/ "%%" / "%_" / "%-"
macro-literal = %x21-24 / %x26-7E
; visible characters except "%"
macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" /
"c" / "r" / "t"
transformer = *DIGIT [ "r" ]
prefix = "+" / "-" / "?" / "~"
Actually, if I read the above correctly, -m= is not legal. m-= is ok,
but m~= and m?= are not. So lets make it
m = [PREFIX] [IP notation]
where [IP notation] is defined like in the bind man page (man named.conf):
ip_prefix An IP network specified in dotted-decimal
form, followed by "/" and then the number of
bits in the netmask. E.g. 127/8 is the
network 127.0.0.0 with netmask 255.0.0.0.
1.2.3.0/28 is network 1.2.3.0 with netmask
255.255.255.240.
dotted-decimal One or more integers valued 0 through 255
separated only by dots ("."), such as 123,
45.67 or 89.123.45.67.
For IPv6, RFC3513 speficies how the net-blocks should be specified:
"The text representation of IPv6 address prefixes is similar to the
way IPv4 addresses prefixes are written in CIDR notation [CIDR]. An
IPv6 address prefix is represented by the notation:
ipv6-address/prefix-length
where
ipv6-address is an IPv6 address in any of the notations listed
in section 2.2.
prefix-length is a decimal value specifying how many of the
leftmost contiguous bits of the address comprise
the prefix."
ie,
mask-string = [ prefix ] ip-netblock
ip-netblock = as per bind MAN page for IPv4 or RFC3513 for IPv6
Once again, the mask would not work as a mechanism (unless it was in
include, like Frank mentioned), because each mechanism can return a
match. the mask modifiers can return a match only after *all of them*
have been checked against the IP. Think of a mask like m=65/6 m=214/6.
For senders in the 214 net, your proposed -!ip4 mechanism would
wrongfully declare the 214 sources as "FAIL".
Also, I would revert back to my original syntax that allows m=65/6
instead of requiring m=65.0.0.0/6. Both would work of course, but the
simpler syntax would be legal. This is because I don't understand why
that syntax has to be compatible with other systems. Maybe someone can
explain. I think that as long as the checkers recognize the mask
modifier, they will also know (from the draft) how to interpret its
contents.
At 12:15 AM 3/26/2005 -0500, Radu wrote:
Let me quote the rules for creating masks first:
If no compiler
1. there is no masking, or you'd have to insert it manually,
which is inconvenient and error prone.
elseif compiler is used
2. If compiled with cron, or once in a while, -flatten should
not be used. There will be left-over mechanisms whose
resulting IP address may change (administrative gap)
Thus, masks MUST not be added, since while they work initially
they would break the record when the ISP changes their
infrastructure.
3. If compiled with cron, and -flatten not used, but the record
compiles into a list of IPs anyway (ie, you list no mechanisms
that lie outside your adminstrative boundary), then it may
include masks if useful.
Masks should be added to a list of IPs, only if that list is already
too long to fit in one 512-byte DNS response message. In this case, a
mask may allow the SPF check to return a FAIL without initiating a TCP
connection to retrieve the full DNS message.
The compiler currently has an option to specify the max length of an
output SPF string, in case a name server has a lower limit for the
length of TXT records.
So the number of characters allowed by the name server software will
dictate the max length of string that the compiler is configured to
produce. Since the mask has to be in the first record, it will cause the
compiler to shorten the number of bytes used for mechanisms such that
the the top record, including the mask and any other modifiers fits
within the server's TXT record limit.
I am afraid it won't be so easy to provide a clear number like "450".
Bind insists on providing the NS records for the zone with every
response. The more you have, the less room is available for the TXT
record. Also when the domain name is longer, that takes some space away
too. Ie, in the response packet of _s4.ohmi.org, the name takes up 13
bytes, but for a _s4.longer-domain.name.com, it takes more space,
leaving less available for the TXT record.
It looks to me like it will take some work to figure out how many bytes
are available for the TXT record, and what all the variables are.
At ohmi I use 3 name servers and BIND, and the biggest TXT record I can
fit into a 512-byte UDP packet is 357 bytes. YMMV, but it proves that
even a seemingly conservative limit (450 or 400) is not always
appropriate. If I had more slave name servers or a longer domain name,
my usable TXT space would be even less.
So I suspect that for sites that compile their record with a cron job,
they should find a value for the -len parameter that works on their
system. Alternately, the compiler should automatically figure it out.
Do we have any volunteers to take up the task of understanding the DNS
response packet and writing up a report, and a formula/algorithm that
can be used the maximum TXT record size available at an arbitrary
domain? Reading through RFC 1035 may not be enough, and we have to
consider some of the more popular DNS servers to see what their quirks
are (for instance insisting to provide additional "helpful" records even
though doing so requires them to drop to TCP mode).
This is some real research work that must be done sooner or later.
By the way. Since SPF2/PRA records share the same packet space with the
SPF1, we will definately have problems. One of these two MUST move to
their own hostname. For instance _spf.{domain_name} or _spf2.{domain_name}.
Since there are more spf1 records than spf2 records currently published,
it will probably be PRA that must move.
The move could be done in a backwards compatible way:
If the {domainname} TXT query did not return a PRA record, but did
return an SPF1 record, try looking at _spf2.{domain_name}
else
There is no PRA record, don't do the extra query.
We should bring this up to the PRA people before they get too close to
the point of no-changes-acceptable.
4. Masks can only be reliably inserted when your record is
completely in your administrative control, as above, or if
the compiler runs as part of the DNS server.
5. In that case, the record can be safely flattened *only if*
the TTLs of all mechanisms are respected,
including those across the domain boundary. In that case, the
record, and implicitly the mask get regenerated every time
the IP list gets regenerated beause of expired TTLs. So,
the mask always reflects the current record.
Also, there's an additional condition on inserting masks.
6. A mask may only be inserted if all mechanisms that cannot be
compiled into an ip list (those that use the %{l} or %{i} macros)
are brought up into the top TXT record.
In other words, a mask may only be inserted if the remaining
mechanisms in subsequent redirects/includes contain only
IP lists.
end if.
<Prev in Thread] |
Current Thread |
[Next in Thread>
|
- Re: Re: DNS load research, (continued)
- Use of New Mask Mechanism, David MacQuigg
- Re: Use of New Mask Mechanism, Radu Hociung
- Re: Use of New Mask Mechanism,
Radu Hociung <=
- Re: Use of New Mask Mechanism, David MacQuigg
- Re: Use of New Mask Mechanism, David MacQuigg
- Re: Use of New Mask Mechanism, Radu Hociung
- Re: Use of New Mask Mechanism, David MacQuigg
- Re: Use of New Mask Mechanism, Radu Hociung
- Re: Use of New Mask Mechanism, David MacQuigg
- Re: Use of New Mask Mechanism, Radu Hociung
- Re: Use of New Mask Mechanism, David MacQuigg
- Re: Use of New Mask Mechanism, Radu Hociung
- Need for Complexity in SPF Records, David MacQuigg
|
|
|