Skip to content

Instantly share code, notes, and snippets.

@bortzmeyer
Created April 6, 2010 19:48
Show Gist options
  • Save bortzmeyer/358004 to your computer and use it in GitHub Desktop.
Save bortzmeyer/358004 to your computer and use it in GitHub Desktop.
-- Pseudo-code (syntax more or less Ada-like) to show what happens to
-- a DNS resolver when the root is signed and the responses become
-- larger.
-- Background information:
-- https://www.dns-oarc.net/oarc/services/replysizetest
-- RFC 5625
-- http://www.iis.se/docs/Routertester_en.Pdf
-- SSAC report #35 http://www.icann.org/committees/security/sac035.pdf
-- Stephane Bortzmeyer <bortzmeyer@nic.fr>
-- Variables used:
-- EDNS0: boolean, indicates if the resolver sends EDNS0 requests
-- EDNS0_Size: positive integer, the buffer size advertised by EDNS0
-- DO_DNSSEC: boolean, the DO flag indicating DNSSEC support by the resolver
-- Min_Response_Size: integer, the minimum (after dropping
-- unnecessary RR) size of the DNS response sent by the authoritative
-- server
-- Clean_path_for_fragments: boolean, indicates that UDP fragments
-- can travel from the authoritative name server to the resolver
-- Clean_Path_For_EDNS0: boolean, indicates that EDNS0 responses
-- (which may be larger than 512 bytes) can travel from the
-- authoritative name server to the resolver
-- Can_TCP: boolean, indicates that the resolver can ask through TCP
-- (which implies a clean TCP patch and an authoritative name server
-- which accept TCP)
-- The code can be executed several times for one request, for
-- instance because a resolver tries first with UDP, then retries
-- with TCP.
if UDP then
if EDNS0 then
if EDNS0_Size > MTU then
-- BIND default, EDNS0_size = 4096 bytes
if DO_DNSSEC then
-- BIND default, even if not configured for validation
if Min_Response_Size > MTU then -- Not the case today with the root
if Clean_Path_for_fragments then
OK;
else
-- After a while BIND will switch to no-EDNS0, start over
Retry("Responses not received may be because of EDNS0");
end if;
elsif Min_Response_Size > 512 then
-- No fragmentation will occur
if Clean_Path_For_EDNS0 then
OK; -- That's the normal and typical case for a BIND resolver today,
-- with the signed root
else
Retry("Responses not received may be because of EDNS0");
end if;
else -- Won't occur today, responses from the root are already > 512
OK;
end if;
else
-- Without DNSSEC, responses wil be shorter but some
-- responses from the root already are > 512
if Min_Response_Size > MTU then
-- Unlikely, without DNSSEC
if Clean_Path_for_fragments then
OK;
else
Retry("Responses not received may be because of EDNS0");
end if;
elsif Min_Response_Size > 512 then
if Clean_Path_For_EDNS0 then
OK;
else
Retry("Responses not received may be because of EDNS0");
end if;
else -- Most common case today, the typical unsigned answer is 100-200 bytes
OK;
end if;
end if;
elsif EDNS0_Size >= 512 then -- But lower than the MTU
if DO_DNSSEC then
if Min_Response_Size > EDNS0_Size then
-- This assumes that DNS packets with TC bit set arrive safely, not always true
Retry("Truncation");
elsif Min_Response_Size >= 512 then
if Clean_Path_for_EDNS0 then
OK;
else
Retry("Responses not received may be because of EDNS0");
end if;
else -- Won't often occur today, some responses from the root are already > 512
OK; -- Not always, some middleboxes may block EDNS0 responses, even with size <= 512
end if;
else
-- No DNSSEC, so replies will probably be under EDNS0_Size
if Min_Response_Size > 512 then
if Clean_Path_For_EDNS0 then
OK;
else
Retry("Responses not received may be because of EDNS0");
end if;
else
OK;
end if;
end if;
else -- EDNS0 with size < 512
Error("Stupid value");
end if;
else -- No EDNS0 at all
if Min_Response_Size > 512 then
Retry("Truncation");
else
OK;
end if;
end if;
else -- TCP
if Can_TCP then
OK; -- But higher latency and higher load on authoritative name servers
else
Error("Fallback to TCP failed");
end if;
end if;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment