diff --git a/scripts/pi-hole/js/settings.js b/scripts/pi-hole/js/settings.js
index 93ab09cb..c50c7554 100644
--- a/scripts/pi-hole/js/settings.js
+++ b/scripts/pi-hole/js/settings.js
@@ -229,17 +229,6 @@ $(function () {
$('[data-toggle="tooltip"]').tooltip({ html: true, container: "body" });
});
-// Change "?tab=" parameter in URL for save and reload
-$(".nav-tabs a").on("shown.bs.tab", function (e) {
- var tab = e.target.hash.substring(1);
- window.history.pushState("", "", "?tab=" + tab);
- if (tab === "piholedhcp") {
- window.location.reload();
- }
-
- window.scrollTo(0, 0);
-});
-
// Auto dismissal for info notifications
$(function () {
var alInfo = $("#alInfo");
@@ -255,6 +244,25 @@ $(function () {
input.setAttribute("autocorrect", "off");
input.setAttribute("autocapitalize", "off");
input.setAttribute("spellcheck", false);
+
+ // En-/disable conditional forwarding input fields based
+ // on the checkbox state
+ $('input[name="rev_server"]').click(function () {
+ $('input[name="rev_server_cidr"]').prop("disabled", !this.checked);
+ $('input[name="rev_server_target"]').prop("disabled", !this.checked);
+ $('input[name="rev_server_domain"]').prop("disabled", !this.checked);
+ });
+});
+
+// Change "?tab=" parameter in URL for save and reload
+$(".nav-tabs a").on("shown.bs.tab", function (e) {
+ var tab = e.target.hash.substring(1);
+ window.history.pushState("", "", "?tab=" + tab);
+ if (tab === "piholedhcp") {
+ window.location.reload();
+ }
+
+ window.scrollTo(0, 0);
});
// Bar/Smooth chart toggle
diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php
index 9f8c2366..23e0efdc 100644
--- a/scripts/pi-hole/php/savesettings.php
+++ b/scripts/pi-hole/php/savesettings.php
@@ -19,6 +19,30 @@ function validIP($address){
return !filter_var($address, FILTER_VALIDATE_IP) === false;
}
+function validCIDRIP($address){
+ // This validation strategy has been taken from ../js/groups-common.js
+ $isIPv6 = strpos($address, ":") !== false;
+ if($isIPv6) {
+ // One IPv6 element is 16bit: 0000 - FFFF
+ $v6elem = "[0-9A-Fa-f]{1,4}";
+ // CIDR for IPv6 is any multiple of 4 from 4 up to 128 bit
+ $v6cidr = "(4";
+ for ($i=8; $i <= 128; $i+=4) {
+ $v6cidr .= "|$i";
+ }
+ $v6cidr .= ")";
+ $validator = "/^(((?:$v6elem))((?::$v6elem))*::((?:$v6elem))((?::$v6elem))*|((?:$v6elem))((?::$v6elem)){7})\/$v6cidr$/";
+ return preg_match($validator, $address);
+ } else {
+ // One IPv4 element is 8bit: 0 - 256
+ $v4elem = "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)";
+ // Note that rev-server accepts only /8, /16, /24, and /32
+ $allowedv4cidr = "(8|16|24|32)";
+ $validator = "/^$v4elem\.$v4elem\.$v4elem\.$v4elem\/$allowedv4cidr$/";
+ return preg_match($validator, $address);
+ }
+}
+
// Check for existance of variable
// and test it only if it exists
function istrue(&$argument) {
@@ -325,28 +349,35 @@ function addStaticDHCPLease($mac, $ip, $hostname) {
$extra .= "no-dnssec";
}
- // Check if Conditional Forwarding is requested
- if(isset($_POST["conditionalForwarding"]))
+ // Check if rev-server is requested
+ if(isset($_POST["rev_server"]))
{
- $conditionalForwardingIP = trim($_POST["conditionalForwardingIP"]);
- $conditionalForwardingDomain = trim($_POST["conditionalForwardingDomain"]);
-
- // Validate conditional forwarding IP
- if (!validIP($conditionalForwardingIP))
+ // Validate CIDR IP
+ $cidr = trim($_POST["rev_server_cidr"]);
+ if (!validCIDRIP($cidr))
{
- $error .= "Conditional forwarding IP (".htmlspecialchars($conditionalForwardingIP).") is invalid!
";
+ $error .= "Conditional forwarding subnet (\"".htmlspecialchars($cidr)."\") is invalid!
".
+ "This field requires CIDR notation for local subnets (e.g., 192.168.0.0/16).
".
+ "Please use only subnets /8, /16, /24, and /32.
";
}
- // Validate conditional forwarding domain name
- if(!validDomain($conditionalForwardingDomain))
+ // Validate target IP
+ $target = trim($_POST["rev_server_target"]);
+ if (!validIP($target))
{
- $error .= "Conditional forwarding domain name (".htmlspecialchars($conditionalForwardingDomain).") is invalid!
";
+ $error .= "Conditional forwarding target IP (\"".htmlspecialchars($target)."\") is invalid!
";
}
+
+ // Validate conditional forwarding domain name (empty is okay)
+ $domain = trim($_POST["rev_server_domain"]);
+ if(strlen($domain) > 0 && !validDomain($domain))
+ {
+ $error .= "Conditional forwarding domain name (\"".htmlspecialchars($domain)."\") is invalid!
";
+ }
+
if(!$error)
{
- $addressArray = explode(".", $conditionalForwardingIP);
- $reverseAddress = $addressArray[2].".".$addressArray[1].".".$addressArray[0].".in-addr.arpa";
- $extra .= " conditional_forwarding ".$conditionalForwardingIP." ".$conditionalForwardingDomain." $reverseAddress";
+ $extra .= " rev-server ".$cidr." ".$target." ".$domain;
}
}
diff --git a/settings.php b/settings.php
index 06512b48..1d71de0a 100644
--- a/settings.php
+++ b/settings.php
@@ -164,12 +164,13 @@ if (isset($setupVars["DNSMASQ_LISTENING"])) {
} else {
$DNSinterface = "single";
}
-if (isset($setupVars["CONDITIONAL_FORWARDING"]) && ($setupVars["CONDITIONAL_FORWARDING"] == 1)) {
- $conditionalForwarding = true;
- $conditionalForwardingDomain = $setupVars["CONDITIONAL_FORWARDING_DOMAIN"];
- $conditionalForwardingIP = $setupVars["CONDITIONAL_FORWARDING_IP"];
+if (isset($setupVars["REV_SERVER"]) && ($setupVars["REV_SERVER"] == 1)) {
+ $rev_server = true;
+ $rev_server_cidr = $setupVars["REV_SERVER_CIDR"];
+ $rev_server_target = $setupVars["REV_SERVER_TARGET"];
+ $rev_server_domain = $setupVars["REV_SERVER_DOMAIN"];
} else {
- $conditionalForwarding = false;
+ $rev_server = false;
}
?>
@@ -975,38 +976,69 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "adlists", "
when enabling DNSSEC. A DNSSEC resolver test can be found
here.
If not configured as your DHCP server, Pi-hole won't be able to +
Validate DNS replies and cache DNSSEC data. When forwarding DNS + queries, Pi-hole requests the DNSSEC records needed to validate + the replies. If a domain fails validation or the upstream does not + support DNSSEC, this setting can cause issues resolving domains. + Use Google, Cloudflare, DNS.WATCH, Quad9, or another DNS + server which supports DNSSEC when activating DNSSEC. Note that + the size of your log might increase significantly + when enabling DNSSEC. A DNSSEC resolver test can be found + here.
+If not configured as your DHCP server, Pi-hole typically won't be able to determine the names of devices on your local network. As a result, tables such as Top Clients will only show IP addresses.
One solution for this is to configure Pi-hole to forward these - requests to your DHCP server (most likely your router), but only for devices on your - home network. To configure this we will need to know the IP - address of your DHCP server and the name of your local network.
-Note: The local domain name must match the domain name specified - in your DHCP server, likely found within the DHCP settings.
-| IP of your router | -Local domain name | -
|---|---|
| - value=""> - | -value=""> - | -
If your local network spans 192.168.0.1 - 192.168.0.255, then you will have to input
+ 192.168.0.0/24. If your local network is 192.168.47.1 - 192.168.47.255, it will
+ be 192.168.47.0/24 and similar. If your network is larger, the CIDR has to be
+ different, for instance a range of 10.8.0.1 - 10.8.255.255 results in 10.8.0.0/16,
+ whereas an even wider network of 10.0.0.1 - 10.255.255.255 results in 10.0.0.0/8.
+ Setting up IPv6 ranges is exactly similar to setting up IPv4 here and fully supported.
+ Feel free to reach out to us on our
+ Discourse forum
+ in case you need any assistance setting up local host name resolution for your particular system.
You can also specify a local domain name (like fritz.box) to ensure queries to
+ devices ending in your local domain name will not leave your network, however, this is optional.
+ The local domain name must match the domain name specified
+ in your DHCP server for this to work. You can likely find it within the DHCP settings.
| Local network in CIDR notation | +IP address of your DHCP server (router) | +Local domain name (optional) | +
|---|---|---|
| + value="" + disabled> + | ++ value="" + disabled> + | ++ value="" + disabled> + | +