From 5a246179c9096c916833f54a212f55d688098c62 Mon Sep 17 00:00:00 2001 From: Dario Lombardo Date: Tue, 28 Jan 2014 13:36:27 +0100 Subject: [PATCH] Added rcode check --- README.md | 9 +++--- dns.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ dns.h | 3 ++ radar.c | 15 +++------- 4 files changed, 100 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c4728aa..390881d 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,12 @@ To compile, just issue the following commands: USAGE ===== - namescan 0.1.1 - massive DNS scanner + namescan 0.1.2 - massive DNS scanner Usage: ./namescan [-i ] [-v] [-s ] [-d ] [-t ] [-o ] - [-n ] [-q ] [-c ] [-r] [-l ] + [-n ] [-q ] [-c ] [-r] [-l ] [-e] - * -i : the interface to use. If not specified, the first available interface will be used + * -i: the interface to use. If not specified, the first available interface will be used * -v: verbose mode * -s: the source IP address to use. Default: the current interface IP. * -d: delay between packets. Deafault: 0. @@ -45,7 +45,8 @@ USAGE * -c query class. Default: 1. * -r: do not randomize targets. * -l: show only relays that are above this amplification ratio. + * -e: do not add EDNS0 record * ip address(es) to scan. See below. The addresses to scan can be specified as a comma-separated list of CIDR addresses. -Example: 8.8.8.8/24,9.9.9.9/16. +Example: `8.8.8.8/24,9.9.9.9/16`, or `8.8.4.4`. diff --git a/dns.c b/dns.c index 23f5f17..22981fd 100644 --- a/dns.c +++ b/dns.c @@ -5,6 +5,7 @@ #include #include #include +#include void domainname_encode(char* qname, char* qname_enc) { @@ -44,6 +45,7 @@ void dns_pack(char* qname, uint16_t qtype, uint16_t qclass, char** dns, unsigned hdr.n_record[3] = htons(1); } + LOG_INFO("Using record: %s\n", qname); domainname_encode(qname, qname_enc); // compute the len of the dns packet @@ -154,3 +156,89 @@ int string_to_qclass(char* qclass_s) CONVERT_DNS_TYPE(qclass_s, "ANY", 255); return 0; } + +static char* rcode_to_string(uint8_t rcode, char* s, unsigned s_len) +{ + memset(s, 0x0, s_len); + + switch(rcode) { + case 0: + strncat(s, "No error", s_len); + break; + case 1: + strncat(s, "Format error", s_len); + break; + case 2: + strncat(s, "Server error", s_len); + break; + case 3: + strncat(s, "Non existent domain", s_len); + break; + case 4: + strncat(s, "Not implemented", s_len); + break; + case 5: + strncat(s, "Refused", s_len); + break; + case 6: + strncat(s, "Name Exists when it should not", s_len); + break; + case 7: + strncat(s, "RR Set Exists when it should not", s_len); + break; + case 8: + strncat(s, "RR Set that should exist does not", s_len); + break; + case 9: + strncat(s, "Not Authorized", s_len); + break; + case 10: + strncat(s, "Name not contained in zone", s_len); + break; + case 16: + strncat(s, "Bad OPT Version", s_len); + break; + case 17: + strncat(s, "Key not recognized", s_len); + break; + case 18: + strncat(s, "Signature out of time window", s_len); + break; + case 19: + strncat(s, "Bad TKEY Mode", s_len); + break; + case 20: + strncat(s, "Duplicate key name", s_len); + break; + case 21: + strncat(s, "Algorithm not supported", s_len); + break; + case 22: + strncat(s, "Bad Truncation", s_len); + break; + default: + LOG_ERROR("Unassigned RCODE"); + } + return s; +} + +int rcode_check(struct ip* ip, dns_header_t* dnshdr) +{ + char msgbuf[100]; + char buf[INET_ADDRSTRLEN]; + + switch(dnshdr->flags.rcode) { + case 0: + return 0; + case 5: + case 9: + LOG_DEBUG("Not allowed from %s\n", inet_ntop(AF_INET, &ip->ip_src, buf, INET_ADDRSTRLEN)); + return 1; + default: + LOG_ERROR("Error from %s: %s\n", inet_ntop(AF_INET, &ip->ip_src, buf, INET_ADDRSTRLEN), + rcode_to_string(dnshdr->flags.rcode, msgbuf, 100)); + return 1; + } + + return 0; +} diff --git a/dns.h b/dns.h index a9b9f75..55803de 100644 --- a/dns.h +++ b/dns.h @@ -4,6 +4,7 @@ #include #include +#include #pragma pack(1) typedef struct { @@ -44,4 +45,6 @@ int string_to_qtype(char* qtype_s); int string_to_qclass(char* qclass_s); +int rcode_check(struct ip* ip, dns_header_t* dnshdr); + #endif diff --git a/radar.c b/radar.c index 1a2fe64..51f68b6 100644 --- a/radar.c +++ b/radar.c @@ -93,8 +93,6 @@ void print_server(struct ip* ip, float ratio, FILE* fp) #define IS_LAST_FRAGMENT(ip) ((!((ntohs(ip->ip_off)) & IP_MF)) && ((ntohs(ip->ip_off)) & IP_OFFMASK)) #define IS_NOT_FRAGMENT(ip) ((!((ntohs(ip->ip_off)) & IP_MF)) && (!((ntohs(ip->ip_off)) & IP_OFFMASK))) -#define RCODE_OK(h) ((h)->flags.rcode != 0 ? 0 : 1) - void process_pkt(u_char* args, const struct pcap_pkthdr* h, const u_char* packet) { radar_params_t* rp = (radar_params_t*)args; @@ -103,11 +101,12 @@ void process_pkt(u_char* args, const struct pcap_pkthdr* h, const u_char* packet struct udphdr* udphdr; dns_header_t* dnshdr; - char buf[INET_ADDRSTRLEN]; float ratio = 0; fragnode_t* fragnode; + char buf[INET_ADDRSTRLEN]; + if (IS_FIRST_FRAGMENT(ip)) { if (h->len < (sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr) + sizeof(dns_header_t))) { @@ -119,11 +118,8 @@ void process_pkt(u_char* args, const struct pcap_pkthdr* h, const u_char* packet dnshdr = (dns_header_t*)(packet + sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr)); - if (!RCODE_OK(dnshdr)) { - LOG_DEBUG("\nForbidden resolution for %s, discarding\n", - inet_ntop(AF_INET, &ip->ip_src, buf, INET_ADDRSTRLEN)); + if (rcode_check(ip, dnshdr)) return; - } if (fingerprint_check(udphdr->dest, dnshdr->txid)) fragnode_add(&head, ip->ip_id, ip->ip_src, ip->ip_dst, h->len); @@ -156,11 +152,8 @@ void process_pkt(u_char* args, const struct pcap_pkthdr* h, const u_char* packet + sizeof(struct udphdr)); ratio = (float)h->len/(float)probesize; - if (!RCODE_OK(dnshdr)) { - LOG_DEBUG("\nForbidden resolution for %s, discarding\n", - inet_ntop(AF_INET, &ip->ip_src, buf, INET_ADDRSTRLEN)); + if (rcode_check(ip, dnshdr)) return; - } if (ratio >= rp->level && fingerprint_check(udphdr->dest, dnshdr->txid)) { print_server(ip, ratio, rp->outfile);