New syntax: querytype=A accepts now also a list (like querytype=A,AAAA,MX). You can use the exclamation mark as before for inversion (querytype=!A) matches everything BUT type A queries. This has now been extended to be able to invert a list, too (like (querytype=!A,AAAA matches everything BUT A and AAAA queries)

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2023-01-28 15:28:36 +01:00
parent 8b9e6c6c7e
commit 49e1c74455
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
4 changed files with 78 additions and 14 deletions

View File

@ -159,9 +159,13 @@ static bool compile_regex(const char *regexin, const enum regex_type regexid, co
// Analyze FTL-specific parts
while((part = strtok_r(NULL, FTL_REGEX_SEP, &saveptr)) != NULL)
{
char extra[17] = { 0 };
// options ";querytype=!AAAA" and ";querytype=AAAA"
if(sscanf(part, "querytype=%16s", extra))
char extra[64] = { 0 };
// options like
// - ";querytype=A" (only match type A queries)
// - ";querytype=!AAAA" (match everything but AAAA queries)
// - ";querytype=A,AAAA" (match only A and AAAA queries)
// - ";querytype=!A,AAAA" (match everything but A and AAAA queries)
if(sscanf(part, "querytype=%63s", extra))
{
// Warn if specified more than one querytype option
if(regex[index].ext.query_type != 0)
@ -169,6 +173,19 @@ static bool compile_regex(const char *regexin, const enum regex_type regexid, co
"Overwriting previous querytype setting",
dbidx, regexin);
// Check if the first letter is a "!"
// This means that the query type matching is inverted
bool inverted = false;
if(extra[0] == '!')
{
// Set inverted mode (will be applied
// after parsing all query types)
inverted = true;
// Remove the "!" from the string
memmove(extra, extra+1, strlen(extra));
}
// Split input string into individual query types
char *saveptr2 = NULL;
char *token = strtok_r(extra, ",", &saveptr2);
@ -183,12 +200,6 @@ static bool compile_regex(const char *regexin, const enum regex_type regexid, co
regex[index].ext.query_type ^= 1 << type;
break;
}
// Check for INVERTED querytype
else if(token[0] == '!' && strcasecmp(token + 1u, querytypes[type]) == 0)
{
regex[index].ext.query_type ^= ~(1 << type);
break;
}
}
// Check if we found a valid query type
if(regex[index].ext.query_type == 0)
@ -203,6 +214,11 @@ static bool compile_regex(const char *regexin, const enum regex_type regexid, co
// Get next token
token = strtok_r(NULL, ",", &saveptr2);
}
// Invert query types if requested
if(inverted)
regex[index].ext.query_type = ~regex[index].ext.query_type;
if(regex[index].ext.query_type != 0 && config.debug & DEBUG_REGEX)
{
logg(" Hint: This regex matches only specific query types:");

View File

@ -208,9 +208,11 @@ INSERT INTO domainlist VALUES(11,3,'^regex-REPLYv6$;reply=fe80::1234',1,15599288
INSERT INTO domainlist VALUES(12,3,'^regex-REPLYv46$;reply=1.2.3.4;reply=fe80::1234',1,1559928803,1559928803,'');
INSERT INTO domainlist VALUES(13,3,'^regex-A$;querytype=A',1,1559928803,1559928803,'');
INSERT INTO domainlist VALUES(14,3,'^regex-notA$;querytype=!A',1,1559928803,1559928803,'');
INSERT INTO domainlist VALUES(15,3,'^regex-multiple.ftl$;querytype=ANY,HTTPS,SVCB;reply=refused',1,1559928803,1559928803,'');
INSERT INTO domainlist VALUES(16,3,'^regex-notMultiple.ftl$;querytype=!ANY,HTTPS,SVCB;reply=refused',1,1559928803,1559928803,'');
/* Other special domains */
INSERT INTO domainlist VALUES(15,1,'blacklisted-group-disabled.com',1,1559928803,1559928803,'Entry disabled by a group');
INSERT INTO domainlist VALUES(17,1,'blacklisted-group-disabled.com',1,1559928803,1559928803,'Entry disabled by a group');
INSERT INTO adlist VALUES(1,'https://hosts-file.net/ad_servers.txt',1,1559928803,1559928803,'Migrated from /etc/pihole/adlists.list',1559928803,2000,2,1);

View File

@ -98,9 +98,19 @@ pdnsutil add-record ftl. mx MX "50 ns1.ftl."
# SVCB + HTTPS
pdnsutil add-record ftl. svcb SVCB '1 port="80"'
pdnsutil add-record ftl. regex-multiple SVCB '1 port="80"'
pdnsutil add-record ftl. regex-notMultiple SVCB '1 port="80"'
# HTTPS
pdnsutil add-record ftl. https HTTPS '1 . alpn="h3,h2"'
pdnsutil add-record ftl. regex-multiple HTTPS '1 . alpn="h3,h2"'
pdnsutil add-record ftl. regex-notMultiple HTTPS '1 . alpn="h3,h2"'
# ANY
pdnsutil add-record ftl. regex-multiple A 192.168.3.12
pdnsutil add-record ftl. regex-multiple AAAA fe80::3f41
pdnsutil add-record ftl. regex-notMultiple A 192.168.3.12
pdnsutil add-record ftl. regex-notMultiple AAAA fe80::3f41
# Create reverse lookup zone
pdnsutil create-zone arpa ns1.ftl

View File

@ -58,7 +58,7 @@
@test "Number of compiled regex filters as expected" {
run bash -c 'grep "Compiled [0-9]* whitelist" /var/log/pihole/FTL.log'
printf "%s\n" "${lines[@]}"
[[ ${lines[0]} == *"Compiled 2 whitelist and 9 blacklist regex filters"* ]]
[[ ${lines[0]} == *"Compiled 2 whitelist and 11 blacklist regex filters"* ]]
}
@test "Blacklisted domain is blocked" {
@ -196,7 +196,7 @@
[[ ${lines[0]} == "2" ]]
run bash -c "grep -c 'Regex blacklist ([[:digit:]]*, DB ID [[:digit:]]*) .* NOT ENABLED for client 127.0.0.4' /var/log/pihole/FTL.log"
printf "%s\n" "${lines[@]}"
[[ ${lines[0]} == "9" ]]
[[ ${lines[0]} == "11" ]]
}
@test "Client 5: Client is recognized by MAC address" {
@ -228,7 +228,7 @@
[[ ${lines[0]} == "2" ]]
run bash -c "grep -c 'Regex blacklist ([[:digit:]]*, DB ID [[:digit:]]*) .* NOT ENABLED for client 127.0.0.5' /var/log/pihole/FTL.log"
printf "%s\n" "${lines[@]}"
[[ ${lines[0]} == "9" ]]
[[ ${lines[0]} == "11" ]]
}
@test "Client 6: Client is recognized by interface name" {
@ -266,7 +266,7 @@
[[ ${lines[0]} == "2" ]]
run bash -c "grep -c 'Regex blacklist ([[:digit:]]*, DB ID [[:digit:]]*) .* NOT ENABLED for client 127.0.0.6' /var/log/pihole/FTL.log"
printf "%s\n" "${lines[@]}"
[[ ${lines[0]} == "9" ]]
[[ ${lines[0]} == "11" ]]
}
@test "Normal query (A) is not blocked" {
@ -1082,6 +1082,42 @@
[[ "${lines[@]}" == *"- HTTPS"* ]]
}
@test "Regex Test 52: Option \";querytype=ANY,HTTPS,SVCB;reply=refused\" working as expected (ONLY matching ANY, HTTPS or SVCB queries)" {
run bash -c 'dig A regex-multiple.ftl @127.0.0.1'
printf "dig A: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: NOERROR"* ]]
run bash -c 'dig AAAA regex-multiple.ftl @127.0.0.1'
printf "dig AAAA: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: NOERROR"* ]]
run bash -c 'dig SVCB regex-multiple.ftl @127.0.0.1'
printf "dig SVCB: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: REFUSED"* ]]
run bash -c 'dig HTTPS regex-multiple.ftl @127.0.0.1'
printf "dig HTTPS: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: REFUSED"* ]]
run bash -c 'dig ANY regex-multiple.ftl @127.0.0.1'
printf "dig ANY: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: REFUSED"* ]]
}
@test "Regex Test 53: Option \";querytype=!ANY,HTTPS,SVCB;reply=refused\" working as expected (NOT matching ANY, HTTPS or SVCB queries)" {
run bash -c 'dig A regex-notMultiple.ftl @127.0.0.1'
printf "dig A: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: REFUSED"* ]]
run bash -c 'dig AAAA regex-notMultiple.ftl @127.0.0.1'
printf "dig AAAA: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: REFUSED"* ]]
run bash -c 'dig SVCB regex-notMultiple.ftl @127.0.0.1'
printf "dig SVCB: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: NOERROR"* ]]
run bash -c 'dig HTTPS regex-notMultiple.ftl @127.0.0.1'
printf "dig HTTPS: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: NOERROR"* ]]
run bash -c 'dig ANY regex-notMultiple.ftl @127.0.0.1'
printf "dig ANY: %s\n" "${lines[@]}"
[[ "${lines[@]}" == *"status: NOERROR"* ]]
}
# x86_64-musl is built on busybox which has a slightly different
# variant of ls displaying three, instead of one, spaces between the
# user and group names.