Add dns_resolver option

This allows one to configure the address of the DNS server to use for
lookup operations.

Addresses GH-216
This commit is contained in:
Jon Siwek 2018-11-21 13:42:25 -06:00
parent fd63168171
commit af82e87699
4 changed files with 121 additions and 23 deletions

View file

@ -3656,6 +3656,12 @@ global dns_skip_all_addl = T &redef;
## traffic and do not process it. Set to 0 to turn off this functionality. ## traffic and do not process it. Set to 0 to turn off this functionality.
global dns_max_queries = 25 &redef; global dns_max_queries = 25 &redef;
## The address of the DNS resolver to use. If not changed from the
## unspecified address, ``[::]``, the first nameserver from /etc/resolv.conf
## gets used (IPv6 is currently only supported if set via this option, not
## when parsed from the file).
const dns_resolver = [::] &redef;
## HTTP session statistics. ## HTTP session statistics.
## ##
## .. bro:see:: http_stats ## .. bro:see:: http_stats

View file

@ -376,12 +376,6 @@ DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode)
mode = arg_mode; mode = arg_mode;
char err[NB_DNS_ERRSIZE];
nb_dns = nb_dns_init(err);
if ( ! nb_dns )
reporter->Warning("problem initializing NB-DNS: %s", err);
dns_mapping_valid = dns_mapping_unverified = dns_mapping_new_name = dns_mapping_valid = dns_mapping_unverified = dns_mapping_new_name =
dns_mapping_lost_name = dns_mapping_name_changed = dns_mapping_lost_name = dns_mapping_name_changed =
dns_mapping_altered = 0; dns_mapping_altered = 0;
@ -410,6 +404,35 @@ void DNS_Mgr::InitPostScript()
if ( did_init ) if ( did_init )
return; return;
auto dns_resolver_id = global_scope()->Lookup("dns_resolver");
auto dns_resolver_addr = dns_resolver_id->ID_Val()->AsAddr();
char err[NB_DNS_ERRSIZE];
if ( dns_resolver_addr == IPAddr("::") )
nb_dns = nb_dns_init(err);
else
{
struct sockaddr_storage ss = {0};
if ( dns_resolver_addr.GetFamily() == IPv4 )
{
struct sockaddr_in* sa = (struct sockaddr_in*)&ss;
sa->sin_family = AF_INET;
dns_resolver_addr.CopyIPv4(&sa->sin_addr);
}
else
{
struct sockaddr_in6* sa = (struct sockaddr_in6*)&ss;
sa->sin6_family = AF_INET6;
dns_resolver_addr.CopyIPv6(&sa->sin6_addr);
}
nb_dns = nb_dns_init2(err, (struct sockaddr*)&ss);
}
if ( ! nb_dns )
reporter->Warning("problem initializing NB-DNS: %s", err);
const char* cache_dir = dir ? dir : "."; const char* cache_dir = dir ? dir : ".";
if ( mode == DNS_PRIME && ! ensure_dir(cache_dir) ) if ( mode == DNS_PRIME && ! ensure_dir(cache_dir) )
@ -471,15 +494,15 @@ static const char* fake_addr_lookup_result(const IPAddr& addr)
TableVal* DNS_Mgr::LookupHost(const char* name) TableVal* DNS_Mgr::LookupHost(const char* name)
{ {
if ( mode == DNS_FAKE )
return fake_name_lookup_result(name);
if ( ! nb_dns ) if ( ! nb_dns )
return empty_addr_set(); return empty_addr_set();
if ( ! did_init ) if ( ! did_init )
Init(); Init();
if ( mode == DNS_FAKE )
return fake_name_lookup_result(name);
if ( mode != DNS_PRIME ) if ( mode != DNS_PRIME )
{ {
HostMap::iterator it = host_mappings.find(name); HostMap::iterator it = host_mappings.find(name);

View file

@ -86,7 +86,7 @@ struct nb_dns_hostent {
struct nb_dns_info { struct nb_dns_info {
int s; /* Resolver file descriptor */ int s; /* Resolver file descriptor */
struct sockaddr_in server; /* server address to bind to */ struct sockaddr_storage server; /* server address to bind to */
struct nb_dns_entry *list; /* outstanding requests */ struct nb_dns_entry *list; /* outstanding requests */
struct nb_dns_hostent dns_hostent; struct nb_dns_hostent dns_hostent;
}; };
@ -109,6 +109,18 @@ my_strerror(int errnum)
#endif #endif
} }
static const char* sa_ntop(struct sockaddr* sa, char* buf, int len)
{
if ( sa->sa_family == AF_INET )
return inet_ntop(sa->sa_family,
&(((struct sockaddr_in*)sa)->sin_addr),
buf, len);
else
return inet_ntop(sa->sa_family,
&(((struct sockaddr_in6*)sa)->sin6_addr),
buf, len);
}
struct nb_dns_info * struct nb_dns_info *
nb_dns_init(char *errstr) nb_dns_init(char *errstr)
{ {
@ -136,13 +148,12 @@ nb_dns_init(char *errstr)
for ( i = 0; i < _res.nscount; ++i ) for ( i = 0; i < _res.nscount; ++i )
{ {
nd->server = _res.nsaddr_list[i]; memcpy(&nd->server, &_res.nsaddr_list[i], sizeof(struct sockaddr_in));
/* XXX support IPv6 */ /* XXX support IPv6 */
if ( nd->server.sin_family != AF_INET ) if ( nd->server.ss_family != AF_INET )
continue; continue;
nd->s = socket(nd->server.sin_family, SOCK_DGRAM, 0); nd->s = socket(nd->server.ss_family, SOCK_DGRAM, 0);
if ( nd->s < 0 ) if ( nd->s < 0 )
{ {
@ -153,10 +164,14 @@ nb_dns_init(char *errstr)
} }
if ( connect(nd->s, (struct sockaddr *)&nd->server, if ( connect(nd->s, (struct sockaddr *)&nd->server,
sizeof(struct sockaddr)) < 0 ) nd->server.ss_family == AF_INET ?
sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6)) < 0 )
{ {
snprintf(errstr, NB_DNS_ERRSIZE, "connect(%s): %s", char s[INET6_ADDRSTRLEN];
inet_ntoa(nd->server.sin_addr), my_strerror(errno)); sa_ntop((struct sockaddr*)&nd->server, s, INET6_ADDRSTRLEN);
snprintf(errstr, NB_DNS_ERRSIZE, "connect(%s): %s", s,
my_strerror(errno));
close(nd->s); close(nd->s);
free(nd); free(nd);
return (NULL); return (NULL);
@ -170,6 +185,58 @@ nb_dns_init(char *errstr)
return (NULL); return (NULL);
} }
struct nb_dns_info *
nb_dns_init2(char *errstr, struct sockaddr* sa)
{
register struct nb_dns_info *nd;
nd = (struct nb_dns_info *)malloc(sizeof(*nd));
if (nd == NULL) {
snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_init: malloc(): %s",
my_strerror(errno));
return (NULL);
}
memset(nd, 0, sizeof(*nd));
nd->s = -1;
if ( sa->sa_family == AF_INET )
{
memcpy(&nd->server, sa, sizeof(struct sockaddr_in));
((struct sockaddr_in*)&nd->server)->sin_port = htons(53);
}
else
{
memcpy(&nd->server, sa, sizeof(struct sockaddr_in6));
((struct sockaddr_in6*)&nd->server)->sin6_port = htons(53);
}
nd->s = socket(nd->server.ss_family, SOCK_DGRAM, 0);
if ( nd->s < 0 )
{
snprintf(errstr, NB_DNS_ERRSIZE, "socket(): %s",
my_strerror(errno));
free(nd);
return (NULL);
}
if ( connect(nd->s, (struct sockaddr *)&nd->server,
nd->server.ss_family == AF_INET ?
sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6)) < 0 )
{
char s[INET6_ADDRSTRLEN];
sa_ntop((struct sockaddr*)&nd->server, s, INET6_ADDRSTRLEN);
snprintf(errstr, NB_DNS_ERRSIZE, "connect(%s): %s", s,
my_strerror(errno));
close(nd->s);
free(nd);
return (NULL);
}
return (nd);
}
void void
nb_dns_finish(struct nb_dns_info *nd) nb_dns_finish(struct nb_dns_info *nd)
{ {
@ -226,12 +293,12 @@ _nb_dns_cmpsockaddr(register struct sockaddr *sa1,
sin6a = (struct sockaddr_in6 *)sa1; sin6a = (struct sockaddr_in6 *)sa1;
sin6b = (struct sockaddr_in6 *)sa2; sin6b = (struct sockaddr_in6 *)sa2;
if (sin6a->sin6_port != sin6b->sin6_port) { if (sin6a->sin6_port != sin6b->sin6_port) {
snprintf(errstr, NB_DNS_ERRSIZE, serr, 2); snprintf(errstr, NB_DNS_ERRSIZE, serr, 62);
return (-1); return (-1);
} }
if (memcmp(&sin6a->sin6_addr, &sin6b->sin6_addr, if (memcmp(&sin6a->sin6_addr, &sin6b->sin6_addr,
sizeof(sin6a->sin6_addr)) != 0) { sizeof(sin6a->sin6_addr)) != 0) {
snprintf(errstr, NB_DNS_ERRSIZE, serr, 3); snprintf(errstr, NB_DNS_ERRSIZE, serr, 63);
return (-1); return (-1);
} }
break; break;
@ -446,7 +513,7 @@ nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr)
register int msglen, qtype, atype, n, i; register int msglen, qtype, atype, n, i;
register struct nb_dns_entry *ne, *lastne; register struct nb_dns_entry *ne, *lastne;
socklen_t fromlen; socklen_t fromlen;
struct sockaddr from; struct sockaddr_storage from;
u_long msg[MAXPACKET / sizeof(u_long)]; u_long msg[MAXPACKET / sizeof(u_long)];
register char *bp, *ep; register char *bp, *ep;
register char **ap, **hap; register char **ap, **hap;
@ -460,7 +527,8 @@ nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr)
/* This comes from the second half of do_query() */ /* This comes from the second half of do_query() */
fromlen = sizeof(from); fromlen = sizeof(from);
msglen = recvfrom(nd->s, (char *)msg, sizeof(msg), 0, &from, &fromlen); msglen = recvfrom(nd->s, (char *)msg, sizeof(msg), 0,
(struct sockaddr*)&from, &fromlen);
if (msglen <= 0) { if (msglen <= 0) {
snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): %s", snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): %s",
my_strerror(errno)); my_strerror(errno));
@ -479,8 +547,8 @@ nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr)
} }
/* RES_INSECURE1 style check */ /* RES_INSECURE1 style check */
if (_nb_dns_cmpsockaddr((struct sockaddr *)&nd->server, &from, if (_nb_dns_cmpsockaddr((struct sockaddr*)&nd->server,
errstr) < 0) { (struct sockaddr*)&from, errstr) < 0) {
nr->host_errno = NO_RECOVERY; nr->host_errno = NO_RECOVERY;
return (-1); return (-1);
} }

View file

@ -17,6 +17,7 @@ typedef unsigned int nb_uint32_t;
/* Public routines */ /* Public routines */
struct nb_dns_info *nb_dns_init(char *); struct nb_dns_info *nb_dns_init(char *);
struct nb_dns_info *nb_dns_init2(char *, struct sockaddr*);
void nb_dns_finish(struct nb_dns_info *); void nb_dns_finish(struct nb_dns_info *);
int nb_dns_fd(struct nb_dns_info *); int nb_dns_fd(struct nb_dns_info *);