Analyze which upstream server sent us the reply

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER
2021-06-25 10:23:10 +02:00
parent 1204e8f598
commit 378dd0fe81
3 changed files with 70 additions and 25 deletions
+1 -1
View File
@@ -644,7 +644,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
}
}
FTL_header_analysis(header->hb4, rcode, daemon->log_display_id);
FTL_header_analysis(header->hb4, rcode, server, daemon->log_display_id);
/* RFC 4035 sect 4.6 para 3 */
if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
+67 -22
View File
@@ -59,6 +59,7 @@ static void FTL_forwarded(const unsigned int flags, const char *name, const unio
static void FTL_reply(const unsigned int flags, const char *name, const union all_addr *addr, const char* arg, const int id, const char* file, const int line);
static void FTL_upstream_error(const unsigned int rcode, const int id, const char* file, const int line);
static void FTL_dnssec(const char *result, const int id, const char* file, const int line);
static void get_mysockaddr_ip_port(union mysockaddr *server, char ip[ADDRSTRLEN+1], in_port_t *port);
// Static blocking metadata
static const char *blockingreason = NULL;
@@ -75,6 +76,9 @@ static struct {
union all_addr addr6;
} next_iface = {"", {{0}}, {{0}}};
// Fork-private copy of the server data the most recent reply came from
static union mysockaddr last_server = {{ 0 }};
unsigned char* pihole_privacylevel = &config.privacylevel;
const char flagnames[][12] = {"F_IMMORTAL ", "F_NAMEP ", "F_REVERSE ", "F_FORWARD ", "F_DHCP ", "F_NEG ", "F_HOSTS ", "F_IPV4 ", "F_IPV6 ", "F_BIGNAME ", "F_NXDOMAIN ", "F_CNAME ", "F_DNSKEY ", "F_CONFIG ", "F_DS ", "F_DNSSECOK ", "F_UPSTREAM ", "F_RRNAME ", "F_SERVER ", "F_QUERY ", "F_NOERR ", "F_AUTH ", "F_DNSSEC ", "F_KEYTAG ", "F_SECSTAT ", "F_NO_RR ", "F_IPSET ", "F_NOEXTRA ", "F_SERVFAIL", "F_RCODE"};
@@ -377,11 +381,7 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
else if(addr)
{
// Use original requestor
inet_ntop(family,
family == AF_INET ?
(union alladdr*)&addr->in.sin_addr :
(union alladdr*)&addr->in6.sin6_addr,
clientIP, ADDRSTRLEN);
get_mysockaddr_ip_port(addr, clientIP, NULL);
}
else
{
@@ -1265,6 +1265,24 @@ void FTL_dnsmasq_reload(void)
resolver_ready = true;
}
static void get_mysockaddr_ip_port(union mysockaddr *server, char ip[ADDRSTRLEN+1], in_port_t *port)
{
// Extract IP address
inet_ntop(server->sa.sa_family,
server->sa.sa_family == AF_INET ?
(union alladdr*)&server->in.sin_addr :
(union alladdr*)&server->in6.sin6_addr,
ip, ADDRSTRLEN);
// Extract port (only if requested)
if(port != NULL)
{
*port = ntohs(server->sa.sa_family == AF_INET ?
server->in.sin_port :
server->in6.sin6_port);
}
}
static void FTL_reply(const unsigned int flags, const char *name, const union all_addr *addr,
const char *arg, const int id, const char* file, const int line)
{
@@ -1347,7 +1365,18 @@ static void FTL_reply(const unsigned int flags, const char *name, const union al
answer = arg; // e.g. "reply <TLD> is no DS"
}
logg("**** got %s reply: %s is %s (ID %i, %s:%i)", cached ? "cache" : "upstream", name, answer, id, file, line);
if(cached || last_server.sa.sa_family == 0)
// Log cache or upstream reply from unknown source
logg("**** got %s reply: %s is %s (ID %i, %s:%i)", cached ? "cache" : "upstream", name, answer, id, file, line);
else
{
// Log server who replied to our request
char ip[ADDRSTRLEN+1] = { 0 };
in_port_t port = 0;
get_mysockaddr_ip_port(&last_server, ip, &port);
logg("**** got %s reply from %s#%d: %s is %s (ID %i, %s:%i)",
cached ? "cache" : "upstream", ip, port, name, answer, id, file, line);
}
}
// Get response time
@@ -1737,23 +1766,8 @@ static void FTL_upstream_error(const unsigned int rcode, const int id, const cha
unlock_shm();
}
void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode, const int id, const char* file, const int line)
static void FTL_mark_externally_blocked(const int id, const char* file, const int line)
{
// Analyze DNS header bits
// Check if RA bit is unset in DNS header and rcode is NXDOMAIN
// If the response code (rcode) is NXDOMAIN, we may be seeing a response from
// an externally blocked query. As they are not always accompany a necessary
// SOA record, they are not getting added to our cache and, therefore,
// FTL_reply() is never getting called from within the cache routines.
// Hence, we have to store the necessary information about the NXDOMAIN
// reply already here.
if((header4 & 0x80) || rcode != NXDOMAIN)
{
// RA bit is set or rcode is not NXDOMAIN
return;
}
// Lock shared memory
lock_shm();
@@ -1813,6 +1827,37 @@ void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode,
unlock_shm();
}
void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode, const struct server *server,
const int id, const char* file, const int line)
{
// Analyze DNS header bits
// Check if RA bit is unset in DNS header and rcode is NXDOMAIN
// If the response code (rcode) is NXDOMAIN, we may be seeing a response from
// an externally blocked query. As they are not always accompany a necessary
// SOA record, they are not getting added to our cache and, therefore,
// FTL_reply() is never getting called from within the cache routines.
// Hence, we have to store the necessary information about the NXDOMAIN
// reply already here.
if(!(header4 & 0x80) && rcode == NXDOMAIN)
// RA bit is not set and rcode is NXDOMAIN
FTL_mark_externally_blocked(id, file, line);
// Store server which sent this reply
if(server)
{
memcpy(&last_server, &server->addr, sizeof(last_server));
if(config.debug & DEBUG_EXTRA)
logg("Got forward address: YES");
}
else
{
memset(&last_server, 0, sizeof(last_server));
if(config.debug & DEBUG_EXTRA)
logg("Got forward address: NO");
}
}
void print_flags(const unsigned int flags)
{
// Debug function, listing resolver flags in clear text
+2 -2
View File
@@ -26,8 +26,8 @@ void FTL_iface(const int ifidx, const struct irec *ifaces);
#define FTL_new_query(flags, name, addr, types, qtype, id, edns, proto) _FTL_new_query(flags, name, addr, types, qtype, id, edns, proto, __FILE__, __LINE__)
bool _FTL_new_query(const unsigned int flags, const char *name, union mysockaddr *addr, const char *types, const unsigned short qtype, const int id, const ednsData *edns, enum protocol proto, const char* file, const int line);
#define FTL_header_analysis(header4, rcode, id) _FTL_header_analysis(header4, rcode, id, __FILE__, __LINE__)
void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode, const int id, const char* file, const int line);
#define FTL_header_analysis(header4, rcode, server, id) _FTL_header_analysis(header4, rcode, server, id, __FILE__, __LINE__)
void _FTL_header_analysis(const unsigned char header4, const unsigned int rcode, const struct server *server, const int id, const char* file, const int line);
void FTL_forwarding_retried(const struct server *server, const int oldID, const int newID, const bool dnssec);