1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
# Copyright 2004-2012 SPARTA, Inc. All rights reserved.
# See the COPYING file included with the dnssec-tools package for details.
DNSSEC-Tools
Is your domain secure?
DNSSEC-aware Resolver library
-----------------------------
A library that is capable of sending queries to, and receiving answers
from a DNSSEC-aware name server.
Overview
--------
This library provides the resolver component of the "validating resolver"
(see libval_implementation_notes for details on the validator component).
It provides the interfaces necessary for the validator to fetch answers from
a DNSSEC-aware name server.
Most of the implementation of the resolver component and some for the
validator library was re-used from an older implementation of the secure
resolver library developed at Tislabs. The older implementation was
built as per the older RFC 2535 DNSSEC specifications and modifications
were made so that our library was conformant to the newer specifications
and also contained other feature improvements. The choice to split
the secure resolver functionality into two libraries was made in order to
decouple these two distinct roles. Given a well documented interface between
these two components it could then be possible to plug the
validator component with applications that contain their own native
implementation of the resolver functionality.
The resolver library does not itself perform any recursion. This design
choice was made reduce the complexity within the resolver and keep it
as DNSSEC-agnostic as possible (DNSSEC-relevant information may be present in
the additional section of the referrals). The library still needs to be
'DNSSEC-aware' in that queries that it sends must have the DO bit
(and consequently EDNS0) and CD bits set to permit all DNSSEC-relevant
resource records to be returned in different sections of the DNS response.
The resolver library is built to support both synchronous as well as
asynchronous queries to the DNS. Asynchronous queries are a useful
optimization feature in some instances, where it is possible to
parallize other time-consuming operations while the query is in transit.
The following interfaces are exported by the libsres library (more
details may be found in the libsres manual page):
int query_send( const char *name,
const u_int16_t type,
const u_int16_t class,
struct name_server *nslist,
int edns0_size,
int *trans_id);
int response_recv(int *trans_id,
struct name_server **respondent,
u_int8_t **response,
u_int32_t *response_length);
int get ( const char *name_n,
const u_int16_t type_h,
const u_int16_t class_h,
struct name_server *nslist,
int edns0_size,
struct name_server **respondent,
u_int8_t **response,
u_int32_t *response_length);
int clone_ns(struct name_server **cloned_ns, struct name_server *ns);
int clone_ns_list(struct name_server **ns_list,
struct name_server *orig_ns_list);
void free_name_server (struct name_server **ns);
void free_name_servers (struct name_server **ns);
query_send() and response_recv() provide the asynchronous query/response
interface to the libsres library. A synchronous interface to the
query/response mechanism can be implemented using the above interfaces
as shown below:
if (SR_UNSET == (ret_val = query_send(name, type, class,
nslist, EDNS_UDP_SIZE, &trans_id))) {
do {
ret_val = response_recv(&trans_id, server,
response, response_length);
} while (ret_val == SR_NO_ANSWER_YET);
}
The above code segment forms the essence of the get() interface.
The response_recv() function never blocks. The validator must constantly
poll the resolver to see if any data has arrived.
The clone_ns (clone_ns_list) interface can be used to make a copy of an
existing name server structure (name server list). The free_name_server(s)
methods can be used to free up memory allocated within the name_server
structure.
Other symbols exported by the libsres library include the following:
nametoclass, nametotype,
ns_name_ntop, ns_name_pton, ns_name_unpack ns_parse_ttl,
p_class, p_section p_type
The above are helper functions that have been directly imported from
the BIND library. p_type has been enhanced so that the DNSSEC RR types
(such as DNSKEY, RRSIG, NSEC, NSEC3, DLV) are also recognized.
The libsres libarary perfoms some basic header checking on the
data that it receives from the name server before sending it on to
the application that initiated the query. The rcodes normally returned
by the name server are passed back as return values to the get() and
response_recv() methods. Only two non-error rcodes exist --
the no error RCODE itself and the NXDOMAIN response. The NXDOMAIN
response is considered as "no error" when there are only SOA or NSEC
records in the authority section (proof of non-existence).
The query transmission framework
--------------------------------
The brief algorithm is as given below. This logic is invoked each time a
call is made to the res_io_accept method().
1. while there are more name servers to query
1.1. Send the query to the first name server and wait for ns.ns_retrans
seconds
1.2. If there is no response, send the query to the next name server and
increment the delay for the first name server by its current
ns_retrans
1.3. If the number of retries for a name server has exceeded ns.ns_retry
stop attempting to re-send this query to this name servers.
1.4. Keep adding name servers in a staggered fashion while re-trying
queries to existing name servers.
2. wait for a response or for all requests to time out
If res_io_method() is called within a loop (such as the case in get()), the
pattern of (re)transmissions is roughly ( for _res.retries = 4,
_res.delay = 5, three servers, one address each):
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 (seconds)
Svr 1 : 1 2 3 4 Give up
Svr 2 : 1 2 3 4 Give up
Svr 3 : 1 2 3 4 Give up
All pending queries are destroyed once an answer is obtained. From
the application's standpoint the answer may still not be complete
(for example, RRSIGs may be missing), in which case it may wish to
retry a different set of name servers or query separately for missing data.
Resolver Current Status
-----------------------
This library provides very basic functionality for name resolution.
The data structures and interfaces exported to applications are still
in a state of flux.
The following enhancements still need to be made:
1. Clean up the interface between the resolver and the validator.
2. The current design requires the validator to constantly poll the resolver
for data. Since the calls are non-blocking, this process may have some
demands on CPU cycles. A better approach would be for the validator to
never have to poll the resolver for data once a query is issued;
instead, the resolver should invoke some callback function to hand over
any data back to the validator or to any other program that requested
such data.
3. Most zones are served by multiple name servers. Only the answer returned
by the first name server is used. The resolver needs to keep track of
the response times for different name servers so that future queries to the
same zone can be made on a preferential basis to name servers that have the
best response time.
4. The measures outlined in draft-ietf-dnsext-forgery-resilience must be
followed.
5. Support for TSIG
6. Detection of multiple responses for a given query
Acknowledgements
----------------
Most of the code in the libsres library was derived from an earlier
implementation of the secure resolver library written by
Ed Lewis at Tislabs.
libsres has some reliance on BIND code (although these are mostly
helper routines) and some other libbind artifacts.
|