mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
Merge pull request #1293 from pi-hole/new/force_ip46
Deprecate REPLY_ADDR4/6 in favor of more fine-grained setting
This commit is contained in:
+108
-22
@@ -502,43 +502,129 @@ void read_FTLconf(void)
|
||||
else
|
||||
logg(" RATE_LIMIT: Disabled");
|
||||
|
||||
// REPLY_ADDR4
|
||||
// LOCAL_IPV4
|
||||
// Use a specific IP address instead of automatically detecting the
|
||||
// IPv4 interface address a query arrived on
|
||||
// IPv4 interface address a query arrived on for A hostname queries
|
||||
// defaults to: not set
|
||||
config.reply_addr.overwrite_v4 = false;
|
||||
config.reply_addr.v4.s_addr = 0;
|
||||
buffer = parse_FTLconf(fp, "REPLY_ADDR4");
|
||||
if(buffer != NULL && inet_pton(AF_INET, buffer, &config.reply_addr.v4))
|
||||
config.reply_addr.overwrite_v4 = true;
|
||||
config.reply_addr.own_host.overwrite_v4 = false;
|
||||
config.reply_addr.own_host.v4.s_addr = 0;
|
||||
buffer = parse_FTLconf(fp, "LOCAL_IPV4");
|
||||
if(buffer != NULL && inet_pton(AF_INET, buffer, &config.reply_addr.own_host.v4))
|
||||
config.reply_addr.own_host.overwrite_v4 = true;
|
||||
|
||||
if(config.reply_addr.overwrite_v4)
|
||||
if(config.reply_addr.own_host.overwrite_v4)
|
||||
{
|
||||
char addr[INET_ADDRSTRLEN] = { 0 };
|
||||
inet_ntop(AF_INET, &config.reply_addr.v4, addr, INET_ADDRSTRLEN);
|
||||
logg(" REPLY_ADDR4: Using IPv4 address %s in IP blocking mode", addr);
|
||||
inet_ntop(AF_INET, &config.reply_addr.own_host.v4, addr, INET_ADDRSTRLEN);
|
||||
logg(" LOCAL_IPV4: Using IPv4 address %s for pi.hole and hostname", addr);
|
||||
}
|
||||
else
|
||||
logg(" REPLY_ADDR4: Automatic interface-dependent detection of address");
|
||||
logg(" LOCAL_IPV4: Automatic interface-dependent detection of address");
|
||||
|
||||
// REPLY_ADDR6
|
||||
// LOCAL_IPV6
|
||||
// Use a specific IP address instead of automatically detecting the
|
||||
// IPv6 interface address a query arrived on
|
||||
// IPv6 interface address a query arrived on for AAAA hostname queries
|
||||
// defaults to: not set
|
||||
config.reply_addr.overwrite_v6 = false;
|
||||
memset(&config.reply_addr.v6, 0, sizeof(config.reply_addr.v6));
|
||||
buffer = parse_FTLconf(fp, "REPLY_ADDR6");
|
||||
if(buffer != NULL && inet_pton(AF_INET6, buffer, &config.reply_addr.v6))
|
||||
config.reply_addr.overwrite_v6 = true;
|
||||
config.reply_addr.own_host.overwrite_v6 = false;
|
||||
memset(&config.reply_addr.own_host.v6, 0, sizeof(config.reply_addr.own_host.v6));
|
||||
buffer = parse_FTLconf(fp, "LOCAL_IPV6");
|
||||
if(buffer != NULL && inet_pton(AF_INET6, buffer, &config.reply_addr.own_host.v6))
|
||||
config.reply_addr.own_host.overwrite_v6 = true;
|
||||
|
||||
if(config.reply_addr.overwrite_v6)
|
||||
if(config.reply_addr.own_host.overwrite_v6)
|
||||
{
|
||||
char addr[INET6_ADDRSTRLEN] = { 0 };
|
||||
inet_ntop(AF_INET6, &config.reply_addr.v6, addr, INET6_ADDRSTRLEN);
|
||||
logg(" REPLY_ADDR6: Using IPv6 address %s in IP blocking mode", addr);
|
||||
inet_ntop(AF_INET6, &config.reply_addr.own_host.v6, addr, INET6_ADDRSTRLEN);
|
||||
logg(" LOCAL_IPV6: Using IPv6 address %s for pi.hole and hostname", addr);
|
||||
}
|
||||
else
|
||||
logg(" REPLY_ADDR6: Automatic interface-dependent detection of address");
|
||||
logg(" LOCAL_IPV6: Automatic interface-dependent detection of address");
|
||||
|
||||
// BLOCK_IPV4
|
||||
// Use a specific IPv4 address for IP blocking mode replies
|
||||
// defaults to: REPLY_ADDR4 setting
|
||||
config.reply_addr.ip_blocking.overwrite_v4 = false;
|
||||
config.reply_addr.ip_blocking.v4.s_addr = 0;
|
||||
buffer = parse_FTLconf(fp, "BLOCK_IPV4");
|
||||
if(buffer != NULL && inet_pton(AF_INET, buffer, &config.reply_addr.ip_blocking.v4))
|
||||
config.reply_addr.ip_blocking.overwrite_v4 = true;
|
||||
|
||||
if(config.reply_addr.ip_blocking.overwrite_v4)
|
||||
{
|
||||
char addr[INET_ADDRSTRLEN] = { 0 };
|
||||
inet_ntop(AF_INET, &config.reply_addr.ip_blocking.v4, addr, INET_ADDRSTRLEN);
|
||||
logg(" BLOCK_IPV4: Using IPv4 address %s in IP blocking mode", addr);
|
||||
}
|
||||
else
|
||||
logg(" BLOCK_IPV4: Automatic interface-dependent detection of address");
|
||||
|
||||
// BLOCK_IPV6
|
||||
// Use a specific IPv6 address for IP blocking mode replies
|
||||
// defaults to: REPLY_ADDR6 setting
|
||||
config.reply_addr.ip_blocking.overwrite_v6 = false;
|
||||
memset(&config.reply_addr.ip_blocking.v6, 0, sizeof(config.reply_addr.own_host.v6));
|
||||
buffer = parse_FTLconf(fp, "BLOCK_IPV6");
|
||||
if(buffer != NULL && inet_pton(AF_INET6, buffer, &config.reply_addr.ip_blocking.v6))
|
||||
config.reply_addr.ip_blocking.overwrite_v6 = true;
|
||||
|
||||
if(config.reply_addr.ip_blocking.overwrite_v6)
|
||||
{
|
||||
char addr[INET6_ADDRSTRLEN] = { 0 };
|
||||
inet_ntop(AF_INET6, &config.reply_addr.ip_blocking.v6, addr, INET6_ADDRSTRLEN);
|
||||
logg(" BLOCK_IPV6: Using IPv6 address %s in IP blocking mode", addr);
|
||||
}
|
||||
else
|
||||
logg(" BLOCK_IPV6: Automatic interface-dependent detection of address");
|
||||
|
||||
// REPLY_ADDR4 (deprecated setting)
|
||||
// Use a specific IP address instead of automatically detecting the
|
||||
// IPv4 interface address a query arrived on A hostname and IP blocked queries
|
||||
// defaults to: not set
|
||||
struct in_addr reply_addr4;
|
||||
buffer = parse_FTLconf(fp, "REPLY_ADDR4");
|
||||
if(buffer != NULL && inet_pton(AF_INET, buffer, &reply_addr4))
|
||||
{
|
||||
if(config.reply_addr.own_host.overwrite_v4 || config.reply_addr.ip_blocking.overwrite_v4)
|
||||
{
|
||||
logg(" WARNING: Ignoring REPLY_ADDR4 as LOCAL_IPV4 or BLOCK_IPV4 has been specified.");
|
||||
}
|
||||
else
|
||||
{
|
||||
config.reply_addr.own_host.overwrite_v4 = true;
|
||||
memcpy(&config.reply_addr.own_host.v4, &reply_addr4, sizeof(reply_addr4));
|
||||
config.reply_addr.ip_blocking.overwrite_v4 = true;
|
||||
memcpy(&config.reply_addr.ip_blocking.v4, &reply_addr4, sizeof(reply_addr4));
|
||||
|
||||
char addr[INET_ADDRSTRLEN] = { 0 };
|
||||
inet_ntop(AF_INET, &reply_addr4, addr, INET_ADDRSTRLEN);
|
||||
logg(" REPLY_ADDR4: Using IPv4 address %s instead of automatically determined IP address", addr);
|
||||
}
|
||||
}
|
||||
|
||||
// REPLY_ADDR6 (deprecated setting)
|
||||
// Use a specific IP address instead of automatically detecting the
|
||||
// IPv4 interface address a query arrived on A hostname and IP blocked queries
|
||||
// defaults to: not set
|
||||
struct in6_addr reply_addr6;
|
||||
buffer = parse_FTLconf(fp, "REPLY_ADDR6");
|
||||
if(buffer != NULL && inet_pton(AF_INET, buffer, &reply_addr6))
|
||||
{
|
||||
if(config.reply_addr.own_host.overwrite_v6 || config.reply_addr.ip_blocking.overwrite_v6)
|
||||
{
|
||||
logg(" WARNING: Ignoring REPLY_ADDR6 as LOCAL_IPV6 or BLOCK_IPV6 has been specified.");
|
||||
}
|
||||
else
|
||||
{
|
||||
config.reply_addr.own_host.overwrite_v6 = true;
|
||||
memcpy(&config.reply_addr.own_host.v6, &reply_addr6, sizeof(reply_addr6));
|
||||
config.reply_addr.ip_blocking.overwrite_v6 = true;
|
||||
memcpy(&config.reply_addr.ip_blocking.v6, &reply_addr6, sizeof(reply_addr6));
|
||||
|
||||
char addr[INET6_ADDRSTRLEN] = { 0 };
|
||||
inet_ntop(AF_INET6, &reply_addr6, addr, INET6_ADDRSTRLEN);
|
||||
logg(" REPLY_ADDR6: Using IPv6 address %s instead of automatically determined IP address", addr);
|
||||
}
|
||||
}
|
||||
|
||||
// SHOW_DNSSEC
|
||||
// Should FTL analyze and include automatically generated DNSSEC queries in the Query Log?
|
||||
|
||||
+13
-5
@@ -77,13 +77,21 @@ typedef struct {
|
||||
enum debug_flags debug;
|
||||
time_t DBinterval;
|
||||
struct {
|
||||
bool overwrite_v4 :1;
|
||||
bool overwrite_v6 :1;
|
||||
struct in_addr v4;
|
||||
struct in6_addr v6;
|
||||
struct {
|
||||
bool overwrite_v4 :1;
|
||||
bool overwrite_v6 :1;
|
||||
struct in_addr v4;
|
||||
struct in6_addr v6;
|
||||
} own_host;
|
||||
struct {
|
||||
bool overwrite_v4 :1;
|
||||
bool overwrite_v6 :1;
|
||||
struct in_addr v4;
|
||||
struct in6_addr v6;
|
||||
} ip_blocking;
|
||||
} reply_addr;
|
||||
} ConfigStruct;
|
||||
ASSERT_SIZEOF(ConfigStruct, 88, 80, 80);
|
||||
ASSERT_SIZEOF(ConfigStruct, 112, 104, 104);
|
||||
|
||||
typedef struct {
|
||||
const char* conf;
|
||||
|
||||
+34
-54
@@ -73,7 +73,6 @@ static char *get_ptrname(struct in_addr *addr);
|
||||
|
||||
// Static blocking metadata
|
||||
static const char *blockingreason = "";
|
||||
static union all_addr null_addrp = {{ 0 }};
|
||||
static enum reply_type force_next_DNS_reply = REPLY_UNKNOWN;
|
||||
static int last_regex_idx = -1;
|
||||
static struct ptr_record *pihole_ptr = NULL;
|
||||
@@ -322,21 +321,28 @@ size_t _FTL_make_answer(struct dns_header *header, char *limit, const size_t len
|
||||
// Add A answer record if requested
|
||||
if(flags & F_IPV4)
|
||||
{
|
||||
union all_addr *addr = &null_addrp;
|
||||
union all_addr addr = {{ 0 }};
|
||||
|
||||
// Overwrite with IP address if requested
|
||||
if(redirecting)
|
||||
addr = &redirect_addr4;
|
||||
memcpy(&addr, &redirect_addr4, sizeof(addr));
|
||||
else if(config.blockingmode == MODE_IP ||
|
||||
config.blockingmode == MODE_IP_NODATA_AAAA ||
|
||||
forced_ip)
|
||||
addr = &next_iface.addr4;
|
||||
{
|
||||
if(hostname && config.reply_addr.own_host.overwrite_v4)
|
||||
memcpy(&addr, &config.reply_addr.own_host.v4, sizeof(addr));
|
||||
else if(!hostname && config.reply_addr.ip_blocking.overwrite_v4)
|
||||
memcpy(&addr, &config.reply_addr.ip_blocking.v4, sizeof(addr));
|
||||
else
|
||||
memcpy(&addr, &next_iface.addr4, sizeof(addr));
|
||||
}
|
||||
|
||||
// Debug logging
|
||||
if(config.debug & DEBUG_QUERIES)
|
||||
{
|
||||
char ip[ADDRSTRLEN+1] = { 0 };
|
||||
alladdr_extract_ip(addr, AF_INET, ip);
|
||||
alladdr_extract_ip(&addr, AF_INET, ip);
|
||||
logg(" Adding RR: \"%s A %s\"", name, ip);
|
||||
}
|
||||
|
||||
@@ -344,27 +350,34 @@ size_t _FTL_make_answer(struct dns_header *header, char *limit, const size_t len
|
||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||
if(add_resource_record(header, limit, &trunc, sizeof(struct dns_header),
|
||||
&p, hostname ? daemon->local_ttl : config.block_ttl,
|
||||
NULL, T_A, C_IN, (char*)"4", &addr->addr4))
|
||||
log_query(flags & ~F_IPV6, name, addr, (char*)blockingreason, 0);
|
||||
NULL, T_A, C_IN, (char*)"4", &addr.addr4))
|
||||
log_query(flags & ~F_IPV6, name, &addr, (char*)blockingreason, 0);
|
||||
}
|
||||
|
||||
// Add AAAA answer record if requested
|
||||
if(flags & F_IPV6)
|
||||
{
|
||||
union all_addr *addr = &null_addrp;
|
||||
union all_addr addr = {{ 0 }};
|
||||
|
||||
// Overwrite with IP address if requested
|
||||
if(redirecting)
|
||||
addr = &redirect_addr6;
|
||||
memcpy(&addr, &redirect_addr6, sizeof(addr));
|
||||
else if(config.blockingmode == MODE_IP ||
|
||||
forced_ip)
|
||||
addr = &next_iface.addr6;
|
||||
{
|
||||
if(hostname && config.reply_addr.own_host.overwrite_v6)
|
||||
memcpy(&addr, &config.reply_addr.own_host.v6, sizeof(addr));
|
||||
else if(!hostname && config.reply_addr.ip_blocking.overwrite_v6)
|
||||
memcpy(&addr, &config.reply_addr.ip_blocking.v6, sizeof(addr));
|
||||
else
|
||||
memcpy(&addr, &next_iface.addr6, sizeof(addr));
|
||||
}
|
||||
|
||||
// Debug logging
|
||||
if(config.debug & DEBUG_QUERIES)
|
||||
{
|
||||
char ip[ADDRSTRLEN+1] = { 0 };
|
||||
alladdr_extract_ip(addr, AF_INET6, ip);
|
||||
alladdr_extract_ip(&addr, AF_INET6, ip);
|
||||
logg(" Adding RR: \"%s AAAA %s\"", name, ip);
|
||||
}
|
||||
|
||||
@@ -372,8 +385,8 @@ size_t _FTL_make_answer(struct dns_header *header, char *limit, const size_t len
|
||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||
if(add_resource_record(header, limit, &trunc, sizeof(struct dns_header),
|
||||
&p, hostname ? daemon->local_ttl : config.block_ttl,
|
||||
NULL, T_AAAA, C_IN, (char*)"6", &addr->addr6))
|
||||
log_query(flags & ~F_IPV4, name, addr, (char*)blockingreason, 0);
|
||||
NULL, T_AAAA, C_IN, (char*)"6", &addr.addr6))
|
||||
log_query(flags & ~F_IPV4, name, &addr, (char*)blockingreason, 0);
|
||||
}
|
||||
|
||||
// Log empty replies
|
||||
@@ -507,8 +520,12 @@ bool _FTL_new_query(const unsigned int flags, const char *name,
|
||||
// Send NODATA when the current interface doesn't have
|
||||
// the requested IP address, for instance AAAA on an
|
||||
// virtual interface that has only an IPv4 address
|
||||
if((querytype == TYPE_A && !next_iface.haveIPv4) ||
|
||||
(querytype == TYPE_AAAA && !next_iface.haveIPv6))
|
||||
if((querytype == TYPE_A &&
|
||||
!next_iface.haveIPv4 &&
|
||||
!config.reply_addr.own_host.overwrite_v4) ||
|
||||
(querytype == TYPE_AAAA &&
|
||||
!next_iface.haveIPv6 &&
|
||||
!config.reply_addr.own_host.overwrite_v6))
|
||||
force_next_DNS_reply = REPLY_NODATA;
|
||||
else
|
||||
force_next_DNS_reply = REPLY_IP;
|
||||
@@ -820,40 +837,14 @@ void _FTL_iface(struct irec *recviface, const union all_addr *addr, const sa_fam
|
||||
if(config.debug & DEBUG_NETWORKING)
|
||||
logg("Interfaces: Called from %s:%d", short_path(file), line);
|
||||
|
||||
// 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));
|
||||
next_iface.haveIPv4 = true;
|
||||
|
||||
if(config.debug & DEBUG_NETWORKING)
|
||||
{
|
||||
char buffer[ADDRSTRLEN+1] = { 0 };
|
||||
inet_ntop(AF_INET, &next_iface.addr4, buffer, ADDRSTRLEN);
|
||||
logg("Configuration overwrites IPv4 address: %s", buffer);
|
||||
}
|
||||
}
|
||||
if(config.reply_addr.overwrite_v6)
|
||||
{
|
||||
memcpy(&next_iface.addr6, &config.reply_addr.v6, sizeof(config.reply_addr.v6));
|
||||
next_iface.haveIPv6 = true;
|
||||
|
||||
if(config.debug & DEBUG_NETWORKING)
|
||||
{
|
||||
char buffer[ADDRSTRLEN+1] = { 0 };
|
||||
inet_ntop(AF_INET6, &next_iface.addr6, buffer, ADDRSTRLEN);
|
||||
logg("Configuration overwrites IPv6 address: %s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Use dummy when interface record is not available
|
||||
next_iface.name[0] = '-';
|
||||
next_iface.name[1] = '\0';
|
||||
|
||||
// Check if we need to identify the receving interface by its address
|
||||
if(!recviface && addr &&
|
||||
((addrfamily == AF_INET && addr->addr4.s_addr != 0) ||
|
||||
(addrfamily == AF_INET6 && addr->addr6.s6_addr[0] != 0)))
|
||||
((addrfamily == AF_INET && addr->addr4.s_addr != INADDR_ANY) ||
|
||||
(addrfamily == AF_INET6 && !IN6_IS_ADDR_UNSPECIFIED(&addr->addr6))))
|
||||
{
|
||||
if(config.debug & DEBUG_NETWORKING)
|
||||
{
|
||||
@@ -953,17 +944,6 @@ void _FTL_iface(struct irec *recviface, const union all_addr *addr, const sa_fam
|
||||
strncpy(next_iface.name, iname, sizeof(next_iface.name)-1);
|
||||
next_iface.name[sizeof(next_iface.name)-1] = '\0';
|
||||
|
||||
// Check if this family type is overwritten by config settings
|
||||
// We logged this above
|
||||
if((config.reply_addr.overwrite_v4 && family == AF_INET) ||
|
||||
(config.reply_addr.overwrite_v6 && family == AF_INET6))
|
||||
{
|
||||
if(config.debug & DEBUG_NETWORKING)
|
||||
logg(" - SKIP IPv%d interface %s: REPLY_ADDR%d used",
|
||||
family == AF_INET ? 4 : 6, iname, family == AF_INET ? 4 : 6);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isULA = false, isGUA = false, isLL = false;
|
||||
// Check if this address is different from 0000:0000:0000:0000:0000:0000:0000:0000
|
||||
if(family == AF_INET6 && memcmp(&next_iface.addr6.addr6, &iface->addr.in6.sin6_addr, sizeof(iface->addr.in6.sin6_addr)) != 0)
|
||||
|
||||
@@ -2,3 +2,7 @@ DEBUG_ALL=true
|
||||
RESOLVE_IPV4=no
|
||||
RESOLVE_IPV6=no
|
||||
CHECK_LOAD=false
|
||||
LOCAL_IPV4=10.100.0.10
|
||||
LOCAL_IPV6=fe80::10
|
||||
BLOCK_IPV4=10.100.0.11
|
||||
BLOCK_IPV6=fe80::11
|
||||
|
||||
@@ -1279,3 +1279,33 @@
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[0]}" == "" ]]
|
||||
}
|
||||
|
||||
@test "Pi-hole uses LOCAL_IPV4/6 for pi.hole" {
|
||||
run bash -c "dig A pi.hole +short @127.0.0.1"
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[0]}" == "10.100.0.10" ]]
|
||||
run bash -c "dig AAAA pi.hole +short @127.0.0.1"
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[0]}" == "fe80::10" ]]
|
||||
}
|
||||
|
||||
@test "Pi-hole uses LOCAL_IPV4/6 for hostname" {
|
||||
run bash -c "dig A $(hostname) +short @127.0.0.1"
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[0]}" == "10.100.0.10" ]]
|
||||
run bash -c "dig AAAA $(hostname) +short @127.0.0.1"
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[0]}" == "fe80::10" ]]
|
||||
}
|
||||
|
||||
@test "Pi-hole uses BLOCK_IPV4/6 for blocked domain" {
|
||||
echo "BLOCKINGMODE=IP" >> /etc/pihole/pihole-FTL.conf
|
||||
run bash -c "kill -HUP $(cat /run/pihole-FTL.pid)"
|
||||
sleep 2
|
||||
run bash -c "dig A blacklisted.ftl +short @127.0.0.1"
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[0]}" == "10.100.0.11" ]]
|
||||
run bash -c "dig AAAA blacklisted.ftl +short @127.0.0.1"
|
||||
printf "%s\n" "${lines[@]}"
|
||||
[[ "${lines[0]}" == "fe80::11" ]]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user