mirror of
https://github.com/pi-hole/web.git
synced 2024-12-06 19:36:21 +01:00
Added support for CNAME records add/remove
Signed-off-by: Matthias rank <development@m-rank.de>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
<?php /*
|
||||
* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
require "scripts/pi-hole/php/header.php";
|
||||
|
||||
?>
|
||||
|
||||
<!-- Title -->
|
||||
<div class="page-header">
|
||||
<h1>Local CNAME Records</h1>
|
||||
<small>On this page, you can add CNAME records.</small>
|
||||
</div>
|
||||
|
||||
<!-- Domain Input -->
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box">
|
||||
<!-- /.box-header -->
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Add a new CNAME record
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="domain">Domain:</label>
|
||||
<input id="domain" type="text" class="form-control" placeholder="Add a domain (example.com or sub.example.com)">
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="target">Target Domain:</label>
|
||||
<input id="target" type="url" class="form-control" placeholder="Associated Target Domain Record">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer clearfix">
|
||||
<button id="btnAdd" class="btn btn-primary pull-right">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alerts -->
|
||||
<div id="alInfo" class="alert alert-info alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Updating CNAME records...
|
||||
</div>
|
||||
<div id="alSuccess" class="alert alert-success alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Success! The list will refresh.
|
||||
</div>
|
||||
<div id="alFailure" class="alert alert-danger alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
Failure! Something went wrong, see output below:<br/><br/><pre><span id="err"></span></pre>
|
||||
</div>
|
||||
<div id="alWarning" class="alert alert-warning alert-dismissible fade in" role="alert" hidden="true">
|
||||
<button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
At least one domain was already present, see output below:<br/><br/><pre><span id="warn"></span></pre>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="recent-queries">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
List of local CNAME records
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<table id="customCNAMETable" class="display table table-striped table-bordered" cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Domain</th>
|
||||
<th>Target</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<button type="button" id="resetButton" hidden="true" class="btn btn-default btn-sm text-red">Clear Filters</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="scripts/pi-hole/js/customcname.js"></script>
|
||||
|
||||
<?php
|
||||
require "scripts/pi-hole/php/footer.php";
|
||||
?>
|
||||
@@ -0,0 +1,116 @@
|
||||
/* Pi-hole: A black hole for Internet advertisements
|
||||
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||
* Network-wide ad blocking via your own hardware.
|
||||
*
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
var table;
|
||||
|
||||
function showAlert(type, message) {
|
||||
var alertElement = null;
|
||||
var messageElement = null;
|
||||
|
||||
switch (type) {
|
||||
case "info":
|
||||
alertElement = $("#alInfo");
|
||||
break;
|
||||
case "success":
|
||||
alertElement = $("#alSuccess");
|
||||
break;
|
||||
case "warning":
|
||||
alertElement = $("#alWarning");
|
||||
messageElement = $("#warn");
|
||||
break;
|
||||
case "error":
|
||||
alertElement = $("#alFailure");
|
||||
messageElement = $("#err");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (messageElement !== null) messageElement.html(message);
|
||||
|
||||
alertElement.fadeIn(200);
|
||||
alertElement.delay(8000).fadeOut(2000);
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$("#btnAdd").on("click", addCustomCNAME);
|
||||
|
||||
table = $("#customCNAMETable").DataTable({
|
||||
ajax: "scripts/pi-hole/php/customcname.php?action=get",
|
||||
columns: [{}, {}, { orderable: false, searchable: false }],
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 2,
|
||||
render: function (data, type, row) {
|
||||
return (
|
||||
'<button class="btn btn-danger btn-xs deleteCustomCNAME" type="button" data-domain=\'' +
|
||||
row[0] +
|
||||
"' data-target='" +
|
||||
row[1] +
|
||||
"'>" +
|
||||
'<span class="far fa-trash-alt"></span>' +
|
||||
"</button>"
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
drawCallback: function () {
|
||||
$(".deleteCustomCNAME").on("click", deleteCustomCNAME);
|
||||
}
|
||||
});
|
||||
// Disable autocorrect in the search box
|
||||
var input = document.querySelector("input[type=search]");
|
||||
input.setAttribute("autocomplete", "off");
|
||||
input.setAttribute("autocorrect", "off");
|
||||
input.setAttribute("autocapitalize", "off");
|
||||
input.setAttribute("spellcheck", false);
|
||||
});
|
||||
|
||||
function addCustomCNAME() {
|
||||
var target = $("#target").val();
|
||||
var domain = $("#domain").val();
|
||||
|
||||
showAlert("info");
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/customcname.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "add", target: target, domain: domain },
|
||||
success: function (response) {
|
||||
if (response.success) {
|
||||
showAlert("success");
|
||||
table.ajax.reload();
|
||||
} else showAlert("error", response.message);
|
||||
},
|
||||
error: function () {
|
||||
showAlert("error", "Error while adding this custom CNAME record");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteCustomCNAME() {
|
||||
var target = $(this).attr("data-target");
|
||||
var domain = $(this).attr("data-domain");
|
||||
|
||||
showAlert("info");
|
||||
$.ajax({
|
||||
url: "scripts/pi-hole/php/customcname.php",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { action: "delete", domain: domain, target: target },
|
||||
success: function (response) {
|
||||
if (response.success) {
|
||||
showAlert("success");
|
||||
table.ajax.reload();
|
||||
} else showAlert("error", response.message);
|
||||
},
|
||||
error: function (jqXHR, exception) {
|
||||
showAlert("error", "Error while deleting this custom CNAME record");
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
require_once "func.php";
|
||||
|
||||
$customCNAMEFile = "/etc/dnsmasq.d/05-pihole-custom-cname.conf";
|
||||
|
||||
switch ($_REQUEST['action'])
|
||||
{
|
||||
case 'get': echo json_encode(echoCustomCNAMEEntries()); break;
|
||||
case 'add': echo json_encode(addCustomCNAMEEntry()); break;
|
||||
case 'delete': echo json_encode(deleteCustomCNAMEEntry()); break;
|
||||
default:
|
||||
die("Wrong action");
|
||||
}
|
||||
|
||||
function echoCustomCNAMEEntries()
|
||||
{
|
||||
$entries = getCustomCNAMEEntries();
|
||||
|
||||
$data = [];
|
||||
foreach ($entries as $entry)
|
||||
$data[] = [ $entry->domain, $entry->target ];
|
||||
|
||||
return [ "data" => $data ];
|
||||
}
|
||||
|
||||
function getCustomCNAMEEntries()
|
||||
{
|
||||
global $customCNAMEFile;
|
||||
|
||||
$entries = [];
|
||||
|
||||
$handle = fopen($customCNAMEFile, "r");
|
||||
if ($handle)
|
||||
{
|
||||
while (($line = fgets($handle)) !== false) {
|
||||
$line = str_replace("cname=","", $line);
|
||||
$line = str_replace("\r","", $line);
|
||||
$line = str_replace("\n","", $line);
|
||||
$explodedLine = explode (",", $line);
|
||||
|
||||
if (count($explodedLine) <= 1)
|
||||
continue;
|
||||
|
||||
$data = new \stdClass();
|
||||
$data->domains = array_slice($explodedLine, 0, -1);
|
||||
$data->domain = implode(",", $data->domains);
|
||||
$data->target = $explodedLine[count($explodedLine)-1];
|
||||
$entries[] = $data;
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
function addCustomCNAMEEntry()
|
||||
{
|
||||
try
|
||||
{
|
||||
$target = !empty($_REQUEST['target']) ? $_REQUEST['target']: "";
|
||||
$domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain']: "";
|
||||
|
||||
if (empty($target))
|
||||
return errorJsonResponse("Target must be set");
|
||||
|
||||
if (empty($domain))
|
||||
return errorJsonResponse("Domain must be set");
|
||||
|
||||
// Check if each submitted domain is valid
|
||||
$domains = array_map('trim', explode(",", $domain));
|
||||
foreach ($domains as $d) {
|
||||
if (!is_valid_domain_name($d))
|
||||
return errorJsonResponse("Domain '$d' is not valid");
|
||||
}
|
||||
|
||||
$existingEntries = getCustomCNAMEEntries();
|
||||
|
||||
// Check if a record for one of the domains already exists
|
||||
foreach ($existingEntries as $entry)
|
||||
foreach ($domains as $d)
|
||||
if (in_array($d, $entry->domains))
|
||||
return errorJsonResponse("There is already a CNAME record for '$d'");
|
||||
|
||||
exec("sudo pihole -a addcustomcname ".$domain." ".$target);
|
||||
|
||||
return successJsonResponse();
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return errorJsonResponse($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function deleteCustomCNAMEEntry()
|
||||
{
|
||||
try
|
||||
{
|
||||
$target = !empty($_REQUEST['target']) ? $_REQUEST['target']: "";
|
||||
$domain = !empty($_REQUEST['domain']) ? $_REQUEST['domain']: "";
|
||||
|
||||
if (empty($target))
|
||||
return errorJsonResponse("Target must be set");
|
||||
|
||||
if (empty($domain))
|
||||
return errorJsonResponse("Domain must be set");
|
||||
|
||||
$existingEntries = getCustomCNAMEEntries();
|
||||
|
||||
$found = false;
|
||||
foreach ($existingEntries as $entry)
|
||||
if ($entry->domain == $domain)
|
||||
if ($entry->target == $target) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$found)
|
||||
return errorJsonResponse("This domain/ip association does not exist");
|
||||
|
||||
exec("sudo pihole -a removecustomcname ".$domain." ".$target);
|
||||
|
||||
return successJsonResponse();
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return errorJsonResponse($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function successJsonResponse($message = "")
|
||||
{
|
||||
return [ "success" => true, "message" => $message ];
|
||||
}
|
||||
|
||||
function errorJsonResponse($message = "")
|
||||
{
|
||||
return [ "success" => false, "message" => $message ];
|
||||
}
|
||||
?>
|
||||
@@ -608,10 +608,25 @@ if($auth) {
|
||||
</a>
|
||||
</li>
|
||||
<!-- Local DNS Records -->
|
||||
<li<?php if($scriptname === "dns_records.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="dns_records.php">
|
||||
<i class="fa fa-address-book"></i> <span>Local DNS Records</span>
|
||||
</a>
|
||||
<li class="treeview <?php if(in_array($scriptname, array("dns_records.php", "cname_records.php"))){ ?>active<?php } ?>">
|
||||
<a href="#">
|
||||
<span class="pull-right-container">
|
||||
<i class="fa fa-angle-down pull-right" style="padding-right: 5px;"></i>
|
||||
</span>
|
||||
<i class="fa fa-address-book"></i> <span>Local DNS</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li<?php if($scriptname === "dns_records.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="dns_records.php">
|
||||
<i class="fa fa-address-book"></i> <span>DNS Records</span>
|
||||
</a>
|
||||
</li>
|
||||
<li<?php if($scriptname === "cname_records.php"){ ?> class="active"<?php } ?>>
|
||||
<a href="cname_records.php">
|
||||
<i class="fa fa-address-book"></i> <span>CNAME Records</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<!-- Logout -->
|
||||
<?php
|
||||
|
||||
Reference in New Issue
Block a user