Merge pull request #1111 from pi-hole/new/reply_pihole_hostname

Handle pi.hole and hostname interface-dependent
This commit is contained in:
DL6ER
2021-06-23 22:52:51 +02:00
committed by GitHub
6 changed files with 110 additions and 31 deletions
+26
View File
@@ -22,6 +22,8 @@
#include "database/common.h"
// destroy_shmem()
#include "shmem.h"
// uname()
#include <sys/utsname.h>
// killed
#include "signals.h"
@@ -141,6 +143,30 @@ char *getUserName(void)
return name;
}
// "man 7 hostname" says:
//
// Each element of the hostname must be from 1 to 63 characters long and the
// entire hostname, including the dots, can be at most 253 characters long.
//
// Valid characters for hostnames are ASCII(7) letters from a to z, the
// digits from 0 to 9, and the hyphen (-). A hostname may not start with a
// hyphen.
#define HOSTNAMESIZE 256
static char nodename[HOSTNAMESIZE] = { 0 };
const char *hostname(void)
{
// Ask kernel for node name if not known
// This is equivalent to "uname -n"
if(nodename[0] == '\0')
{
struct utsname buf;
if(uname(&buf) == 0)
strncpy(nodename, buf.nodename, HOSTNAMESIZE);
nodename[HOSTNAMESIZE-1] = '\0';
}
return nodename;
}
void delay_startup(void)
{
// Exit early if not sleeping
+1
View File
@@ -16,6 +16,7 @@ extern pthread_t threads[THREADS_MAX];
void go_daemon(void);
void savepid(void);
char *getUserName(void);
const char *hostname(void);
void delay_startup(void);
bool is_fork(const pid_t mpid, const pid_t pid) __attribute__ ((const));
void cleanup(const int ret);
+1 -1
View File
@@ -102,7 +102,7 @@ ASSERT_SIZEOF(domainsData, 24, 16, 16);
typedef struct {
unsigned char magic;
enum domain_client_status blocking_status;
unsigned char force_reply;
enum reply_type force_reply;
enum query_types query_type;
int domainID;
int clientID;
+80 -28
View File
@@ -58,7 +58,7 @@ static void query_blocked(queriesData* query,
// Static blocking metadata
static union all_addr null_addrp = {{ 0 }};
static unsigned char force_next_DNS_reply = 0u;
static enum reply_type force_next_DNS_reply = REPLY_UNKNOWN;
// Adds debug information to the regular pihole.log file
char debug_dnsmasq_lines = 0;
@@ -82,10 +82,28 @@ void FTL_iface(const int ifidx, const struct irec *ifaces)
// Copy overwrite addresses if configured via REPLY_ADDR4 and/or REPLY_ADDR6 settings
if(config.reply_addr.overwrite_v4)
{
memcpy(&next_iface.addr4, &config.reply_addr.v4, sizeof(config.reply_addr.v4));
if(config.debug & DEBUG_NETWORKING)
{
char buffer[ADDRSTRLEN+1] = { 0 };
inet_ntop(AF_INET, &next_iface.addr4, buffer, ADDRSTRLEN);
logg("Interface (%d) %s OVERWRITES IPv4 address %s", ifidx, next_iface.name, buffer);
}
}
if(config.reply_addr.overwrite_v6)
{
memcpy(&next_iface.addr6, &config.reply_addr.v6, sizeof(config.reply_addr.v6));
if(config.debug & DEBUG_NETWORKING)
{
char buffer[ADDRSTRLEN+1] = { 0 };
inet_ntop(AF_INET6, &next_iface.addr6, buffer, ADDRSTRLEN);
logg("Interface (%d) %s OVERWRITES IPv6 address %s", ifidx, next_iface.name, buffer);
}
}
// Use dummy when interface record is not available
next_iface.name[0] = '-';
next_iface.name[1] = '\0';
@@ -396,8 +414,8 @@ static bool _FTL_check_blocking(int queryID, int domainID, int clientID, const c
// Truncate "_esni." from queried domain if the parenting domain was the reason for blocking this query
blockedDomain = domainstr + 6u;
// Force next DNS reply to be NXDOMAIN for _esni.* queries
force_next_DNS_reply = NXDOMAIN;
dns_cache->force_reply = NXDOMAIN;
force_next_DNS_reply = REPLY_NXDOMAIN;
dns_cache->force_reply = REPLY_NXDOMAIN;
}
}
@@ -633,9 +651,24 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
return false;
}
// If domain is "pi.hole" we skip this query
if(strcasecmp(name, "pi.hole") == 0)
return false;
// If domain is "pi.hole" or the local hostname we skip analyzing this query
// and, instead, immediately reply with the IP address
if(strcasecmp(name, "pi.hole") == 0 || strcasecmp(name, hostname()) == 0)
{
if(querytype == TYPE_A || querytype == TYPE_AAAA || querytype == TYPE_ANY)
{
// "Block" this query by sending the interface IP address
force_next_DNS_reply = REPLY_IP;
if(config.debug & DEBUG_QUERIES)
logg("Replying to %s with interface-local IP address", name);
return true;
}
else
{
// Don't block this query
return false;
}
}
// Convert domain to lower case
char *domainString = strdup(name);
@@ -660,7 +693,7 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
inet_ntop(family,
family == AF_INET ?
(union mysockaddr*)&addr->in.sin_addr :
(union mysockaddr*)&addr->in6.sin6_addr,
(union mysockaddr*)&addr->in6.sin6_addr,
clientIP, ADDRSTRLEN);
}
@@ -703,7 +736,7 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
}
// Block this query
force_next_DNS_reply = REFUSED;
force_next_DNS_reply = REPLY_REFUSED;
// Do not further process this query, Pi-hole has never seen it
unlock_shm();
@@ -868,19 +901,21 @@ void _FTL_get_blocking_metadata(union all_addr **addrp, unsigned int *flags, con
// Check first if we need to force our reply to something different than the
// default/configured blocking mode. For instance, we need to force NXDOMAIN
// for intercepted _esni.* queries.
if(force_next_DNS_reply == NXDOMAIN)
if(force_next_DNS_reply == REPLY_NXDOMAIN)
{
*flags = F_NXDOMAIN;
// Reset DNS reply forcing
force_next_DNS_reply = 0u;
force_next_DNS_reply = REPLY_UNKNOWN;
return;
}
else if(force_next_DNS_reply == REFUSED)
else if(force_next_DNS_reply == REPLY_REFUSED)
{
// Empty flags result in REFUSED
*flags = 0;
// Reset DNS reply forcing
force_next_DNS_reply = 0u;
force_next_DNS_reply = REPLY_UNKNOWN;
return;
}
@@ -894,18 +929,35 @@ void _FTL_get_blocking_metadata(union all_addr **addrp, unsigned int *flags, con
if(*flags & F_IPV6)
{
// Pass blocking IPv6 address
if(config.blockingmode == MODE_IP)
if(config.blockingmode == MODE_IP ||
force_next_DNS_reply == REPLY_IP)
{
*addrp = &next_iface.addr6;
}
else
{
*addrp = &null_addrp;
}
// Reset reply forcing
force_next_DNS_reply = REPLY_UNKNOWN;
}
else
{
// Pass blocking IPv4 address
if(config.blockingmode == MODE_IP || config.blockingmode == MODE_IP_NODATA_AAAA)
if(config.blockingmode == MODE_IP ||
config.blockingmode == MODE_IP_NODATA_AAAA ||
force_next_DNS_reply == REPLY_IP)
{
*addrp = &next_iface.addr4;
}
else
{
*addrp = &null_addrp;
}
// Reset reply forcing
force_next_DNS_reply = REPLY_UNKNOWN;
}
if(config.blockingmode == MODE_NX)
@@ -1086,6 +1138,16 @@ void _FTL_reply(const unsigned int flags, const char *name, const union all_addr
// Lock shared memory
lock_shm();
// Save status in corresponding query identified by dnsmasq's ID
const int queryID = findQueryID(id);
if(queryID < 0)
{
// This may happen e.g. if the original query was "pi.hole"
if(config.debug & DEBUG_QUERIES) logg("FTL_reply(): Query %i has not been found", id);
unlock_shm();
return;
}
// Determine returned result if available
char dest[ADDRSTRLEN]; dest[0] = '\0';
if(addr)
@@ -1128,18 +1190,8 @@ void _FTL_reply(const unsigned int flags, const char *name, const union all_addr
struct timeval response;
gettimeofday(&response, 0);
// Save status in corresponding query identified by dnsmasq's ID
const int i = findQueryID(id);
if(i < 0)
{
// This may happen e.g. if the original query was "pi.hole"
if(config.debug & DEBUG_QUERIES) logg("FTL_reply(): Query %i has not been found", id);
unlock_shm();
return;
}
// Get query pointer
queriesData* query = getQuery(i, true);
queriesData* query = getQuery(queryID, true);
// Check if reply time is still unknown
// We only process the first reply in here
@@ -1708,7 +1760,7 @@ static void query_set_reply(const unsigned int flags, const union all_addr *addr
queriesData* query, const struct timeval response)
{
// Iterate through possible values
if(flags & F_NEG || force_next_DNS_reply == NXDOMAIN)
if(flags & F_NEG || force_next_DNS_reply == REPLY_NXDOMAIN)
{
if(flags & F_NXDOMAIN)
// NXDOMAIN
@@ -1726,10 +1778,10 @@ static void query_set_reply(const unsigned int flags, const union all_addr *addr
else if(flags & F_RRNAME)
// TXT query
query->reply = REPLY_RRNAME;
else if((flags & F_RCODE && addr != NULL) || force_next_DNS_reply == REFUSED)
else if((flags & F_RCODE && addr != NULL) || force_next_DNS_reply == REPLY_REFUSED)
{
if((addr != NULL && addr->log.rcode == REFUSED)
|| force_next_DNS_reply == REFUSED )
|| force_next_DNS_reply == REPLY_REFUSED )
{
// REFUSED query
query->reply = REPLY_REFUSED;
+1 -1
View File
@@ -47,7 +47,7 @@ int main (int argc, char* argv[])
// Try to open FTL log
init_FTL_log();
timer_start(EXIT_TIMER);
logg("########## FTL started! ##########");
logg("########## FTL started on %s! ##########", hostname());
log_FTL_version(false);
// Catch signals not handled by dnsmasq
+1 -1
View File
@@ -12,7 +12,7 @@
int main_dnsmasq(int argc, const char ** argv);
extern char * username;
extern char *username;
extern bool startup;
#endif //MAIN_H