Store intermediate CNAME domain pointers in DNS cache for later retrieval from cache without another CNAME inspection

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER
2025-05-21 15:55:36 +02:00
parent 8bec7efc38
commit 2d2fe30e15
3 changed files with 34 additions and 7 deletions

View File

@@ -117,6 +117,7 @@ typedef struct {
enum query_type query_type;
unsigned int domainID;
unsigned int clientID;
unsigned int CNAME_domainID; // only valid if query has a CNAME blocking status
int list_id;
uint32_t hash;
time_t expires;

View File

@@ -1537,7 +1537,9 @@ static bool FTL_check_blocking(const unsigned int queryID, const unsigned int do
if(!query->flags.allowed)
{
force_next_DNS_reply = dns_cache->force_reply;
query_blocked(query, domain, client, QUERY_DENYLIST);
query_blocked(query, domain, client, blocking_status);
if(blocking_status == QUERY_DENYLIST_CNAME)
query->CNAME_domainID = dns_cache->CNAME_domainID;
return true;
}
break;
@@ -1554,7 +1556,9 @@ static bool FTL_check_blocking(const unsigned int queryID, const unsigned int do
if(!query->flags.allowed)
{
force_next_DNS_reply = dns_cache->force_reply;
query_blocked(query, domain, client, QUERY_GRAVITY);
query_blocked(query, domain, client, blocking_status);
if(blocking_status == QUERY_GRAVITY_CNAME)
query->CNAME_domainID = dns_cache->CNAME_domainID;
return true;
}
break;
@@ -1573,7 +1577,9 @@ static bool FTL_check_blocking(const unsigned int queryID, const unsigned int do
{
force_next_DNS_reply = dns_cache->force_reply;
last_regex_idx = dns_cache->list_id;
query_blocked(query, domain, client, QUERY_REGEX);
query_blocked(query, domain, client, blocking_status);
if(blocking_status == QUERY_REGEX_CNAME)
query->CNAME_domainID = dns_cache->CNAME_domainID;
return true;
}
break;
@@ -1863,6 +1869,12 @@ bool FTL_CNAME(const char *dst, const char *src, const int id)
// Store domain that was the reason for blocking the entire chain
query->CNAME_domainID = child_domainID;
// Store CNAME domain ID in DNS cache
const int parent_cacheID = query->cacheID > -1 ? query->cacheID : findCacheID(parent_domainID, clientID, query->type, false);
DNSCacheData *parent_cache = parent_cacheID < 0 ? NULL : getDNSCache(parent_cacheID, true);
if(parent_cache != NULL)
parent_cache->CNAME_domainID = child_domainID;
// Change blocking reason into CNAME-caused blocking
if(query->status == QUERY_GRAVITY)
{
@@ -1870,12 +1882,10 @@ bool FTL_CNAME(const char *dst, const char *src, const int id)
}
else if(query->status == QUERY_REGEX)
{
// Get parent and child DNS cache entries
const int parent_cacheID = query->cacheID > -1 ? query->cacheID : findCacheID(parent_domainID, clientID, query->type, false);
// Get child DNS cache entries
const int child_cacheID = findCacheID(child_domainID, clientID, query->type, false);
// Get cache pointers
DNSCacheData *parent_cache = parent_cacheID < 0 ? NULL : getDNSCache(parent_cacheID, true);
// Get child's cache pointer
const DNSCacheData *child_cache = child_cacheID < 0 ? NULL : getDNSCache(child_cacheID, true);
// Propagate ID of responsible regex up from the child to the parent

View File

@@ -102,6 +102,22 @@ static void recycle(void)
cache_used[query->cacheID] = true;
}
// Scan cache records for CNAME domain pointers that prevent domains
// from being recyclable
for(unsigned int cacheID = 0; cacheID < counters->dns_cache_size; cacheID++)
{
const DNSCacheData *cache = getDNSCache(cacheID, true);
if(cache == NULL)
continue;
// Mark domains as used when this is a CNAME-related cache
// record
if(cache->blocking_status == QUERY_GRAVITY_CNAME ||
cache->blocking_status == QUERY_REGEX_CNAME ||
cache->blocking_status == QUERY_DENYLIST_CNAME)
domain_used[cache->CNAME_domainID] = true;
}
// Recycle clients
unsigned int clients_recycled = 0;
for(unsigned int clientID = 0; clientID < counters->clients; clientID++)