Files
DnsServer/DnsServerCore/www/index.html

7083 lines
568 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<!--
Technitium DNS Server
Copyright (C) 2026 Shreyas Zare (shreyas@technitium.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="referrer" content="no-referrer" />
<title>Technitium DNS Server</title>
<script src="js/jquery.min.js"></script>
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap.min.js"></script>
<script src="js/Chart.min.js"></script>
<link href="css/font-awesome.min.css" rel="stylesheet" />
<script src="js/moment.min.js"></script>
<link href="css/main.css" rel="stylesheet" />
<script src="js/common.js"></script>
<script src="js/main.js"></script>
<script src="js/auth.js"></script>
<script src="js/cluster.js"></script>
<script src="js/zone.js"></script>
<script src="js/other-zones.js"></script>
<script src="js/apps.js"></script>
<script src="js/dnsclient.js"></script>
<script src="js/dhcp.js"></script>
<script src="js/logs.js"></script>
</head>
<body style="background-color: #fafafa;">
<div id="header">
<div id="mnuUser" class="menu dropdown" style="display: none;">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" style="text-decoration: none;">
<span class="menu-title">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
<span id="mnuUserDisplayName"></span>
<span class="caret"></span>
</span>
</a>
<ul class="dropdown-menu">
<li><a href="#" onclick="showMyProfileModal(); return false;">My Profile</a></li>
<li><a href="#" onclick="showCreateMyApiTokenModal(); return false;">Create API Token</a></li>
<li><a href="#" onclick="showChangePasswordModal(); return false;">Change Password</a></li>
<li><a href="#" onclick="showConfigure2FAModal(); return false;">Configure 2FA</a></li>
<li><a href="#" onclick="toggleTheme(); return false;">Toggle Dark Mode</a></li>
<li role="separator" class="divider"></li>
<li><a href="#" onclick="logout(); return false;">Logout</a></li>
</ul>
</div>
</div>
<div id="content">
<div class="container">
<div class="AlertPlaceholder"></div>
<div id="pageLogin" class="pageLogin">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">DNS Server</h3>
</div>
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<label for="txtUser" class="col-sm-3 control-label">Username</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="txtUser" placeholder="username">
</div>
</div>
<div class="form-group">
<label for="txtPass" class="col-sm-3 control-label">Password</label>
<div class="col-sm-8">
<input type="password" class="form-control" id="txtPass" placeholder="password">
</div>
</div>
<div class="form-group" id="div2FAOTP">
<label for="txt2FATOTP" class="col-sm-3 control-label">Enter OTP</label>
<div class="col-sm-8">
<input id="txt2FATOTP" type="text" class="form-control" style="width: 100px;" placeholder="OTP" maxlength="6" autocomplete="off">
<div style="padding-top: 5px;">Enter the 6-digit code you see in your authenticator app.</div>
</div>
</div>
<div class="form-group" style="margin-bottom: 0px;">
<div class="col-sm-offset-3 col-sm-4">
<button id="btnLogin" type="submit" class="btn btn-primary" data-loading-text="Working..." onclick="login(); return false;">Login</button>
</div>
<div class="col-sm-4" style="padding: 6px; text-align: right;">
<a href="#" data-toggle="modal" data-target="#modalForgotPassword">Forgot Password?</a>
</div>
</div>
</form>
</div>
</div>
</div>
<div id="pageMain" class="page">
<div class="panel panel-default">
<div class="panel-heading" style="height: 38px;">
<div style="float: left;">
<h3 class="panel-title">DNS Server<span id="lblDnsServerDomain"></span></h3>
</div>
<div style="float: right;">
<a href="#" data-toggle="modal" data-target="#modalUpdateAvailable" id="lnkUpdateAvailable" style="display: none; color: red !important;">New Update Available!</a>
</div>
</div>
<div class="panel-body" style="min-height: 500px;">
<div>
<ul class="nav nav-tabs" role="tablist">
<li id="mainPanelTabListDashboard" role="presentation" class="active"><a href="#mainPanelTabPaneDashboard" aria-controls="mainPanelTabPaneDashboard" role="tab" data-toggle="tab" onclick="refreshDashboard();">Dashboard</a></li>
<li id="mainPanelTabListZones" role="presentation"><a href="#mainPanelTabPaneZones" aria-controls="mainPanelTabPaneZones" role="tab" data-toggle="tab" onclick="refreshZones(true);">Zones</a></li>
<li id="mainPanelTabListCachedZones" role="presentation"><a href="#mainPanelTabPaneCachedZones" aria-controls="mainPanelTabPaneCachedZones" role="tab" data-toggle="tab">Cache</a></li>
<li id="mainPanelTabListAllowedZones" role="presentation"><a href="#mainPanelTabPaneAllowedZones" aria-controls="mainPanelTabPaneAllowedZones" role="tab" data-toggle="tab">Allowed</a></li>
<li id="mainPanelTabListBlockedZones" role="presentation"><a href="#mainPanelTabPaneBlockedZones" aria-controls="mainPanelTabPaneBlockedZones" role="tab" data-toggle="tab">Blocked</a></li>
<li id="mainPanelTabListApps" role="presentation"><a href="#mainPanelTabPaneApps" aria-controls="mainPanelTabPaneApps" role="tab" data-toggle="tab" onclick="refreshApps();">Apps</a></li>
<li id="mainPanelTabListDnsClient" role="presentation"><a href="#mainPanelTabPaneDnsClient" aria-controls="mainPanelTabPaneDnsClient" role="tab" data-toggle="tab">DNS Client</a></li>
<li id="mainPanelTabListSettings" role="presentation"><a href="#mainPanelTabPaneSettings" aria-controls="mainPanelTabPaneSettings" role="tab" data-toggle="tab" onclick="refreshDnsSettings();">Settings</a></li>
<li id="mainPanelTabListDhcp" role="presentation"><a href="#mainPanelTabPaneDhcp" aria-controls="mainPanelTabPaneDhcp" role="tab" data-toggle="tab" onclick="refreshDhcpTab();">DHCP</a></li>
<li id="mainPanelTabListAdmin" role="presentation"><a href="#mainPanelTabPaneAdmin" aria-controls="mainPanelTabPaneAdmin" role="tab" data-toggle="tab" onclick="refreshAdminTab();">Administration</a></li>
<li id="mainPanelTabListLogs" role="presentation"><a href="#mainPanelTabPaneLogs" aria-controls="mainPanelTabPaneLogs" role="tab" data-toggle="tab" onclick="refreshLogsTab();">Logs</a></li>
<li id="mainPanelTabListAbout" role="presentation"><a href="#mainPanelTabPaneAbout" aria-controls="mainPanelTabPaneAbout" role="tab" data-toggle="tab">About</a></li>
</ul>
<div class="tab-content">
<div id="mainPanelTabPaneDashboard" role="tabpanel" class="tab-pane active" style="padding: 10px 0 0 0;">
<div>
<div class="pull-left">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-default active">
<input type="radio" name="rdStatType" value="lastHour" autocomplete="off" checked> Last Hour
</label>
<label class="btn btn-default">
<input type="radio" name="rdStatType" value="lastDay" autocomplete="off"> Last Day
</label>
<label class="btn btn-default">
<input type="radio" name="rdStatType" value="lastWeek" autocomplete="off"> Last Week
</label>
<label class="btn btn-default">
<input type="radio" name="rdStatType" value="lastMonth" autocomplete="off"> Last Month
</label>
<label class="btn btn-default">
<input type="radio" name="rdStatType" value="lastYear" autocomplete="off"> Last Year
</label>
<label class="btn btn-default">
<input type="radio" name="rdStatType" value="custom" autocomplete="off"> Custom
</label>
</div>
<div id="divCustomDayWise" style="padding: 6px 0px 0px; display: none;">
<span style="margin-right: 6px;"><label for="dpCustomDayWiseStart">Start</label> <input type="datetime-local" id="dpCustomDayWiseStart" size="10"></span>
<span style="margin-right: 6px;"><label for="dpCustomDayWiseEnd">End</label> <input type="datetime-local" id="dpCustomDayWiseEnd" size="10"></span>
<button id="btnCustomDayWise" class="btn btn-default" type="button" style="font-size: 12px; padding: 3px 0px; width: 60px; vertical-align: top;">Show</button>
</div>
</div>
<div class="pull-right">
<select id="optDashboardClusterNode" class="form-control cluster-node-dropdown" style="margin-left: 0px;" onchange="refreshDashboard();"></select>
</div>
<div class="clearfix"></div>
</div>
<div id="divDashboardLoader" style="margin-top: 10px; height: 400px;"></div>
<div id="divDashboard" style="display: none;">
<div class="stats-panel">
<div class="stats-item total-queries">
<div class="number" id="divDashboardStatsTotalQueries">100</div>
<div class="percentage">100%</div>
<div class="title">Total Queries</div>
</div>
<div class="stats-item no-error">
<div class="number" id="divDashboardStatsTotalNoError">70</div>
<div class="percentage" id="divDashboardStatsTotalNoErrorPercentage">0%</div>
<div class="title">No Error</div>
</div>
<div class="stats-item server-failure">
<div class="number" id="divDashboardStatsTotalServerFailure">5</div>
<div class="percentage" id="divDashboardStatsTotalServerFailurePercentage">0%</div>
<div class="title">Server Failure</div>
</div>
<div class="stats-item nxdomain">
<div class="number" id="divDashboardStatsTotalNxDomain">5</div>
<div class="percentage" id="divDashboardStatsTotalNxDomainPercentage">0%</div>
<div class="title">NX Domain</div>
</div>
<div class="stats-item refused">
<div class="number" id="divDashboardStatsTotalRefused">10</div>
<div class="percentage" id="divDashboardStatsTotalRefusedPercentage">0%</div>
<div class="title">Refused</div>
</div>
<div class="stats-item auth-hit">
<div class="number" id="divDashboardStatsTotalAuthHit">10</div>
<div class="percentage" id="divDashboardStatsTotalAuthHitPercentage">0%</div>
<div class="title">Authoritative</div>
</div>
<div class="stats-item recursions">
<div class="number" id="divDashboardStatsTotalRecursions">10</div>
<div class="percentage" id="divDashboardStatsTotalRecursionsPercentage">0%</div>
<div class="title">Recursive</div>
</div>
<div class="stats-item cache-hit">
<div class="number" id="divDashboardStatsTotalCacheHit">10</div>
<div class="percentage" id="divDashboardStatsTotalCacheHitPercentage">0%</div>
<div class="title">Cached</div>
</div>
<div class="stats-item blocked">
<div class="number" id="divDashboardStatsTotalBlocked">10</div>
<div class="percentage" id="divDashboardStatsTotalBlockedPercentage">0%</div>
<div class="title">Blocked</div>
</div>
<div class="stats-item dropped">
<div class="number" id="divDashboardStatsTotalDropped">5</div>
<div class="percentage" id="divDashboardStatsTotalDroppedPercentage">0%</div>
<div class="title">Dropped</div>
</div>
<div class="stats-item stats-last-item clients">
<div class="number" id="divDashboardStatsTotalClients">10</div>
<div class="percentage">&nbsp;</div>
<div class="title">Clients</div>
</div>
</div>
<div>
<canvas id="canvasDashboardMain" style="margin: 10px 0 10px 0;"></canvas>
</div>
<div style="margin-top: 15px;">
<div style="float: left; width: 50%; padding-right: 7px;">
<div class="panel panel-default" style="margin-bottom: 15px;">
<div class="panel-body">
<canvas id="canvasDashboardPie"></canvas>
</div>
</div>
<div class="panel panel-default" style="margin-bottom: 15px;">
<div class="panel-body">
<canvas id="canvasDashboardPie2"></canvas>
</div>
</div>
<div class="panel panel-default" style="margin-bottom: 0px;">
<div class="panel-body">
<canvas id="canvasDashboardPie3"></canvas>
</div>
</div>
</div>
<div style="float: right; width: 50%; padding-left: 7px;">
<div class="zone-stats-panel">
<div class="stats-item">
<div class="number" id="divDashboardStatsZones">10</div>
<div class="title">Zones</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsCachedEntries">10</div>
<div class="title">Cache</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsAllowedZones">10</div>
<div class="title">Allowed</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsBlockedZones">10</div>
<div class="title">Blocked</div>
</div>
<div class="stats-item">
<div class="number" id="divDashboardStatsAllowListZones">10</div>
<div class="title">Allow List</div>
</div>
<div class="stats-item stats-last-item">
<div class="number" id="divDashboardStatsBlockListZones">10</div>
<div class="title">Block List</div>
</div>
<div class="clearfix"></div>
</div>
<div class="panel panel-default" style="margin-bottom: 0px;">
<div class="panel-heading" style="height: 41px; padding: 4px 6px;">
<div class="pull-left" style="padding: 6px 8px;">Top Clients</div>
<div class="pull-right">
<button type="button" class="btn btn-default" data-loading-text="More" onclick="showTopStats('TopClients', 1000);" style="font-size: 12px; padding: 4px 14px; margin: 2px 0px;">More</button>
</div>
<div class="clearfix"></div>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>Client</th>
<th>Queries</th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tableTopClients">
</tbody>
</table>
</div>
</div>
<div style="clear: both;"></div>
</div>
<div style="margin-top: 15px;">
<div style="float: left; width: 50%; padding-right: 7px;">
<div class="panel panel-default" style="margin-bottom: 0px;">
<div class="panel-heading" style="height: 41px; padding: 4px 6px;">
<div class="pull-left" style="padding: 6px 8px;">Top Domains</div>
<div class="pull-right">
<button type="button" class="btn btn-default" data-loading-text="More" onclick="showTopStats('TopDomains', 1000);" style="font-size: 12px; padding: 4px 14px; margin: 2px 0px;">More</button>
</div>
<div class="clearfix"></div>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>Domain</th>
<th>Hits</th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tableTopDomains">
</tbody>
</table>
</div>
</div>
<div style="float: right; width: 50%; padding-left: 7px;">
<div class="panel panel-default" style="margin-bottom: 0px;">
<div class="panel-heading" style="height: 41px; padding: 4px 6px;">
<div class="pull-left" style="padding: 6px 8px;">Top Blocked Domains</div>
<div class="pull-right">
<div class="btn-group">
<button id="btnDashboardBlockingOptions" onclick="dashboardBlockingOptionsOnClick();" data-loading-text="Blocking" type="button" class="btn btn-default dropdown-toggle" style="font-size: 12px; padding: 4px 14px; margin: 2px 0px;" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Blocking <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li id="mnuDashboardBlockingOptionsEnableBlocking" style="display: none;"><a href="#" onclick="enableBlocking(); return false;">Enable Blocking</a></li>
<li id="mnuDashboardBlockingOptionsDisableBlocking" style="display: none;"><a href="#" onclick="disableBlocking(); return false;">Disable Blocking</a></li>
<li><a href="#" onclick="temporaryDisableBlockingForMenu(1); return false;">Disable Blocking For 1 Minute</a></li>
<li><a href="#" onclick="temporaryDisableBlockingForMenu(2); return false;">Disable Blocking For 2 Minutes</a></li>
<li><a href="#" onclick="temporaryDisableBlockingForMenu(5); return false;">Disable Blocking For 5 Minutes</a></li>
<li><a href="#" onclick="temporaryDisableBlockingForMenu(10); return false;">Disable Blocking For 10 Minutes</a></li>
<li><a href="#" onclick="temporaryDisableBlockingForMenu(15); return false;">Disable Blocking For 15 Minutes</a></li>
<li><a href="#" onclick="temporaryDisableBlockingForMenu(30); return false;">Disable Blocking For 30 Minutes</a></li>
<li><a href="#" onclick="temporaryDisableBlockingForMenu(60); return false;">Disable Blocking For 1 Hour</a></li>
<li><a href="#" onclick="temporaryDisableBlockingForMenu(180); return false;">Disable Blocking For 3 Hours</a></li>
</ul>
</div>
<button type="button" class="btn btn-default" data-loading-text="More" onclick="showTopStats('TopBlockedDomains', 1000);" style="font-size: 12px; padding: 4px 14px; margin: 2px 0px;">More</button>
</div>
<div class="clearfix"></div>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>Domain</th>
<th>Hits</th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tableTopBlockedDomains">
</tbody>
</table>
</div>
</div>
<div style="clear: both;"></div>
</div>
</div>
</div>
<div id="mainPanelTabPaneZones" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<div id="divViewZonesLoader" style="display: none; margin-top: 10px; height: 400px;"></div>
<div id="divViewZones">
<div class="form-inline" style="margin-bottom: 4px;">
<div class="pull-right">
<div class="form-group" style="margin-right: 0px;">
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showAddZoneModal();">Add Zone</button>
<select id="optZonesClusterNode" class="form-control cluster-node-dropdown" onchange="refreshZones();"></select>
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="form-inline">
<form class="pull-left">
<div class="form-group">
<input id="txtZonesEdit" class="form-control" style="width: 300px;" type="text" placeholder="example.com" />
<button type="submit" class="btn btn-primary" onclick="showEditZone(); return false;">Edit</button>
</div>
</form>
<form class="pull-right">
<div class="form-group">
<label for="txtZonesPageNumber">Page Number</label>
<input id="txtZonesPageNumber" class="form-control" style="width: 100px;" type="number" />
</div>
<div class="form-group">
<label for="optZonesPerPage">Zones Per Page</label>
<select class="form-control" id="optZonesPerPage">
<option selected>10</option>
<option>25</option>
<option>50</option>
<option>100</option>
<option>250</option>
<option>500</option>
</select>
</div>
<button type="submit" class="btn btn-primary form-group" style="margin-right: 0px;" onclick="refreshZones(); return false;">Go</button>
</form>
<div class="clearfix"></div>
</div>
<div style="padding: 8px;">
<div class="pull-left" style="padding-top: 8px;">
<b id="tableZonesTopStatus">0 zones</b>
</div>
<div class="pull-right">
<nav aria-label="Page navigation">
<ul id="tableZonesTopPagination" class="pagination" style="margin: 0;">
<li><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
<li><a href="#">1</a></li>
<li><a href="#" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
</ul>
</nav>
</div>
<div class="clearfix"></div>
</div>
<table id="tableZones" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tableZonesBody', 0); return false;">#</a></th>
<th><a href="#" onclick="sortTable('tableZonesBody', 1); return false;">Zone</a></th>
<th><a href="#" onclick="sortTable('tableZonesBody', 2); return false;">Type</a></th>
<th><a href="#" onclick="sortTable('tableZonesBody', 3); return false;">DNSSEC</a></th>
<th><a href="#" onclick="sortTable('tableZonesBody', 4); return false;">Status</a></th>
<th><a href="#" onclick="sortTable('tableZonesBody', 5); return false;">Serial</a></th>
<th><a href="#" onclick="sortTable('tableZonesBody', 6); return false;">Expiry</a></th>
<th><a href="#" onclick="sortTable('tableZonesBody', 7); return false;">Last Modified</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tableZonesBody"></tbody>
<tfoot>
<tr>
<td colspan="9">
<div>
<div class="pull-left" style="padding-top: 8px;">
<b id="tableZonesFooterStatus">0 zones</b>
</div>
<div class="pull-right">
<nav aria-label="Page navigation">
<ul id="tableZonesFooterPagination" class="pagination" style="margin: 0;">
<li><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
<li><a href="#">1</a></li>
<li><a href="#" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
</ul>
</nav>
</div>
<div class="clearfix"></div>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
<div id="divEditZone" style="display: none;">
<div>
<div class="pull-left">
<ul class="pager" style="margin: 0px;">
<li class="previous"><a href="#" onclick="refreshZones(); return false;"><span aria-hidden="true">&larr;</span> Back</a></li>
</ul>
</div>
<div class="pull-right">
<select id="optEditZoneClusterNode" class="form-control cluster-node-dropdown" style="margin-left: 0px;" disabled></select>
</div>
<div class="clearfix"></div>
</div>
<div style="padding: 10px 0px;">
<h3 style="margin: 4px 0;"><span id="titleEditZone" style="margin-right: 10px;">example.com</span><a href="#" onclick="showEditZone($('#titleEditZone').attr('data-zone'), $('#txtEditZonePageNumber').val(), $('#txtEditZoneFilterName').val(), $('#txtEditZoneFilterType').val()); return false;"><span class="glyphicon glyphicon-refresh" style="font-size: 20px;" aria-hidden="true"></span></a></h3>
<div style="float: left;">
<span id="titleEditZoneType" class="label label-default">Primary</span>
<span id="titleEditZoneDnssecStatus" class="label label-default">DNSSEC</span>
<span id="titleEditZoneStatus" class="label label-success">Enabled</span>
<span id="titleEditZoneCatalog" class="label label-default">catalog</span>
<div id="titleEditZoneExpiry" style="padding-top: 4px; font-size: 10px; font-weight: bold;">Expiry: 01 Jan 2020 00:00:00</div>
</div>
<div style="float: right; padding: 2px 0px;">
<button id="btnEditZoneAddRecord" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showAddRecordModal();">Add Record</button>
<button id="btnEnableZoneEditZone" type="button" class="btn btn-default" style="padding: 2px 0px; width: 100px;" onclick="enableZone(this);">Enable Zone</button>
<button id="btnDisableZoneEditZone" type="button" class="btn btn-warning" style="padding: 2px 0px; width: 100px;" onclick="disableZone(this);">Disable Zone</button>
<button id="btnEditZoneDeleteZone" type="button" class="btn btn-danger" style="padding: 2px 0px; width: 100px;" onclick="deleteZone(this);">Delete Zone</button>
<button id="btnZoneResync" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="resyncZone(this, $('#titleEditZone').attr('data-zone'));" data-loading-text="Resyncing...">Resync</button>
<div id="divOptionsMenu" class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" style="padding: 2px 0px; width: 100px;" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Options <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li id="lnkImportZone"><a href="#" onclick="showImportZoneModal($('#titleEditZone').attr('data-zone')); return false;">Import Zone</a></li>
<li id="lnkExportZone"><a href="#" onclick="exportZone($('#titleEditZone').attr('data-zone')); return false;">Export Zone</a></li>
<li id="lnkZoneConvert"><a href="#" onclick="showConvertZoneModal($('#titleEditZone').attr('data-zone'), $('#titleEditZone').attr('data-zone-type')); return false;">Convert Zone</a></li>
<li id="lnkCloneZone"><a href="#" onclick="showCloneZoneModal($('#titleEditZone').attr('data-zone')); return false;">Clone Zone</a></li>
<li id="lnkZoneOptions"><a href="#" onclick="$('#btnSaveZoneOptions').attr('data-zones-row-id', null); showZoneOptionsModal($('#titleEditZone').attr('data-zone')); return false;">Zone Options</a></li>
</ul>
</div>
<button id="btnZonePermissions" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showZonePermissionsModal($('#titleEditZone').attr('data-zone'));">Permissions</button>
<div id="divZoneDnssecOptions" class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" style="padding: 2px 0px; width: 100px;" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
DNSSEC <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li id="lnkZoneDnssecSignZone"><a href="#" onclick="showSignZoneModal($('#titleEditZone').attr('data-zone')); return false;">Sign Zone</a></li>
<li id="lnkZoneDnssecHideRecords"><a href="#" onclick="toggleHideDnssecRecords(true); return false;">Hide DNSSEC Records</a></li>
<li id="lnkZoneDnssecShowRecords"><a href="#" onclick="toggleHideDnssecRecords(false); return false;">Show DNSSEC Records</a></li>
<li id="lnkZoneDnssecViewDsRecords"><a href="#" onclick="showViewDsModal($('#titleEditZone').attr('data-zone')); return false;">View DS Info</a></li>
<li id="lnkZoneDnssecProperties"><a href="#" onclick="showDnssecPropertiesModal($('#titleEditZone').attr('data-zone')); return false;">Properties</a></li>
<li id="lnkZoneDnssecUnsignZone"><a href="#" onclick="showUnsignZoneModal($('#titleEditZone').attr('data-zone')); return false;">Unsign Zone</a></li>
</ul>
</div>
</div>
<div style="clear: both;"></div>
</div>
<div class="form-inline well" style="padding: 10px 10px 0 10px;margin-bottom: 10px;">
<form>
<div class="pull-left">
<div class="form-group">
<label for="txtEditZoneFilterName">Name</label>
<input id="txtEditZoneFilterName" class="form-control" style="width: 300px;" type="text" placeholder="abc or a* or *b* or a?c" />
</div>
<div class="form-group">
<label for="txtEditZoneFilterType">Type</label>
<input id="txtEditZoneFilterType" class="form-control" style="width: 130px;" type="text" />
</div>
</div>
<div class="pull-right">
<div class="form-group">
<label for="txtEditZonePageNumber">Page Number</label>
<input id="txtEditZonePageNumber" class="form-control" style="width: 100px;" type="number" />
</div>
<div class="form-group">
<label for="optEditZoneRecordsPerPage">Records Per Page</label>
<select class="form-control" id="optEditZoneRecordsPerPage">
<option selected>10</option>
<option>25</option>
<option>50</option>
<option>100</option>
<option>250</option>
<option>500</option>
</select>
</div>
<button type="submit" class="btn btn-primary form-group" style="margin-right: 0px;" onclick="showEditZonePage(); return false;">Go</button>
</div>
<div class="clearfix"></div>
</form>
</div>
<div style="padding: 8px;">
<div class="pull-left" style="padding-top: 8px;">
<b id="tableEditZoneTopStatus">0 records</b>
</div>
<div class="pull-right">
<nav aria-label="Page navigation">
<ul id="tableEditZoneTopPagination" class="pagination" style="margin: 0;">
<li><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
<li><a href="#">1</a></li>
<li><a href="#" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
</ul>
</nav>
</div>
<div class="clearfix"></div>
</div>
<table id="tableEditZone" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tableEditZoneBody', 0); return false;">#</a></th>
<th><a href="#" onclick="sortTable('tableEditZoneBody', 1); return false;">Name</a></th>
<th><a href="#" onclick="sortTable('tableEditZoneBody', 2); return false;">Type</a></th>
<th><a href="#" onclick="sortTable('tableEditZoneBody', 3); return false;">TTL</a></th>
<th><a href="#" onclick="sortTable('tableEditZoneBody', 4); return false;">Data</a></th>
<th></th>
</tr>
</thead>
<tbody id="tableEditZoneBody">
</tbody>
<tfoot>
<tr>
<td colspan="6">
<div>
<div class="pull-left" style="padding-top: 8px;">
<b id="tableEditZoneFooterStatus">0 records</b>
</div>
<div class="pull-right">
<nav aria-label="Page navigation">
<ul id="tableEditZoneFooterPagination" class="pagination" style="margin: 0;">
<li><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
<li><a href="#">1</a></li>
<li><a href="#" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
</ul>
</nav>
</div>
<div class="clearfix"></div>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<div id="mainPanelTabPaneCachedZones" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<div class="well well-sm zone-list-pane">
<form class="form-inline">
<div class="form-group" style="width: 100%">
<input type="text" class="form-control" style="width: inherit;" id="txtCacheZone" placeholder="example.com">
</div>
<div class="form-group">
<button id="btnBrowseCacheZone" type="submit" class="btn btn-primary" data-loading-text="Browse" onclick="refreshCachedZonesList($('#txtCacheZone').val()); return false;">Browse</button>
</div>
</form>
<div id="lstCachedZones" class="zones">
</div>
</div>
<div id="divCachedZoneViewer" class="zone-viewer-pane">
<div class="panel panel-default">
<div class="panel-heading" style="height: 36px; padding: 4px 6px;">
<div id="txtCachedZoneViewerTitle" class="pull-left" style="padding: 4px;">technitium.com</div>
<div class="form-inline pull-right">
<button id="btnDeleteCachedZone" type="button" class="btn btn-warning" data-loading-text="Delete" onclick="deleteCachedZone();" style="font-size: 12px; padding: 4px 6px; width: 50px;">Delete</button>
<button type="button" class="btn btn-danger" data-loading-text="Delete" onclick="flushDnsCache(this, $('#optCachedZonesClusterNode').val());" style="font-size: 12px; padding: 4px 6px; width: 50px;">Flush</button>
<select id="optCachedZonesClusterNode" class="form-control cluster-node-dropdown" style="margin-left: 2px;" onchange="refreshCachedZonesList();"></select>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<pre id="preCachedZoneViewerBody">
</pre>
</div>
</div>
</div>
</div>
<div id="mainPanelTabPaneAllowedZones" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<div class="well well-sm zone-list-pane">
<form class="form-inline">
<div class="form-group" style="width: 100%">
<input type="text" class="form-control" style="width: inherit;" id="txtAllowZone" placeholder="example.com">
</div>
<div class="form-group">
<button id="btnAllowZone" type="submit" class="btn btn-primary" data-loading-text="Allow" onclick="allowZone(); return false;">Allow</button>
<button id="btnBrowseAllowZone" type="button" class="btn btn-default" data-loading-text="Browse" onclick="refreshAllowedZonesList($('#txtAllowZone').val());">Browse</button>
</div>
</form>
<div id="lstAllowedZones" class="zones">
</div>
</div>
<div id="divAllowedZoneViewer" class="zone-viewer-pane">
<div class="panel panel-default">
<div class="panel-heading" style="height: 36px; padding: 4px 6px;">
<div id="txtAllowedZoneViewerTitle" class="pull-left" style="padding: 4px;">technitium.com</div>
<div class="form-inline pull-right">
<button type="button" class="btn btn-default" data-loading-text="Import" onclick="resetImportAllowedZonesModal();" data-toggle="modal" data-target="#modalImportAllowedZones" style="font-size: 12px; padding: 4px 6px; width: 50px;">Import</button>
<button type="button" class="btn btn-default" data-loading-text="Export" onclick="exportAllowedZones(this);" style="font-size: 12px; padding: 4px 6px; width: 50px;">Export</button>
<button id="btnDeleteAllowedZone" type="button" class="btn btn-warning" data-loading-text="Delete" onclick="deleteAllowedZone();" style="font-size: 12px; padding: 4px 6px; width: 50px;">Delete</button>
<button id="btnFlushAllowedZone" type="button" class="btn btn-danger" data-loading-text="Flush" onclick="flushAllowedZone();" style="font-size: 12px; padding: 4px 6px; width: 50px;">Flush</button>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<pre id="preAllowedZoneViewerBody">
</pre>
</div>
</div>
</div>
</div>
<div id="mainPanelTabPaneBlockedZones" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<div class="well well-sm zone-list-pane">
<form class="form-inline">
<div class="form-group" style="width: 100%">
<input type="text" class="form-control" style="width: inherit;" id="txtBlockZone" placeholder="example.com">
</div>
<div class="form-group">
<button id="btnBlockZone" type="submit" class="btn btn-primary" data-loading-text="Block" onclick="blockZone(); return false;">Block</button>
<button id="btnBrowseBlockZone" type="button" class="btn btn-default" data-loading-text="Browse" onclick="refreshBlockedZonesList($('#txtBlockZone').val());">Browse</button>
</div>
</form>
<div id="lstBlockedZones" class="zones">
</div>
</div>
<div id="divBlockedZoneViewer" class="zone-viewer-pane">
<div class="panel panel-default">
<div class="panel-heading" style="height: 36px; padding: 4px 6px;">
<div id="txtBlockedZoneViewerTitle" class="pull-left" style="padding: 4px;">technitium.com</div>
<div class="form-inline pull-right">
<button id="btnImportBlockedZone" type="button" class="btn btn-default" data-loading-text="Import" onclick="resetImportBlockedZonesModal();" data-toggle="modal" data-target="#modalImportBlockedZones" style="font-size: 12px; padding: 4px 6px; width: 50px;">Import</button>
<button id="btnExportBlockedZone" type="button" class="btn btn-default" data-loading-text="Export" onclick="exportBlockedZones(this);" style="font-size: 12px; padding: 4px 6px; width: 50px;">Export</button>
<button id="btnDeleteBlockedZone" type="button" class="btn btn-warning" data-loading-text="Delete" onclick="deleteBlockedZone();" style="font-size: 12px; padding: 4px 6px; width: 50px;">Delete</button>
<button id="btnFlushBlockedZone" type="button" class="btn btn-danger" data-loading-text="Flush" onclick="flushBlockedZone();" style="font-size: 12px; padding: 4px 6px; width: 50px;">Flush</button>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<pre id="preBlockedZoneViewerBody">
</pre>
</div>
</div>
</div>
</div>
<div id="mainPanelTabPaneApps" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<div id="divViewAppsLoader" style=" display: none; margin-top: 10px; height: 400px;"></div>
<div id="divViewApps">
<div class="form-inline">
<div style="float: right;">
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showStoreAppsModal();">App Store</button>
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showInstallAppModal();">Install</button>
</div>
<div style="clear: both;"></div>
</div>
<table id="tableApps" class="table table-hover">
<thead>
<tr>
<th style="min-width: 100px;"><a href="#" onclick="sortTable('tableAppsBody', 0); return false;">Installed Apps</a></th>
<th style="width: 96px;"></th>
</tr>
</thead>
<tbody id="tableAppsBody">
</tbody>
<tfoot id="tableAppsFooter">
<tr><td colspan="3"><b>Total Apps: 0</b></td></tr>
</tfoot>
</table>
</div>
</div>
<div id="mainPanelTabPaneDnsClient" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<form class="form-inline well" style="padding-bottom: 6px; margin-bottom: 15px;">
<div>
<div class="form-group">
<label for="txtDnsClientNameServer">Server</label>
<div class="input-group dropdown">
<input type="text" class="form-control dropdown-toggle" style="min-width: 270px; border-right: 0px;" id="txtDnsClientNameServer" value="This Server {this-server}">
<ul id="optDnsClientNameServers" class="dropdown-menu" style="max-height: 500px; overflow-y: scroll;">
</ul>
<span role="button" class="input-group-addon dropdown-toggle" style="background-color: white;" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span></span>
</div>
</div>
<div class="form-group">
<label for="txtDnsClientDomain">Domain</label>
<input type="text" class="form-control" style="min-width: 295px;" id="txtDnsClientDomain" placeholder="example.com">
</div>
<div class="form-group">
<label for="optDnsClientType">Type</label>
<select class="form-control" id="optDnsClientType" style="padding-left: 6px; padding-right: 0px;">
<option>A</option>
<option>NS</option>
<option>CNAME</option>
<option>SOA</option>
<option>PTR</option>
<option>MX</option>
<option>TXT</option>
<option>RP</option>
<option>AAAA</option>
<option>SRV</option>
<option>NAPTR</option>
<option>DNAME</option>
<option>DS</option>
<option>SSHFP</option>
<option>RRSIG</option>
<option>NSEC</option>
<option>DNSKEY</option>
<option>NSEC3</option>
<option>NSEC3PARAM</option>
<option>TLSA</option>
<option>ZONEMD</option>
<option>SVCB</option>
<option>HTTPS</option>
<option>URI</option>
<option>CAA</option>
<option>ANY</option>
<option>AXFR</option>
<option>ANAME</option>
</select>
</div>
<div class="form-group">
<label for="optDnsClientProtocol">DNS-over-</label>
<select class="form-control" id="optDnsClientProtocol" style="padding-left: 6px; padding-right: 0px;">
<option>UDP</option>
<option>TCP</option>
<option>TLS</option>
<option>HTTPS</option>
<option>QUIC</option>
</select>
</div>
<div class="form-group">
<label for="txtDnsClientEDnsClientSubnet">EDNS Client Subnet</label>
<input type="text" class="form-control" style="min-width: 240px;" id="txtDnsClientEDnsClientSubnet">
</div>
<div class="form-group">
<div class="checkbox">
<label>
<input type="checkbox" id="chkDnsClientDnssecValidation"> Enable DNSSEC Validation
</label>
</div>
</div>
</div>
<div>
<div class="form-group">
<button type="submit" class="btn btn-primary" id="btnDnsClientResolve" style="padding: 2px 0px; width: 100px;" data-loading-text="Resolving..." onclick="resolveQuery(); return false;">Resolve</button>
<button type="button" class="btn btn-warning" id="btnDnsClientImport" style="padding: 2px 0px; width: 100px;" data-loading-text="Importing..." onclick="resolveQuery(true);">Import</button>
<select id="optDnsClientClusterNode" class="form-control cluster-node-dropdown"></select>
</div>
</div>
</form>
<div id="divDnsClientLoader" style="margin-top: 15px; height: 300px;"></div>
<div id="divDnsClientOutputAccordion" style="margin-bottom: 0px; display: none;" class="panel-group" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="divDnsClientFinalResponseHeading">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#divDnsClientOutputAccordion" href="#divDnsClientFinalResponseCollapse" aria-expanded="true" aria-controls="divDnsClientFinalResponseCollapse">
Response
</a>
</h4>
</div>
<div id="divDnsClientFinalResponseCollapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="divDnsClientFinalResponseHeading">
<div class="panel-body">
<pre id="preDnsClientFinalResponse" style="margin-bottom: 0px;"></pre>
</div>
</div>
</div>
<div id="divDnsClientRawResponsePanel" class="panel panel-default">
<div class="panel-heading" role="tab" id="divDnsClientRawResponsesHeading">
<h4 class="panel-title">
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#divDnsClientOutputAccordion" href="#divDnsClientRawResponsesCollapse" aria-expanded="false" aria-controls="divDnsClientRawResponsesCollapse">
Raw Responses (<span id="spanDnsClientRawResponsesCount"></span>)
</a>
</h4>
</div>
<div id="divDnsClientRawResponsesCollapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="divDnsClientRawResponsesHeading">
<ul id="ulDnsClientRawResponsesList" class="list-group">
</ul>
</div>
</div>
</div>
</div>
<div id="mainPanelTabPaneSettings" role="tabpanel" class="tab-pane">
<div id="divDnsSettingsLoader" style="margin-top: 10px; height: 400px;"></div>
<div id="divDnsSettings" style="display: none;">
<form style="margin-top: 10px;" onsubmit="return false;">
<ul class="nav nav-tabs" role="tablist">
<li id="settingsTabListGeneral" role="presentation" class="active"><a href="#settingsTabPaneGeneral" aria-controls="settingsTabPaneGeneral" role="tab" data-toggle="tab">General</a></li>
<li id="settingsTabListWebService" role="presentation"><a href="#settingsTabPaneWebService" aria-controls="settingsTabPaneWebService" role="tab" data-toggle="tab">Web Service</a></li>
<li id="settingsTabListOptionalProtocols" role="presentation"><a href="#settingsTabPaneOptionalProtocols" aria-controls="settingsTabPaneOptionalProtocols" role="tab" data-toggle="tab">Optional Protocols</a></li>
<li id="settingsTabListTsig" role="presentation"><a href="#settingsTabPaneTsig" aria-controls="settingsTabPaneTsig" role="tab" data-toggle="tab">TSIG</a></li>
<li id="settingsTabListRecursion" role="presentation"><a href="#settingsTabPaneRecursion" aria-controls="settingsTabPaneRecursion" role="tab" data-toggle="tab">Recursion</a></li>
<li id="settingsTabListCache" role="presentation"><a href="#settingsTabPaneCache" aria-controls="settingsTabPaneCache" role="tab" data-toggle="tab">Cache</a></li>
<li id="settingsTabListBlocking" role="presentation"><a href="#settingsTabPaneBlocking" aria-controls="settingsTabPaneBlocking" role="tab" data-toggle="tab">Blocking</a></li>
<li id="settingsTabListProxyForwarders" role="presentation"><a href="#settingsTabPaneProxyForwarders" aria-controls="settingsTabPaneProxyForwarders" role="tab" data-toggle="tab">Proxy &amp; Forwarders</a></li>
<li id="settingsTabListLogging" role="presentation"><a href="#settingsTabPaneLogging" aria-controls="settingsTabPaneLogging" role="tab" data-toggle="tab">Logging</a></li>
<li class="pull-right">
<select id="optSettingsClusterNode" class="form-control pull-right cluster-node-dropdown" style="margin-left: 0px;" onchange="refreshDnsSettings();"></select>
</li>
</ul>
<div class="tab-content" style="min-height: 350px; padding-top: 15px;">
<div id="settingsTabPaneGeneral" role="tabpanel" class="tab-pane active">
<div id="divSettingsGeneralLocalParameters" class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDnsServerDomain" class="col-sm-3 control-label">DNS Server Domain</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDnsServerDomain" placeholder="domain name" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The primary fully qualified domain name used by this DNS Server to identify itself.</div>
</div>
<div class="form-group">
<label for="txtDnsServerLocalEndPoints" class="col-sm-3 control-label">DNS Server Local End Points</label>
<div class="col-sm-6">
<textarea id="txtDnsServerLocalEndPoints" class="form-control" rows="3" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Local End Points are the network interface IP addresses and ports you want the DNS Server to listen for requests.</div>
</div>
<div class="form-group">
<label for="txtDnsServerIPv4SourceAddresses" class="col-sm-3 control-label">DNS Server IPv4 Source Addresses</label>
<div class="col-sm-6">
<textarea id="txtDnsServerIPv4SourceAddresses" class="form-control" rows="3" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The IPv4 source addresses that the DNS server must use for making all outbound DNS requests when the server is connected to two or more networks. Network addresses are also accepted.</div>
</div>
<div class="form-group">
<label for="txtDnsServerIPv6SourceAddresses" class="col-sm-3 control-label">DNS Server IPv6 Source Addresses</label>
<div class="col-sm-6">
<textarea id="txtDnsServerIPv6SourceAddresses" class="form-control" rows="3" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The IPv6 source addresses that the DNS server must use for making all outbound DNS requests when the server is connected to two or more networks. Network addresses are also accepted. Note that this option will be used only when <code>Prefer IPv6</code> option is enabled.</div>
</div>
<div>
<p>Note! The DNS Server local end point changes will be automatically applied and so you do not need to manually restart the main service.</p>
<p>Note! The source adddresses configured above must be the IP addresses that are configured on the local system's network interface. When using source addresses option, its also necessary to ensure that the system has a default route or a specific route for the source address to be able to reach the destination network. When source addresses are not configured, the IP address of the interface with a default route will be used as the source address.</p>
</div>
</div>
<div id="divSettingsGeneralDefaultParameters" class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDefaultRecordTtl" class="col-sm-3 control-label">Default Record TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDefaultRecordTtl" placeholder="TTL" style="width: 100px; display: inline;">
<span>seconds (default 3600/1h)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The default TTL value to use if not specified when adding or updating records in a Zone.</div>
</div>
<div class="form-group">
<label for="txtDefaultNsRecordTtl" class="col-sm-3 control-label">Default NS Record TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDefaultNsRecordTtl" placeholder="TTL" style="width: 100px; display: inline;">
<span>seconds (default 14400/4h)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The default TTL value to use if not specified when adding or updating NS records in a Primary Zone.</div>
</div>
<div class="form-group">
<label for="txtDefaultSoaRecordTtl" class="col-sm-3 control-label">Default SOA Record TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDefaultSoaRecordTtl" placeholder="TTL" style="width: 100px; display: inline;">
<span>seconds (default 900/15m)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The default TTL value to use if not specified when adding or updating SOA records in a Primary Zone.</div>
</div>
<div class="form-group">
<label for="txtDefaultResponsiblePerson" class="col-sm-3 control-label">Default Responsible Person</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDefaultResponsiblePerson" placeholder="email address" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The default SOA Responsible Person email address to use when adding a Primary Zone.</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Zone Defaults</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkUseSoaSerialDateScheme" type="checkbox"> Use SOA Serial Date Scheme
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">The default SOA Serial option to use if not specified when adding a Primary Zone.</div>
</div>
</div>
<div class="form-group">
<label for="txtMinSoaRefresh" class="col-sm-3 control-label">Minimum SOA Refresh</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtMinSoaRefresh" placeholder="TTL" style="width: 100px; display: inline;">
<span>seconds (default 300/5m)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The minimum Refresh interval to be used by Secondary, Stub, Secondary Forwarder, and Secondary Catalog zones. This minimum value will be used if a zone's SOA Refresh value is less than it.</div>
</div>
<div class="form-group">
<label for="txtMinSoaRetry" class="col-sm-3 control-label">Minimum SOA Retry</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtMinSoaRetry" placeholder="TTL" style="width: 100px; display: inline;">
<span>seconds (default 300/5m)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The minimum Retry interval to be used by Secondary, Stub, Secondary Forwarder, and Secondary Catalog zones zones. This minimum value will be used if a zone's SOA Retry value is less than it.</div>
</div>
<div class="form-group">
<label for="txtZoneTransferAllowedNetworks" class="col-sm-3 control-label">Zone Transfer Allowed Networks</label>
<div class="col-sm-6">
<textarea id="txtZoneTransferAllowedNetworks" class="form-control" rows="3" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter IP addresses or network addresses one below another that are allowed to perform zone transfer for all zones without any TSIG authentication.</div>
</div>
</div>
<div class="form-group">
<label for="txtNotifyAllowedNetworks" class="col-sm-3 control-label">Notify Allowed Networks</label>
<div class="col-sm-6">
<textarea id="txtNotifyAllowedNetworks" class="form-control" rows="3" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter IP addresses or network addresses one below another that are allowed to Notify all Secondary Zones.</div>
</div>
</div>
</div>
<div id="divSettingsGeneralDnsApps" class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDefaultRecordTtl" class="col-sm-3 control-label">DNS Apps</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkDnsAppsEnableAutomaticUpdate" type="checkbox"> Enable Automatic Update
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">DNS server will check for DNS Apps update every day and will automatically download and install the updates.</div>
</div>
</div>
</div>
<div id="divSettingsGeneralIpv6" class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">IPv6 Support</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdIPv6Mode" id="rdIPv6ModeDisabled" value="Disabled">
Disable IPv6
</label>
<div style="padding-top: 5px; padding-left: 20px;">Disables IPv6 support such that the DNS server uses only IPv4 for all outbound DNS and HTTP(s) requests.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdIPv6Mode" id="rdIPv6ModeEnabled" value="Enabled">
Enable IPv6
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enables IPv6 support such that the DNS server uses both IPv6 (whenever possible) and IPv4 with equal weightage for all outbound DNS and HTTP(s) requests.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdIPv6Mode" id="rdIPv6ModePreferred" value="Preferred">
Prefer IPv6
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enables IPv6 support such that the DNS server prefers using IPv6 (whenever possible) for all outbound DNS and HTTP(s) requests and will use IPv4 only after exhausting all IPv6 attempts.</div>
</div>
</div>
</div>
<div>Warning! Enable IPv6 support only if this DNS server has native IPv6 Internet access otherwise it will affect performance. There are many name servers on the Internet that do not respond over IPv6 and thus using Prefer IPv6 option when you are running DNS server in recursive resolver mode (i.e. without any forwarders) may cause frequent operational issues with resolution that may result increase in Server Failure responses.</div>
</div>
<div id="divSettingsGeneralUdpSocketPool" class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">UDP Socket Pool</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkEnableUdpSocketPool" type="checkbox"> Enable UDP Socket Pool
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">The DNS Server will use UDP socket pool for all outbound DNS-over-UDP requests when enabled.</div>
</div>
</div>
<div class="form-group">
<label for="txtUdpSocketPoolExcludedPorts" class="col-sm-3 control-label">UDP Socket Pool Excluded Ports</label>
<div class="col-sm-6">
<textarea id="txtUdpSocketPoolExcludedPorts" class="form-control" rows="5" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter port numbers one below other to be excluded from being used by the UDP socket pool.</div>
</div>
</div>
<div>Note! Enabling UDP socket pool provides port randomization for all outbound DNS-over-UDP requests to mitigate spoofing attacks. It is recommended to enable UDP socket pool on Windows platform. On Linux, ports are fairly random and thus socket pool may be enabled if more randomization is desired. The DNS server can detect DNS spoofing attack attempts based on ID mismatch and switch to TCP protocol automatically.</div>
</div>
<div id="divSettingsGeneralEDns" class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtEdnsUdpPayloadSize" class="col-sm-3 control-label">EDNS UDP Payload Size</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtEdnsUdpPayloadSize" placeholder="size" style="width: 100px; display: inline;">
<span>bytes (valid range 512-4096; default 1232)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum UDP payload size that can be used to avoid IP fragmentation.</div>
</div>
</div>
<div id="divSettingsGeneralDnssec" class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">DNSSEC</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkDnssecValidation" type="checkbox" checked> Enable DNSSEC Validation
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">The DNS Server will validate all responses from name servers or forwarders when this option is enabled.</div>
</div>
</div>
<div>
<p>Warning! Devices that do not have a real-time clock and rely on NTP when booting (e.g. Raspberry Pi), enabling DNSSEC validation will cause failure to resolve the NTP server domain name thus causing the DNS server to fail to validate all other domain names too due to invalid system date/time. To fix this issue, just create a Conditional Forwarder zone for the NTP server domain name (e.g. ntp.org) with forwarder set to <code>this-server</code> and Enable DNSSEC Validation option unchecked. This conditional forwarder zone will disable DNSSEC validation for the NTP server domain name and allow the device to update its system data/time on boot.</p>
<p>Warning! When forwarders are configured, DNSSEC validation will work only if the forwarders are security aware i.e. can respond to DNSSEC requests correctly.</p>
<p>Note! Enabling DNSSEC may increase delays in resolving domain names when the cache is initially empty. As the cache fills up, the performance will be normal as expected.</p>
</div>
</div>
<div id="divSettingsGeneralEDnsClientSubnet" class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">EDNS Client Subnet (ECS)</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkEDnsClientSubnet" type="checkbox"> Enable EDNS Client Subnet
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">The DNS Server will use the public IP address of the request with a prefix length, or the existing Client Subnet option from the request.</div>
</div>
</div>
<div class="form-group">
<label for="txtEDnsClientSubnetIPv4PrefixLength" class="col-sm-3 control-label">ECS IPv4 Prefix Length</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtEDnsClientSubnetIPv4PrefixLength" placeholder="prefix" style="width: 100px; display: inline;">
<span>(valid range 0-32; default 24)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The IPv4 prefix length to define the client subnet.</div>
</div>
<div class="form-group">
<label for="txtEDnsClientSubnetIPv6PrefixLength" class="col-sm-3 control-label">ECS IPv6 Prefix Length</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtEDnsClientSubnetIPv6PrefixLength" placeholder="prefix" style="width: 100px; display: inline;">
<span>(valid range 0-64; default 56)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The IPv6 prefix length to define the client subnet.</div>
</div>
<div class="form-group">
<label for="txtEDnsClientSubnetIpv4Override" class="col-sm-3 control-label">ECS IPv4 Override</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtEDnsClientSubnetIpv4Override" placeholder="network address">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The IPv4 network address that must be used as ECS for all outbound requests overriding client's actual subnet.</div>
</div>
<div class="form-group">
<label for="txtEDnsClientSubnetIpv6Override" class="col-sm-3 control-label">ECS IPv6 Override</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtEDnsClientSubnetIpv6Override" placeholder="network address">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The IPv6 network address that must be used as ECS for all outbound requests overriding client's actual subnet.</div>
</div>
<div>
<p>Warning! EDNS Client Subnet (ECS) option when enabled will compromises user's privacy since the DNS server will send the user's public IP network subnet to name servers or forwarders when resolving requests. When not using encrypted DNS protocols, this information can also be read passively by anyone on the network.</p>
<p>Note! EDNS Client Subnet (ECS) option allows passing the user's client subnet information to name servers or forwarders so that the response may contain IP addresses of servers closer to the user's geographic region. EDNS Client Subnet (ECS) option thus is only useful when the DNS server is hosted in a geographically different region compared to the users that are configured to use it.</p>
<p>Note! Enabling EDNS Client Subnet (ECS) option will significantly increase the DNS server's memory usage since the server will have to cache data for each client subnet separately. It will also increase cache misses since DNS server will have to resolve requests and cache them for each client subnet separately.</p>
</div>
</div>
<div id="divSettingsGeneralRateLimiting" class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Queries Per Minute (QPM) Limits (IPv4)</label>
<div class="col-sm-6">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th style="width: 100px;">IPv4 Prefix</th>
<th>UDP Limit</th>
<th>TCP Limit</th>
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addQpmPrefixLimitsIPv4Row('', '', '');">Add</button></th>
</tr>
</thead>
<tbody id="tableQpmPrefixLimitsIPv4"></tbody>
</table>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum queries an IPv4 client subnet can make to DNS-over-UDP and DNS-over-TCP protocol services per minute on average based on the sample size. Set limit value to <code>0</code> to allow unlimited queries.</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Queries Per Minute (QPM) Limits (IPv6)</label>
<div class="col-sm-6">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th style="width: 100px;">IPv6 Prefix</th>
<th>UDP Limit</th>
<th>TCP Limit</th>
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addQpmPrefixLimitsIPv6Row('', '', '');">Add</button></th>
</tr>
</thead>
<tbody id="tableQpmPrefixLimitsIPv6"></tbody>
</table>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum queries an IPv6 client subnet can make to DNS-over-UDP and DNS-over-TCP protocol services per minute on average based on the sample size. Set limit value to <code>0</code> to allow unlimited queries.</div>
</div>
<div class="form-group">
<label for="txtQpmLimitSampleMinutes" class="col-sm-3 control-label">QPM Sample Size</label>
<div class="col-sm-8">
<input type="number" class="form-control" id="txtQpmLimitSampleMinutes" placeholder="sample" style="width: 100px; display: inline;">
<span>minutes (valid range 1-60; default 5)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The sample size in minutes to sample latest data from Last Hour stats for limiting queries per client.</div>
</div>
<div class="form-group">
<label for="txtQpmLimitUdpTruncation" class="col-sm-3 control-label">QPM Limit UDP Truncation</label>
<div class="col-sm-8">
<input type="number" class="form-control" id="txtQpmLimitUdpTruncation" placeholder="%" style="width: 100px; display: inline;">
<span>% (valid range 0-100; default 50)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The percentage of requests that are responded with a truncation (TC) response when QPM limit exceeds for DNS-over-UDP protocol service while the rest of the requests are dropped. A TC response will cause a real client to retry to DNS-over-TCP protocol service.</div>
</div>
<div class="form-group">
<label for="txtQpmLimitBypassList" class="col-sm-3 control-label">QPM Limit Bypass List</label>
<div class="col-sm-6">
<textarea id="txtQpmLimitBypassList" class="form-control" rows="5" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter IP addresses or network addresses one below another that are allowed to bypass the QPM limit.</div>
</div>
</div>
<div>
<p>Note! Queries Per Minute (QPM) feature will limit requests from a client subnet based on its IP address and the specified subnet prefix lengths except for loopback IP addresses. The QPM limit configured will be compared with the average count from the sample size which means a client may exceed the QPM limit for a given minute but won't exceed for the given sample size in minutes. Rate limited clients will be listed in orange color on the dashboard top clients table.</p>
<p>Note! The configured TCP limits apply to the DNS-over-TCP protocol service as well as to the DNS-over-TLS, DNS-over-HTTPS and DNS-over-QUIC optional protocol services.</p>
</div>
</div>
<div id="divSettingsGeneralAdvancedOptions" class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtClientTimeout" class="col-sm-3 control-label">Client Timeout</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtClientTimeout" placeholder="timeout" style="width: 100px; display: inline;">
<span>milliseconds (valid range 1000-10000; default 2000)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The amount of time the DNS server must wait before responding with a <code>ServerFailure</code> response to a client request when no answer is available.</div>
</div>
<div class="form-group">
<label for="txtTcpSendTimeout" class="col-sm-3 control-label">TCP Send Timeout</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtTcpSendTimeout" placeholder="timeout" style="width: 100px; display: inline;">
<span>milliseconds (valid range 1000-90000; default 10000)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum amount of time the DNS Server will wait for the response to be sent. This option will apply for DNS requests being received by the DNS Server over TCP, TLS, TcpProxy, or HTTPS transports.</div>
</div>
<div class="form-group">
<label for="txtTcpReceiveTimeout" class="col-sm-3 control-label">TCP Receive Timeout</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtTcpReceiveTimeout" placeholder="timeout" style="width: 100px; display: inline;">
<span>milliseconds (valid range 1000-90000; default 10000)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum amount of time the DNS Server will wait for receiving data. This option will apply for DNS requests being received by the DNS Server over TCP, TLS, TcpProxy, or HTTPS transports.</div>
</div>
<div class="form-group">
<label for="txtQuicIdleTimeout" class="col-sm-3 control-label">QUIC Idle Timeout</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtQuicIdleTimeout" placeholder="timeout" style="width: 100px; display: inline;">
<span>milliseconds (valid range 1000-90000; default 60000)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The time interval after which an idle QUIC connection will be closed. This option applies only to QUIC transport protocol.</div>
</div>
<div class="form-group">
<label for="txtQuicMaxInboundStreams" class="col-sm-3 control-label">QUIC Max Inbound Streams</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtQuicMaxInboundStreams" placeholder="100" style="width: 100px; display: inline;">
<span>(valid range 1-1000; default 100)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The max number of inbound bidirectional streams that can be accepted per QUIC connection. This option applies only to QUIC transport protocol.</div>
</div>
<div class="form-group">
<label for="txtListenBacklog" class="col-sm-3 control-label">Listen Backlog</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtListenBacklog" placeholder="100" style="width: 100px; display: inline;">
<span>(default 100)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum number of pending inbound connections. This option applies to TCP, TLS, TcpProxy, and QUIC transport protocols.</div>
</div>
<div class="form-group">
<label for="txtMaxConcurrentResolutionsPerCore" class="col-sm-3 control-label">Max Concurrent Resolutions</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtMaxConcurrentResolutionsPerCore" placeholder="100" style="width: 100px; display: inline;">
<span>per CPU core (default 100)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum number of concurrent async outbound resolutions that should be done per CPU core.</div>
</div>
</div>
</div>
<div id="settingsTabPaneWebService" role="tabpanel" class="tab-pane">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtWebServiceLocalAddresses" class="col-sm-3 control-label">Web Service Local Addresses</label>
<div class="col-sm-6">
<textarea id="txtWebServiceLocalAddresses" class="form-control" rows="3" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Local addresses are the network interface IP addresses you want the web service to listen for requests. ANY addresses (0.0.0.0 &amp; [::]) cannot be used together with unicast IP addresses. The web server uses dual-mode sockets by default so the IPv6 ANY address ([::]) works for IPv4 too. The default values work for most scenarios so, do not change these defaults unless you have a requirement for the web service to listen on specific networks. Configured unicast IP addresses will be included as Subject Alternative Name (SAN) in the self signed TLS certificate.</div>
</div>
<div class="form-group">
<label for="txtWebServiceHttpPort" class="col-sm-3 control-label">Web Service HTTP Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtWebServiceHttpPort" placeholder="port" style="width: 100px; display: inline;">
<span>(default 5380)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify the TCP port number for this web console over HTTP protocol.</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">HTTPS Options</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkWebServiceEnableTls" type="checkbox"> Enable HTTPS
</label>
</div>
<div class="checkbox">
<label>
<input id="chkWebServiceEnableHttp3" type="checkbox"> Enable HTTP/3
</label>
</div>
<div class="checkbox">
<label>
<input id="chkWebServiceHttpToTlsRedirect" type="checkbox"> Enable HTTP to HTTPS Redirection
</label>
</div>
<div class="checkbox">
<label>
<input id="chkWebServiceUseSelfSignedTlsCertificate" type="checkbox"> Use A Self Signed TLS Certificate When TLS Certificate File Path Is Unspecified
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="txtWebServiceTlsPort" class="col-sm-3 control-label">Web Service HTTPS Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtWebServiceTlsPort" placeholder="port" style="width: 100px; display: inline;">
<span>(default 53443)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify the TCP port number for this web console over TLS protocol.</div>
</div>
<div class="form-group">
<label for="txtWebServiceTlsCertificatePath" class="col-sm-3 control-label">TLS Certificate File Path</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtWebServiceTlsCertificatePath" placeholder="Web Service TLS Certificate File Path On Server" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify a PKCS #12 certificate (.pfx or .p12) file path on the server. The path can be relative to the DNS server's config folder. The certificate must contain private key.</div>
</div>
<div class="form-group">
<label for="txtWebServiceTlsCertificatePassword" class="col-sm-3 control-label">TLS Certificate Password</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="txtWebServiceTlsCertificatePassword" placeholder="Web Service TLS Certificate Password" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Enter the certificate (.pfx) password, if any.</div>
</div>
<div class="form-group">
<label for="txtWebServiceRealIpHeader" class="col-sm-3 control-label">Real IP Header</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtWebServiceRealIpHeader" placeholder="X-Real-IP" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The HTTP header that must be used to read client's actual IP address when the request comes from a reverse proxy with a private IP address.</div>
</div>
<div>
<p>Note! The web service port changes will be automatically applied and so you do not need to manually restart the main service. The TLS certificate too will be automatically reloaded when the certificate file's date modified property on disk changes. This web page will be automatically redirected to the new web console URL after saving settings. The HTTPS protocol will be enabled only when a TLS certificate is configured.</p>
<p>When using a reverse proxy with the Web Service, you need to add <code id="lblWebServiceRealIpHeader">X-Real-IP</code> header to the proxy request with the IP address of the client to allow the Web server to know the real IP address of the client originating the request. For example, if you are using nginx as the reverse proxy, you can add <code id="lblWebServiceRealIpNginx">proxy_set_header X-Real-IP $remote_addr;</code> to make it work.</p>
<p>The web service uses Kestrel web server which supports both HTTP/2 and HTTP/3 protocols when TLS certificate is configured. HTTP/3 protocol support is not available on all platforms. On Windows, it is available only on Windows 11 (build 22000 or later) and Windows Server 2022. On Linux, it requires <code>libmsquic</code> to be installed.</p>
<p>Note! The web service will always bind to <code>[::]</code> local address for HTTP/3 protocol since this is how the <code>libmsquic</code> library is designed to work.</p>
<p>Use the following openssl command to convert your TLS certificate that is in PEM format to PKCS #12 certificate (.pfx) format:</p>
<pre>openssl pkcs12 -export -out "example.com.pfx" -inkey "privkey.pem" -in "cert.pem" -certfile "chain.pem"</pre>
</div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2023/02/configuring-dns-over-quic-and-https3.html" target="_blank">Help: Configuring DNS-over-QUIC and HTTPS/3 For Technitium DNS Server</a></div>
</div>
</div>
<div id="settingsTabPaneOptionalProtocols" role="tabpanel" class="tab-pane">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Optional DNS Server Protocols</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkEnableEDnsClientSubnetSourceAddress" type="checkbox"> Enable EDNS Client Subnet (ECS) Source Address
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to read the client's source IP address from the EDNS Client Subnet (ECS) option in the DNS requests coming via DNS-over-UDP or DNS-over-TCP protocols. This option allows a DNS proxy to pass the client's source IP address via ECS option to the DNS Server. It is mandatory to configure <b>Reverse Proxy Network ACL</b> below to allow requests coming from your DNS proxy server to work with this option.</div>
<div class="checkbox">
<label>
<input id="chkEnableDnsOverUdpProxy" type="checkbox"> Enable DNS-over-UDP-PROXY
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to accept DNS-over-UDP-PROXY requests. It implements the <a href="https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt" target="_blank">PROXY Protocol</a> for both version 1 &amp; 2 over UDP datagram. It is mandatory to configure <b>Reverse Proxy Network ACL</b> below to allow requests coming from your reverse proxy server.</div>
<div class="checkbox">
<label>
<input id="chkEnableDnsOverTcpProxy" type="checkbox"> Enable DNS-over-TCP-PROXY
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to accept DNS-over-TCP-PROXY requests. It implements the <a href="https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt" target="_blank">PROXY Protocol</a> for both version 1 &amp; 2 over TCP connection. It is mandatory to configure <b>Reverse Proxy Network ACL</b> below to allow requests coming from your reverse proxy server.</div>
<div class="checkbox">
<label>
<input id="chkEnableDnsOverHttp" type="checkbox"> Enable DNS-over-HTTP
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to accept DNS-over-HTTP requests. It must be used with a TLS terminating reverse proxy like nginx. It is mandatory to configure <b>Reverse Proxy Network ACL</b> below to allow requests coming from your reverse proxy server. Enabling this option also allows automatic TLS certificate renewal with HTTP challenge (webroot) for DNS-over-HTTPS service when DNS-over-HTTP port is set to 80.</div>
<div class="checkbox">
<label>
<input id="chkEnableDnsOverTls" type="checkbox"> Enable DNS-over-TLS
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to accept DNS-over-TLS requests.</div>
<div class="checkbox">
<label>
<input id="chkEnableDnsOverHttps" type="checkbox"> Enable DNS-over-HTTPS
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to accept DNS-over-HTTPS requests.</div>
<div class="checkbox">
<label>
<input id="chkEnableDnsOverHttp3" type="checkbox"> Enable DNS-over-HTTP/3
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to accept DNS-over-HTTP/3 requests.</div>
<div class="checkbox">
<label>
<input id="chkEnableDnsOverQuic" type="checkbox"> Enable DNS-over-QUIC
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to accept DNS-over-QUIC requests.</div>
</div>
</div>
<div class="form-group">
<label for="txtDnsOverUdpProxyPort" class="col-sm-3 control-label">DNS-over-UDP-PROXY Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtDnsOverUdpProxyPort" placeholder="port" style="width: 100px; display: inline;">
<span>(default 538)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify the UDP port number for DNS-over-UDP-PROXY protocol.</div>
</div>
<div class="form-group">
<label for="txtDnsOverTcpProxyPort" class="col-sm-3 control-label">DNS-over-TCP-PROXY Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtDnsOverTcpProxyPort" placeholder="port" style="width: 100px; display: inline;">
<span>(default 538)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify the TCP port number for DNS-over-TCP-PROXY protocol.</div>
</div>
<div class="form-group">
<label for="txtDnsOverHttpPort" class="col-sm-3 control-label">DNS-over-HTTP Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtDnsOverHttpPort" placeholder="port" style="width: 100px; display: inline;">
<span>(default 80)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify the TCP port number for DNS-over-HTTP protocol.</div>
</div>
<div class="form-group">
<label for="txtDnsOverTlsPort" class="col-sm-3 control-label">DNS-over-TLS Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtDnsOverTlsPort" placeholder="port" style="width: 100px; display: inline;">
<span>(default 853)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify the TCP port number for DNS-over-TLS protocol.</div>
</div>
<div class="form-group">
<label for="txtDnsOverHttpsPort" class="col-sm-3 control-label">DNS-over-HTTPS Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtDnsOverHttpsPort" placeholder="port" style="width: 100px; display: inline;">
<span>(default 443)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify the TCP port number for DNS-over-HTTPS protocol.</div>
</div>
<div class="form-group">
<label for="txtDnsOverQuicPort" class="col-sm-3 control-label">DNS-over-QUIC Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtDnsOverQuicPort" placeholder="port" style="width: 100px; display: inline;">
<span>(default 853)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify the UDP port number for DNS-over-QUIC protocol.</div>
</div>
<div class="form-group">
<label for="txtReverseProxyNetworkACL" class="col-sm-3 control-label">Reverse Proxy Network ACL</label>
<div class="col-sm-6">
<textarea id="txtReverseProxyNetworkACL" class="form-control" rows="5" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Configure the ACL above to allow requests coming from your reverse proxy server for DNS-over-UDP-PROXY, DNS-over-TCP-PROXY, and DNS-over-HTTP protocols. Enter IP addresses or network addresses one below another to allow access. Add <code>!</code> character at the start to deny access, e.g. <code>!192.168.10.0/24</code> will deny entire subnet. The ACL is processed in the same order its listed. If no networks match, the default policy is to deny all.</div>
</div>
<div class="form-group">
<label for="txtDnsTlsCertificatePath" class="col-sm-3 control-label">TLS Certificate File Path</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDnsTlsCertificatePath" placeholder="DNS Service TLS Certificate File Path On Server" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Specify a PKCS #12 certificate (.pfx or .p12) file path on the server. The path can be relative to the DNS server's config folder. The certificate must contain private key.</div>
</div>
<div class="form-group">
<label for="txtDnsTlsCertificatePassword" class="col-sm-3 control-label">TLS Certificate Password</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="txtDnsTlsCertificatePassword" placeholder="DNS Service TLS Certificate Password" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Enter the certificate (.pfx) password, if any.</div>
</div>
<div class="form-group">
<label for="txtDnsOverHttpRealIpHeader" class="col-sm-3 control-label">Real IP Header</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDnsOverHttpRealIpHeader" placeholder="X-Real-IP" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The HTTP header that must be used to read client's actual IP address when the request comes from a reverse proxy. The specified header will be read only when the request IP address is allowed by the <b>Reverse Proxy Network ACL</b>.</div>
</div>
<div>
<p>Note! These optional DNS server protocol changes will be automatically applied and so you do not need to manually restart the main service. The TLS certificate too will be automatically reloaded when the certificate file's date modified property on disk changes. The DNS-over-TLS, DNS-over-QUIC, and DNS-over-HTTPS protocols will be enabled only when a TLS certificate is configured.</p>
<p>These optional DNS server protocols are used to host these as a service. You do not need to enable these optional protocols to use them with Forwarders or Conditional Forwarder Zones.</p>
<p>For DNS-over-HTTP, use <code>http://<span id="lblDoHHost">localhost:8053</span>/dns-query</code> with a TLS terminating reverse proxy like nginx. For DNS-over-TLS, use <code id="lblDoTHost">tls-certificate-domain:853</code>, for DNS-over-QUIC, use <code id="lblDoQHost">tls-certificate-domain:853</code>, and for DNS-over-HTTPS use <code>https://<span id="lblDoHsHost">tls-certificate-domain</span>/dns-query</code> to configure supported DNS clients.</p>
<p>When using a reverse proxy with the DNS-over-HTTP service, you need to add <code id="lblDnsOverHttpRealIpHeader">X-Real-IP</code> header to the proxy request with the IP address of the client to allow the DNS server to know the real IP address of the client originating the request. For example, if you are using nginx as the reverse proxy, you can add <code id="lblDnsOverHttpRealIpNginx">proxy_set_header X-Real-IP $remote_addr;</code> to make it work.</p>
<p>DNS-over-QUIC protocol support is not available on all platforms. On Windows, it is available only on Windows 11 (build 22000 or later) and Windows Server 2022. On Linux, it requires <code>libmsquic</code> to be installed.</p>
<p>Note! The DNS-over-HTTP/3 protocol will always bind to <code>[::]</code> local address since this is how the <code>libmsquic</code> library is designed to work.</p>
<p>Use the following openssl command to convert your TLS certificate that is in PEM format to PKCS #12 certificate (.pfx) format:</p>
<pre>openssl pkcs12 -export -out "example.com.pfx" -inkey "privkey.pem" -in "cert.pem" -certfile "chain.pem"</pre>
</div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2020/07/how-to-host-your-own-dns-over-https-and.html" target="_blank">Help: How To Host Your Own DNS-over-HTTPS, DNS-over-TLS, And DNS-over-QUIC Services</a></div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2023/02/configuring-dns-over-quic-and-https3.html" target="_blank">Help: Configuring DNS-over-QUIC and HTTPS/3 For Technitium DNS Server</a></div>
</div>
</div>
<div id="settingsTabPaneTsig" role="tabpanel" class="tab-pane">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="tableTsigKeys" class="col-sm-2 control-label">TSIG Keys</label>
<div class="col-sm-10">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th>Key Name</th>
<th>Shared Secret</th>
<th>Algorithm</th>
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addTsigKeyRow('', '', 'hmac-sha256');">Add</button></th>
</tr>
</thead>
<tbody id="tableTsigKeys"></tbody>
</table>
</div>
<div class="col-sm-offset-2 col-sm-10" style="padding-top: 5px;">The shared secret can be a base64 string or a literal string. Keep the shared secret empty if you want to auto generate a strong key.</div>
</div>
<div>Note! You will need to configure these TSIG keys names for zone transfer in the zone options and in the secondary zone SOA record options separately.</div>
</div>
</div>
<div id="settingsTabPaneRecursion" role="tabpanel" class="tab-pane">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Recursion</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdRecursion" id="rdRecursionDeny" value="Deny">
Deny Recursion
</label>
<div style="padding-top: 5px; padding-left: 20px;">Disables recursion so that this DNS Server works as authoritative only.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdRecursion" id="rdRecursionAllow" value="Allow">
Allow Recursion
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enables recursion to allow this DNS Server to resolve any domain name.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdRecursion" id="rdRecursionAllowOnlyForPrivateNetworks" value="AllowOnlyForPrivateNetworks" checked>
Allow Recursion Only For Private Networks (default)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Select this option if you want to support recursion only on private networks. Any recursive request from a public network will be refused.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdRecursion" id="rdRecursionUseSpecifiedNetworkACL" value="UseSpecifiedNetworkACL">
Use Specified Network Access Control List (ACL)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Select this option to specify networks that must be allowed or denied recursion.</div>
</div>
</div>
<div class="col-sm-offset-3 col-sm-6">
<label for="txtRecursionNetworkACL" class="control-label">Network Access Control List (ACL)</label>
<textarea id="txtRecursionNetworkACL" class="form-control" rows="5" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter IP addresses or network addresses one below another to allow access. Add <code>!</code> character at the start to deny access, e.g. <code>!192.168.10.0/24</code> will deny entire subnet. The ACL is processed in the same order its listed. If no networks match, the default policy is to deny all except loopback.</div>
</div>
</div>
<div>Note! Disable recursion if you wish this server to act only as authoritative name server for the configured zones.</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Recursive Resolver</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkRandomizeName" type="checkbox"> Randomize Name
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enables <a href="https://datatracker.ietf.org/doc/draft-vixie-dnsext-dns0x20/" target="_blank">QNAME case randomization</a> when using UDP as the transport protocol to improve security.</div>
<div class="checkbox">
<label>
<input id="chkQnameMinimization" type="checkbox"> QNAME Minimization
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enables <a href="https://datatracker.ietf.org/doc/rfc9156/" target="_blank">QNAME minimization</a> for recursive resolution to improve privacy.</div>
</div>
</div>
<div>Warning! Enabling the <b>Randomize Name</b> option may cause some domain names to fail to resolve due to their name servers dropping the requests or sending the QNAME in response with a different case causing mismatch. The DNS server can already detect DNS spoofing attack attempts and switch to TCP protocol automatically so its safe to not use this feature.</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtResolverRetries" class="col-sm-3 control-label">Resolver Retries</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtResolverRetries" placeholder="retries" style="width: 100px; display: inline;">
<span>(valid range 1-10; default 2)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The total number of retries the recursive resolver must do per name server.</div>
</div>
<div class="form-group">
<label for="txtResolverTimeout" class="col-sm-3 control-label">Resolver Timeout</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtResolverTimeout" placeholder="timeout" style="width: 100px; display: inline;">
<span>milliseconds (valid range 1000-10000; default 1500)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The amount of time the recursive resolver must wait between retries.</div>
</div>
<div class="form-group">
<label for="txtResolverConcurrency" class="col-sm-3 control-label">Resolver Concurrency</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtResolverConcurrency" placeholder="count" style="width: 100px; display: inline;">
<span>(valid range 1-4; default 2)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The number of concurrent requests that should be sent by the recursive resolver to the name servers.</div>
</div>
<div class="form-group">
<label for="txtResolverMaxStackCount" class="col-sm-3 control-label">Resolver Max Stack Count</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtResolverMaxStackCount" placeholder="count" style="width: 100px; display: inline;">
<span>(valid range 10-30; default 16)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum stack count the recursive resolver must use for resolving a domain name.</div>
</div>
<div style="margin-top: 10px;">Note! The DNS Server supports EDNS and thus all outbound recursive resolution requests will have an OPT record for it in the additional section. If a name server does not respond to a request containing OPT record, the recursive resolver will retry again without the OPT record when possible. This means that the number of retries attempted per name server can be Resolver Retries value multiplied by two for certain cases.</div>
<div style="margin-top: 10px;">Note! The DNS server uses Epsilon-Greedy machine learning algorithm and will automatically learn which of the name servers are answering faster without errors and will use those name servers most of the time. Since each domain name has a different set of name servers, it may take a while before the algorithm learns about them.</div>
</div>
</div>
<div id="settingsTabPaneCache" role="tabpanel" class="tab-pane">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">DNS Cache</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkSaveCache" type="checkbox"> Save Cache To Disk
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to save DNS cache on disk when the DNS server stops. The saved cache will be loaded next time the DNS server starts.</div>
</div>
</div>
<div>Note! The DNS server will attempt to save cache to disk when it stops which may take time depending on the cache size. If the DNS server takes a lot of time to stop then it may lead to the OS killing the DNS server process causing an incomplete cache to be stored on disk.</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Serve Stale</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkServeStale" type="checkbox"> Enable Serve Stale
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable the <a href="https://datatracker.ietf.org/doc/rfc8767/" target="_blank">Serve Stale</a> feature to improve resiliency by using expired or stale records in cache to respond when the DNS server is unable to reach the upstream or authoritative name servers to refresh the expired records before the Max Wait Time configured below.</div>
</div>
</div>
<div class="form-group">
<label for="txtServeStaleTtl" class="col-sm-3 control-label">Serve Stale TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtServeStaleTtl" placeholder="seconds" style="width: 100px; display: inline;">
<span>seconds (recommended 259200/3d)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The TTL value in seconds which should be used for cached records that are expired. When the serve stale TTL too expires for a stale record, it gets removed from the cache. Recommended value is between 1-3 days and maximum supported value is 7 days.</div>
</div>
<div class="form-group">
<label for="txtServeStaleAnswerTtl" class="col-sm-3 control-label">Serve Stale Answer TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtServeStaleAnswerTtl" placeholder="seconds" style="width: 100px; display: inline;">
<span>seconds (valid range 0-300/5m; recommended 30)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The TTL value in seconds which should be used for the records in a stale response. This is the TTL value that the client will be using to cache the stale records.</div>
</div>
<div class="form-group">
<label for="txtServeStaleResetTtl" class="col-sm-3 control-label">Serve Stale Reset TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtServeStaleResetTtl" placeholder="seconds" style="width: 100px; display: inline;">
<span>seconds (valid range 10-900/15m; recommended 30)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The TTL value in seconds which should be used to reset the stale record's TTL value in the cache when the resolver fails to refresh the data. The TTL reset causes the stale records to become valid again so that they can be used to serve requests normally. This reset effectively prevents the resolver from attempting to frequently update the stale records.</div>
</div>
<div class="form-group">
<label for="txtServeStaleMaxWaitTime" class="col-sm-3 control-label">Serve Stale Max Wait Time</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtServeStaleMaxWaitTime" placeholder="milliseconds" style="width: 100px; display: inline;">
<span>milliseconds (valid range 0-1800; default 1800)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The time in milliseconds that the DNS server must wait for the resolver before serving stale records from the cache. Lower value will ensure faster response at the expense of not getting updated data from the upstream. Setting value to 0 will instantly return stale answer without waiting for the resolver to fetch updates from the upstream.</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtCacheMaximumEntries" class="col-sm-3 control-label">Cache Maximum Entries</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtCacheMaximumEntries" placeholder="entries" style="width: 125px; display: inline;">
<span>(default 10000; set 0 for unlimited entries)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum number of entries that the cache can store. A relevant value should be configured by monitoring the Cache entries value on Dashboard and the server's memory usage to limit the amount of RAM used by the DNS server. A cache entry is a complete Resource Record Set (RR Set) which is a group of records with the same type for a given domain name. When a value is configured, the DNS server will trigger a clean up operation every few minutes and remove least recently used entries to maintain the maximum allowed entries in cache.</div>
</div>
<div class="form-group">
<label for="txtCacheMinimumRecordTtl" class="col-sm-3 control-label">Cache Minimum TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtCacheMinimumRecordTtl" placeholder="min TTL" style="width: 100px; display: inline;">
<span>seconds (recommended 10)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The minimum TTL value that a record can have in the cache. Set a value to make sure that the records with TTL value less than that stays in cache for a minimum duration.</div>
</div>
<div class="form-group">
<label for="txtCacheMaximumRecordTtl" class="col-sm-3 control-label">Cache Maximum TTL</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="txtCacheMaximumRecordTtl" placeholder="max TTL" style="width: 100px; display: inline;">
<span>seconds (default 604800/1w)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum TTL value that a record can have in the cache. Set a lower value to allow the records to expire early.</div>
</div>
<div class="form-group">
<label for="txtCacheNegativeRecordTtl" class="col-sm-3 control-label">Cache Negative TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtCacheNegativeRecordTtl" placeholder="-ve TTL" style="width: 100px; display: inline;">
<span>seconds (recommended 300/5m)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The negative TTL value to use when there is no SOA MINIMUM value available. Negative caching stores records in cache for <code>NXDOMAIN</code> and <code>NODATA</code> responses.</div>
</div>
<div class="form-group">
<label for="txtCacheFailureRecordTtl" class="col-sm-3 control-label">Cache Failure TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtCacheFailureRecordTtl" placeholder="fail TTL" style="width: 100px; display: inline;">
<span>seconds (recommended 10)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The failure TTL value to be used for caching failure responses. This allows storing failure record in cache and prevent frequent recursive resolution requests to the name servers that are responding with <code>ServerFailure</code> or failing to respond.</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtCachePrefetchEligibility" class="col-sm-3 control-label">Prefetch Eligibility</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtCachePrefetchEligibility" placeholder="eligibility" style="width: 100px; display: inline;">
<span>seconds (recommended 2)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The minimum initial TTL value of a record needed to be eligible for prefetching.</div>
</div>
<div class="form-group">
<label for="txtCachePrefetchTrigger" class="col-sm-3 control-label">Prefetch Trigger</label>
<div class="col-sm-8">
<input type="number" class="form-control" id="txtCachePrefetchTrigger" placeholder="trigger" style="width: 100px; display: inline;">
<span>seconds (recommended 9; set 0 to disable prefetching &amp; auto prefetching)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">A record with TTL value less than trigger value will initiate prefetch operation immediately for itself.</div>
</div>
<div class="form-group">
<label for="txtCachePrefetchSampleIntervalInMinutes" class="col-sm-3 control-label">Auto Prefetch Sampling</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtCachePrefetchSampleIntervalInMinutes" placeholder="interval" style="width: 100px; display: inline;">
<span>minutes (valid range 1-60; default 5)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The interval to sample eligible domain names from last hour stats for auto prefetch.</div>
</div>
<div class="form-group">
<label for="txtCachePrefetchSampleEligibilityHitsPerHour" class="col-sm-3 control-label">Auto Prefetch Eligibility</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtCachePrefetchSampleEligibilityHitsPerHour" placeholder="hits" style="width: 100px; display: inline;">
<span>hits/hour (default 30)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Minimum required hits per hour for a domain name to be eligible for auto prefetch.</div>
</div>
<div>The DNS Server cache auto prefetch option can keep eligible domain names from last hour stats "hot" in cache. Auto prefetch eligibility value can be decided by keeping an eye on the hits shown for last hour on the dashboard. Experiment with auto prefetch sampling interval and eligibility to get best results.</div>
</div>
</div>
<div id="settingsTabPaneBlocking" role="tabpanel" class="tab-pane">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Blocking</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkEnableBlocking" type="checkbox"> Enable Blocking
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Sets the DNS server to block domain names using Blocked Zone and Block List Zone.</div>
<div class="checkbox">
<label>
<input id="chkAllowTxtBlockingReport" type="checkbox"> Allow TXT Blocking Report
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Specifies if the DNS Server should respond with TXT records containing a blocked domain report for TXT type requests. This option also enables Extended DNS Error blocked domain report in response for requests that support EDNS.</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Blocking Temporarily Disabled Till</label>
<div class="col-sm-8">
<div id="lblTemporaryDisableBlockingTill" style="padding-top: 7px;"></div>
<div style="padding-top: 12px;">
<input type="number" class="form-control" id="txtTemporaryDisableBlockingMinutes" placeholder="minutes" style="width: 100px; display: inline;">
<span>minutes</span>
</div>
<div style="padding-top: 6px;">
<button id="btnTemporaryDisableBlockingNow" type="button" class="btn btn-default" style="padding: 2px 0; width: 170px;" data-loading-text="Disabling..." onclick="temporaryDisableBlockingNow();">Temporary Disable Now</button>
</div>
</div>
</div>
<div class="form-group">
<label for="txtBlockingBypassList" class="col-sm-3 control-label">Blocking Bypass List</label>
<div class="col-sm-6">
<textarea id="txtBlockingBypassList" class="form-control" rows="3" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter IP addresses or network addresses one below another that are allowed to bypass blocking.</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Blocking Type</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdBlockingType" id="rdBlockingTypeAnyAddress" value="AnyAddress">
ANY Address
</label>
<div style="padding-top: 5px; padding-left: 20px;">Uses <code>0.0.0.0</code> and <code>::</code> IP addresses for blocked domain names.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdBlockingType" id="rdBlockingTypeNxDomain" value="NxDomain">
NX Domain (recommended)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Uses <code>NX Domain</code> response for blocked domain names.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdBlockingType" id="rdBlockingTypeCustomAddress" value="CustomAddress">
Custom Address
</label>
<div style="padding-top: 5px; padding-left: 20px;">Uses custom IP addresses provided below for blocked domain names.</div>
</div>
</div>
<div class="col-sm-offset-3 col-sm-6" style="margin-bottom: 10px;">
<label for="txtCustomBlockingAddresses" class="control-label">Custom Blocking Addresses (IP Address)</label>
<textarea id="txtCustomBlockingAddresses" class="form-control" rows="3" spellcheck="false"></textarea>
</div>
</div>
<div class="form-group">
<label for="txtBlockingAnswerTtl" class="col-sm-3 control-label">Blocking Answer TTL</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtBlockingAnswerTtl" placeholder="ttl" style="width: 100px; display: inline;">
<span>seconds (default 30)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The TTL value in seconds that must be used for the records in a blocking response. This is the TTL value that the client will use to cache the blocking response.</div>
</div>
<div class="form-group">
<label for="txtBlockListUrls" class="col-sm-3 control-label">Allow / Block List URLs</label>
<div class="col-sm-8">
<textarea id="txtBlockListUrls" class="form-control" rows="7" spellcheck="false"></textarea>
<label for="optQuickBlockList" class="control-label">Quick Add</label>
<select id="optQuickBlockList" class="form-control" style="width: 100%;">
</select>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">
<p>Enter block list URL one below another in the above text field or use the Quick Add list to add known block list URLs.</p>
<p>For directly using block list files saved on this server, use the <code>file://</code> formatted URL path. For example, on Linux the URL should look like <code>file:///home/folder/myblocklist.txt</code> and on Windows it should look like <code>file:///c:/folder/myblocklist.txt</code>.</p>
<p>Add <code>!</code> character at the start of an URL to make it an allow list URL. This option must not be used with allow lists that use <code>Adblock Plus</code> format.</p>
<p>Begin a line with <code>#</code> character at the start to use it for comments.</p>
</div>
</div>
<div class="form-group">
<label for="txtBlockListUpdateIntervalHours" class="col-sm-3 control-label">Block List Update Interval</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtBlockListUpdateIntervalHours" placeholder="hours" style="width: 100px; display: inline;">
<span>hours (valid range 0-168; default 24; set 0 to disable)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The interval in hours to automatically download and update the block lists.</div>
</div>
<div class="form-group">
<label for="lblBlockListNextUpdatedOn" class="col-sm-3 control-label">Block List Next Update On</label>
<div class="col-sm-6" style="padding-top: 5px;">
<span id="lblBlockListNextUpdatedOn" style="margin-right: 15px;"></span>
<button id="btnUpdateBlockListsNow" type="button" class="btn btn-default" style="padding: 2px 0; width: 100px;" data-loading-text="Updating..." onclick="forceUpdateBlockLists();">Update Now</button>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Click the 'Update Now' button to reset the next update schedule and force download and update of the block lists.</div>
</div>
<div style="margin-top: 10px;">Note! The DNS Server will use the data returned by the block list URLs to update the block list zone automatically. The expected file format is standard <code>hosts</code> file format, plain text file containing list of domains to block, wildcard block list file format, or <code>Adblock Plus</code> file format.</div>
<div style="margin-top: 10px;">Warning! The DNS Server loads all block lists in memory and thus it is expected that the server is provisioned with sufficient amount of memory to avoid out of memory issues. On average, 1 million domain names in block list take about 300 MB of memory. The block list update process requires additional memory to load the newly downloaded block lists before it replaces the previously loaded block lists in memory.</div>
<div style="margin-top: 10px;">Note! To customize the Quick Add drop down list, read the instructions given in the <code>www/json/readme.txt</code> file found in the installation folder.</div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2018/10/blocking-internet-ads-using-dns-sinkhole.html" target="_blank">Help: Blocking Internet Ads Using DNS Sinkhole</a></div>
</div>
</div>
<div id="settingsTabPaneProxyForwarders" role="tabpanel" class="tab-pane">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Network Proxy</label>
<div class="col-sm-6">
<div class="radio">
<label>
<input type="radio" name="rdProxyType" id="rdProxyTypeNone" value="None" checked>
No Proxy (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdProxyType" id="rdProxyTypeHttp" value="Http">
HTTP Proxy
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdProxyType" id="rdProxyTypeSocks5" value="Socks5">
SOCKS5 Proxy
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="txtProxyAddress" class="col-sm-3 control-label">Proxy Server Address</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtProxyAddress" placeholder="domain name or IP address" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtProxyPort" class="col-sm-3 control-label">Proxy Server Port</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtProxyPort" placeholder="port" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtProxyUsername" class="col-sm-3 control-label">Username</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtProxyUsername" placeholder="username" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtProxyPassword" class="col-sm-3 control-label">Password</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="txtProxyPassword" placeholder="password" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtProxyBypassList" class="col-sm-3 control-label">Proxy Bypass List</label>
<div class="col-sm-6">
<textarea id="txtProxyBypassList" class="form-control" rows="5" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Enter IP addresses, network addresses or domain names to never proxy.</div>
</div>
<div style="margin-top: 10px;">Note! When proxy server is configured, DNS Server will use it for all outbound network requests.</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtForwarders" class="col-sm-3 control-label">Forwarders</label>
<div class="col-sm-6">
<textarea id="txtForwarders" class="form-control" rows="3" spellcheck="false"></textarea>
<label for="optQuickForwarders" class="control-label">Quick Select</label>
<select id="optQuickForwarders" class="form-control" style="width: 100%;">
</select>
<div style="padding-top: 5px;">Enter forwarder DNS Server IP addresses or URLs one below another in above text field or use the Quick Select list to select desired forwarder.</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Forwarder Protocol</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdForwarderProtocol" id="rdForwarderProtocolUdp" value="Udp" checked>
DNS-over-UDP (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdForwarderProtocol" id="rdForwarderProtocolTcp" value="Tcp">
DNS-over-TCP
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdForwarderProtocol" id="rdForwarderProtocolTls" value="Tls">
DNS-over-TLS
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdForwarderProtocol" id="rdForwarderProtocolHttps" value="Https">
DNS-over-HTTPS
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdForwarderProtocol" id="rdForwarderProtocolQuic" value="Quic">
DNS-over-QUIC
</label>
</div>
<div style="padding-top: 5px;">Select a protocol that this DNS server must use to query the forwarders specified above.</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Concurrent Forwarding</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkEnableConcurrentForwarding" type="checkbox"> Enable Concurrent Forwarding
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to allow querying two or more forwarders concurrently instead of sequentially querying them in their given order. The DNS server will automatically select forwarders (based on their average latency) to query and use the fastest response it receives from any of them. If none of the selected forwarders respond in time, the DNS server will similarly select forwarders from the remaining ones and queries them till all are tried before giving up.</div>
</div>
</div>
<div class="form-group">
<label for="txtForwarderConcurrency" class="col-sm-3 control-label">Forwarder Concurrency</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtForwarderConcurrency" placeholder="count" style="width: 100px; display: inline;">
<span>(valid range 1-10; default 2)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The number of concurrent requests that must be sent when Concurrent Forwarding is enabled for resolving a domain name.</div>
</div>
<div style="margin-top: 10px;">Note! Forwarders are upstream DNS servers which this DNS Server must use to resolve domain names. If no forwarders are configured then the DNS server will use preconfigured ROOT HINTS to perform recursive resolution to resolve domain names.</div>
<div style="margin-top: 10px;">Note! The <code>https</code> URL scheme supports only DNS-over-HTTPS/2 and DNS-over-HTTPS/1.1 protocols. For DNS-over-HTTPS/3, use <code>h3</code> URL scheme instead of <code>https</code> but note that there wont be any protocol fallback if the connection attempt fails.</div>
<div style="margin-top: 10px;">Note! The DNS server uses Epsilon-Greedy machine learning algorithm and will automatically learn which of the forwarders are answering faster without errors and will use those forwarders most of the time.</div>
<div style="margin-top: 10px;">Note! To customize the Quick Select drop down list, read the instructions given in the <code>www/json/readme.txt</code> file found in the installation folder.</div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2018/06/configuring-dns-server-for-privacy.html" target="_blank">Help: Configuring DNS Server For Privacy & Security</a></div>
<div style="margin-top: 10px;"><a href="https://blog.technitium.com/2023/02/configuring-dns-over-quic-and-https3.html" target="_blank">Help: Configuring DNS-over-QUIC and HTTPS/3 For Technitium DNS Server</a></div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtForwarderRetries" class="col-sm-3 control-label">Forwarder Retries</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtForwarderRetries" placeholder="retries" style="width: 100px; display: inline;">
<span>(valid range 1-10; default 3)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The total number of retries the forwarder or conditional forwarder resolver must do per upstream DNS server.</div>
</div>
<div class="form-group">
<label for="txtForwarderTimeout" class="col-sm-3 control-label">Forwarder Timeout</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtForwarderTimeout" placeholder="timeout" style="width: 100px; display: inline;">
<span>milliseconds (valid range 1000-10000; default 2000)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The amount of time the forwarder or conditional forwarder resolver must wait between retries.</div>
</div>
</div>
</div>
<div id="settingsTabPaneLogging" role="tabpanel" class="tab-pane">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Enable Logging To</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdLoggingType" id="rdLoggingTypeNone" value="None">
None
</label>
<div style="padding-top: 5px; padding-left: 20px;">Disables all logging including error logs and audit logs.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdLoggingType" id="rdLoggingTypeFile" value="File">
File
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enables logging errors and audit logs to the log file.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdLoggingType" id="rdLoggingTypeConsole" value="Console">
Console
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enables logging errors and audit logs to the console.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdLoggingType" id="rdLoggingTypeFileAndConsole" value="FileAndConsole">
Both File And Console
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enables logging errors and audit logs to both the log file and console.</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Logging Options</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkIgnoreResolverLogs" type="checkbox"> Ignore Resolver Error Logs
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to stop logging domain name resolution errors into the log file.</div>
<div class="checkbox">
<label>
<input id="chkLogQueries" type="checkbox"> Log All Queries
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to log every query received by this DNS Server and the corresponding response answers into the log file.</div>
<div class="checkbox">
<label>
<input id="chkUseLocalTime" type="checkbox"> Use Local Time
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to use local time instead of UTC for logging.</div>
</div>
</div>
<div class="form-group">
<label for="txtLogFolderPath" class="col-sm-3 control-label">Log Folder Path</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtLogFolderPath" placeholder="Log Folder Path On Server" maxlength="255">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The folder path on the server where the log files should be saved. The path can be relative to the DNS server's config folder.</div>
</div>
<div class="form-group">
<label for="txtMaxLogFileDays" class="col-sm-3 control-label">Max Log File Days</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtMaxLogFileDays" placeholder="Max Days" style="width: 100px; display: inline;">
<span>days (default 365, set 0 to disable auto delete)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Max number of days to keep the log files. Log files older than the specified number of days will be deleted automatically.</div>
</div>
<div>Warning! Enabling query logging will significantly increase the log file size and use up disk space.</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Stats</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkEnableInMemoryStats" type="checkbox"> Enable In-Memory Stats
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">This option will enable in-memory stats and only Last Hour data will be available on Dashboard. No stats data will be stored on disk.</div>
</div>
</div>
<div class="form-group">
<label for="txtMaxStatFileDays" class="col-sm-3 control-label">Max Stat File Days</label>
<div class="col-sm-6">
<input type="number" class="form-control" id="txtMaxStatFileDays" placeholder="Max Days" style="width: 100px; display: inline;">
<span>days (default 365, set 0 to disable auto delete)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Max number of days to keep the dashboard stats. Stat files older than the specified number of days will be deleted automatically.</div>
</div>
</div>
</div>
</div>
<div class="form-group" style="margin-bottom: 0px;">
<div class="pull-left">
<button type="button" class="btn btn-primary" data-loading-text="Saving..." onclick="saveDnsSettings(this);">Save Settings</button>
<button id="btnSettingsFlushCache" type="button" class="btn btn-danger" data-loading-text="Flushing..." onclick="flushDnsCache(this, $('#optSettingsClusterNode').val());" style="margin-left: 6px;">Flush Cache</button>
</div>
<div class="pull-right">
<button id="btnShowBackupSettingsModal" type="button" class="btn btn-success" onclick="resetBackupSettingsModal();" data-toggle="modal" data-target="#modalBackupSettings">Backup Settings</button>
<button id="btnShowRestoreSettingsModal" type="button" class="btn btn-warning" onclick="resetRestoreSettingsModal();" data-toggle="modal" data-target="#modalRestoreSettings" style="margin-left: 6px;">Restore Settings</button>
</div>
<div class="clearfix"></div>
</div>
</form>
</div>
</div>
<div id="mainPanelTabPaneDhcp" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<ul class="nav nav-tabs" role="tablist">
<li id="dhcpTabListLeases" role="presentation" class="active"><a href="#dhcpTabPaneLeases" aria-controls="dhcpTabPaneLeases" role="tab" data-toggle="tab" onclick="refreshDhcpLeases();">Leases</a></li>
<li id="dhcpTabListScopes" role="presentation"><a href="#dhcpTabPaneScopes" aria-controls="dhcpTabPaneScopes" role="tab" data-toggle="tab" onclick="refreshDhcpScopes(true);">Scopes</a></li>
<li class="pull-right">
<select id="optDhcpClusterNode" class="form-control pull-right cluster-node-dropdown" style="margin-left: 0px;" onchange="refreshDhcpTab();"></select>
</li>
</ul>
<div class="tab-content">
<div id="dhcpTabPaneLeases" class="tab-pane active">
<div id="divDhcpLeasesLoader" style="margin-top: 10px; height: 350px;"></div>
<div id="divDhcpLeases" style="margin-top: 10px;">
<table class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tableDhcpLeasesBody', 0); return false;">Scope</a></th>
<th><a href="#" onclick="sortTable('tableDhcpLeasesBody', 1); return false;">MAC Address</a></th>
<th><a href="#" onclick="sortTable('tableDhcpLeasesBody', 2); return false;">IP Address</a></th>
<th><a href="#" onclick="sortTable('tableDhcpLeasesBody', 3); return false;"></a></th>
<th><a href="#" onclick="sortTable('tableDhcpLeasesBody', 4); return false;">Host Name</a></th>
<th><a href="#" onclick="sortTable('tableDhcpLeasesBody', 5); return false;">Lease Obtained</a></th>
<th><a href="#" onclick="sortTable('tableDhcpLeasesBody', 6); return false;">Lease Expires</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tableDhcpLeasesBody">
</tbody>
<tfoot id="tableDhcpLeasesFooter">
<tr><td><b>Total Leases: 0</b></td></tr>
</tfoot>
</table>
</div>
</div>
<div id="dhcpTabPaneScopes" class="tab-pane">
<div id="divDhcpViewScopesLoader" style="margin-top: 10px; height: 350px;"></div>
<div id="divDhcpViewScopes" style="margin-top: 10px;">
<div style="float: right; padding: 2px 0px;">
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showAddDhcpScope();">Add Scope</button>
</div>
<div style="clear: both;"></div>
<table class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tableDhcpScopesBody', 0); return false;">Name</a></th>
<th><a href="#" onclick="sortTable('tableDhcpScopesBody', 1); return false;">Scope Range/Subnet Mask</a></th>
<th><a href="#" onclick="sortTable('tableDhcpScopesBody', 2); return false;">Network/Broadcast</a></th>
<th><a href="#" onclick="sortTable('tableDhcpScopesBody', 3); return false;">Interface</a></th>
<th></th>
</tr>
</thead>
<tbody id="tableDhcpScopesBody">
</tbody>
<tfoot id="tableDhcpScopesFooter">
<tr><td><b>Total Leases: 0</b></td></tr>
</tfoot>
</table>
</div>
<div id="divDhcpEditScope" style="display: none;">
<form style="margin-top: 10px; margin-bottom: 0px;" onsubmit="return false;">
<h4 style="padding: 10px 0px;" id="titleDhcpEditScope">Edit Scope</h4>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDhcpScopeName" class="col-sm-3 control-label">Name</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDhcpScopeName" data-name="" placeholder="Scope Name">
</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeStartingAddress" class="col-sm-3 control-label">Starting Address</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txtDhcpScopeStartingAddress" placeholder="Starting Address">
</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeEndingAddress" class="col-sm-3 control-label">Ending Address</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txtDhcpScopeEndingAddress" placeholder="Ending Address">
</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeSubnetMask" class="col-sm-3 control-label">Subnet Mask</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txtDhcpScopeSubnetMask" placeholder="Subnet Mask">
</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeLeaseTimeDays" class="col-sm-3 control-label">Lease Time</label>
<div class="col-sm-7">
<label for="txtDhcpScopeLeaseTimeDays" class="control-label">Days</label>
<input type="number" class="form-control" style="display: inline; width: 80px; margin-right: 15px;" id="txtDhcpScopeLeaseTimeDays" placeholder="Days">
<label for="txtDhcpScopeLeaseTimeHours" class="control-label">Hours</label>
<input type="number" class="form-control" style="display: inline; width: 80px; margin-right: 15px;" id="txtDhcpScopeLeaseTimeHours" placeholder="Hrs">
<label for="txtDhcpScopeLeaseTimeMinutes" class="control-label">Minutes</label>
<input type="number" class="form-control" style="display: inline; width: 80px; margin-right: 15px;" id="txtDhcpScopeLeaseTimeMinutes" placeholder="Mins">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The duration for which the clients should be leased the IP address.</div>
</div>
<div class="form-group" style="margin-bottom: 0px;">
<label for="txtDhcpScopeOfferDelayTime" class="col-sm-3 control-label">Offer Delay Time</label>
<div class="col-sm-3">
<input type="number" class="form-control" style="width: 80px; display: inline;" id="txtDhcpScopeOfferDelayTime" placeholder="Delay">
<span>milliseconds</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The time duration that the DHCP server delays sending an DHCPOFFER message.</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="chkDhcpScopePingCheckEnabled" class="col-sm-3 control-label">Ping Check</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkDhcpScopePingCheckEnabled" type="checkbox"> Enable Ping Check
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to allow DHCP server to find out if an IP address is already in use to prevent IP address conflict when some of the devices on the network have manually configured IP addresses.</div>
</div>
</div>
<div class="form-group">
<label for="txtDhcpScopePingCheckTimeout" class="col-sm-3 control-label">Ping Check Timeout</label>
<div class="col-sm-4">
<input type="number" class="form-control" style="width: 100px; display: inline;" id="txtDhcpScopePingCheckTimeout" placeholder="timeout">
<span>milliseconds (default 1000)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The timeout interval to wait for an ping reply.</div>
</div>
<div class="form-group">
<label for="txtDhcpScopePingCheckRetries" class="col-sm-3 control-label">Ping Check Retries</label>
<div class="col-sm-3">
<input type="number" class="form-control" style="width: 100px; display: inline;" id="txtDhcpScopePingCheckRetries" placeholder="retry">
<span>(default 2)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The maximum number of ping requests to try.</div>
</div>
<div style="padding-top: 5px;">Warning! Ping check would work as expected only when you make sure that all the client devices with manually configured IP addresses on the network respond to a ping request. Devices running Microsoft Windows by default drop ping requests at host firewall and will cause this ping check to fail to detect in use IP addresses. It is recommended to not rely on this option and instead make sure that you exclude a range of addresses using Exclusions and manually assign IP addresses to your devices only in the excluded range.</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDhcpScopeDomainName" class="col-sm-3 control-label">Domain Name</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="txtDhcpScopeDomainName" placeholder="Domain Name">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The domain name for this network to allow assigning a fully qualified domain name to clients. Use a domain name that you own or that is not in common use like 'home' or 'lan' so that you don't block out an existing domain name. (Option 15)</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeDomainSearchStrings" class="col-sm-3 control-label">Domain Search List</label>
<div class="col-sm-3">
<textarea id="txtDhcpScopeDomainSearchStrings" class="form-control" rows="2" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The list of domain names that the clients can use as a suffix when searching a domain name. (Option 119)</div>
</div>
<div class="form-group">
<label for="chkDhcpScopeDnsUpdates" class="col-sm-3 control-label">DNS Updates</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkDhcpScopeDnsUpdates" type="checkbox"> Enable DNS Updates
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to allow the DHCP server to automatically update forward and reverse DNS entries for clients.</div>
<div class="checkbox">
<label>
<input id="chkDnsOverwriteForDynamicLease" type="checkbox"> Enable DNS Overwrite For Dynamic Lease
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to allow the DHCP server to overwrite existing DNS A record matching the client domain name for dynamic leases.</div>
</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeDnsTtl" class="col-sm-3 control-label">DNS TTL</label>
<div class="col-sm-8">
<input type="text" class="form-control" style="width: 100px; display: inline;" id="txtDhcpScopeDnsTtl" placeholder="DNS TTL">
<span>seconds (default 900/15m)</span>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The TTL value of the DNS records updated for the above provided domain name.</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDhcpScopeRouterAddress" class="col-sm-3 control-label">Router Address</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txtDhcpScopeRouterAddress" placeholder="Router Address">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The default gateway IP address to be used by the clients. (Option 3)</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeDnsServers" class="col-sm-3 control-label">DNS Servers</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkUseThisDnsServer" type="checkbox" onclick="$('#txtDhcpScopeDnsServers').prop('disabled', $(this).prop('checked'));"> Use This DNS Server
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px; margin-bottom: 10px;">Enable this option to automatically use this DNS Server.</div>
</div>
<div class="col-sm-offset-3 col-sm-3">
<textarea id="txtDhcpScopeDnsServers" class="form-control" rows="2" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The DNS server IP addresses to be used by the clients. (Option 6)</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeWinsServers" class="col-sm-3 control-label">WINS Servers</label>
<div class="col-sm-3">
<textarea id="txtDhcpScopeWinsServers" class="form-control" rows="2" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The NBNS/WINS server IP addresses to be used by the clients. (Option 44)</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeNtpServers" class="col-sm-3 control-label">NTP Servers</label>
<div class="col-sm-3">
<textarea id="txtDhcpScopeNtpServers" class="form-control" rows="2" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The Network Time Protocol (NTP) server IP addresses to be used by the clients. (Option 42)</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeNtpServerDomainNames" class="col-sm-3 control-label">NTP Server Domain Names</label>
<div class="col-sm-3">
<textarea id="txtDhcpScopeNtpServerDomainNames" class="form-control" rows="2" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">Enter NTP server domain names (e.g. pool.ntp.org) above that the DHCP server should automatically resolve and pass the resolved IP addresses to clients as NTP server option. (Option 42)</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group" style="margin-bottom: 0px;">
<label for="tableDhcpScopeStaticRoutes" class="col-sm-3 control-label">Static Routes</label>
<div class="col-sm-7">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th>Destination</th>
<th>Subnet Mask</th>
<th>Router</th>
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeStaticRouteRow('', '', '');">Add</button></th>
</tr>
</thead>
<tbody id="tableDhcpScopeStaticRoutes"></tbody>
</table>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The static routes to be used by the clients for accessing specified destination networks. (Option 121)</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDhcpScopeServerAddress" class="col-sm-3 control-label">Bootstrap Server Address</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txtDhcpScopeServerAddress" placeholder="Bootstrap Server Address">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The IP address of next server (TFTP) to use in bootstrap by the clients. If not specified, the DHCP server's IP address is used. (siaddr)</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeServerHostName" class="col-sm-3 control-label">Bootstrap Server Host Name</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txtDhcpScopeServerHostName" placeholder="Bootstrap Server Host Name">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The optional bootstrap server host name to be used by the clients to identify the TFTP server. (sname/Option 66)</div>
</div>
<div class="form-group">
<label for="txtDhcpScopeBootFileName" class="col-sm-3 control-label">Boot File Name</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="txtDhcpScopeBootFileName" placeholder="Boot File Name">
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The boot file name stored on the bootstrap TFTP server to be used by the clients. (file/Option 67)</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group" style="margin-bottom: 0px;">
<label for="tableDhcpScopeVendorInfo" class="col-sm-3 control-label">Vendor Specific Information</label>
<div class="col-sm-9">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th>Vendor Class Identifier</th>
<th>Vendor Specific Information</th>
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeVendorInfoRow('', '');">Add</button></th>
</tr>
</thead>
<tbody id="tableDhcpScopeVendorInfo"></tbody>
</table>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The Vendor Specific Information (option 43) to be sent to the clients that match the Vendor Class Identifier (option 60) in the request. The Vendor Class Identifier can be empty string to match any identifier, or matched exactly, or match a substring, for example <code>substring(vendor-class-identifier,0,9)=="PXEClient"</code>. The Vendor Specific Information must be either a colon (:) separated hex string or a normal hex string, for example <code>06:01:03:0A:04:00:50:58:45:09:14:00:00:11:52:61:73:70:62:65:72:72:79:20:50:69:20:42:6F:6F:74:FF</code> OR <code>0601030A0400505845091400001152617370626572727920506920426F6F74FF</code>.</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDhcpScopeCAPWAPApIpAddresses" class="col-sm-3 control-label">CAPWAP Access Controller Addresses</label>
<div class="col-sm-3">
<textarea id="txtDhcpScopeCAPWAPApIpAddresses" class="form-control" rows="2" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The Control And Provisioning of Wireless Access Points (CAPWAP) Access Controller IP addresses to be used by Wireless Termination Points to discover the Access Controllers to which it is to connect. (Option 138)</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtDhcpScopeTftpServerAddresses" class="col-sm-3 control-label">TFTP Server Addresses</label>
<div class="col-sm-3">
<textarea id="txtDhcpScopeTftpServerAddresses" class="form-control" rows="2" spellcheck="false"></textarea>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The TFTP Server Address or the VoIP Configuration Server Address. (Option 150)</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group" style="margin-bottom: 0px;">
<label for="tableDhcpScopeGenericOptions" class="col-sm-3 control-label">Generic DHCP Options</label>
<div class="col-sm-9">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th style="width: 90px;">Code</th>
<th>Hex Value</th>
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeGenericOptionsRow('', '');">Add</button></th>
</tr>
</thead>
<tbody id="tableDhcpScopeGenericOptions"></tbody>
</table>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">This feature allows you to define DHCP options that are not yet directly supported. To add an option, use the DHCP option code defined for it and enter the value in either a colon (:) separated hex string or a normal hex string format, for example <code>C0:A8:01:01</code> OR <code>C0A80101</code>.</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="tableDhcpScopeExclusions" class="col-sm-3 control-label">Exclusions</label>
<div class="col-sm-6">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th>Starting Address</th>
<th>Ending Address</th>
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeExclusionRow('', '');">Add</button></th>
</tr>
</thead>
<tbody id="tableDhcpScopeExclusions"></tbody>
</table>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The IP address range that must be excluded or not assigned dynamically to any client by the DHCP server.</div>
</div>
<div style="padding-top: 5px;">Note! Make sure to exclude address ranges if you plan to manually assign IP addresses to some of the devices or to assign reserved leases so that these IP addresses are not dynamically allocated in the first place.</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="tableDhcpScopeReservedLeases" class="col-sm-3 control-label">Advanced Options</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkAllowOnlyReservedLeases" type="checkbox"> Allow Only Reserved Lease Allocations
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to stop dynamic IP address allocation and allocate only reserved IP addresses.</div>
</div>
<div class="col-sm-offset-3 col-sm-8">
<div class="checkbox">
<label>
<input id="chkBlockLocallyAdministeredMacAddresses" type="checkbox"> Block Locally Administered MAC Addresses
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to stop dynamic IP address allocation for clients with locally administered MAC addresses. MAC address with 0x02 bit set in the first octet indicate a <a href="https://en.wikipedia.org/wiki/MAC_address" target="_blank">locally administered</a> MAC address which usually means that the device is not using its original MAC address.</div>
</div>
<div class="col-sm-offset-3 col-sm-8">
<div class="checkbox">
<label>
<input id="chkIgnoreClientIdentifierOption" type="checkbox"> Ignore Client Identifier (Option 61)
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">This option when enabled will always use the client's MAC address as the identifier to allocate lease instead of the Client Identifier (Option 61) provided by the client in the request. Some Linux distros use a custom Client Identifier instead of the device's MAC Address which can cause issues when the Virtual Machine (VM) in which the OS is installed is cloned causing both the original and cloned clients to get same IP allocated. There can be issues too when the same client changes its Client Identifier and starts getting a different IP address lease. Enabling the Ignore Client Identifier option will fix such issues. Changing this option may cause the existing clients to get a different IP lease on renewal.</div>
</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group" style="margin-bottom: 0px;">
<label for="tableDhcpScopeReservedLeases" class="col-sm-3 control-label">Reserved Leases</label>
<div class="col-sm-9">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th>Host Name</th>
<th>MAC Address</th>
<th>IP Address</th>
<th>Comments</th>
<th style="width: 84px;"><button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addDhcpScopeReservedLeaseRow('', '', '', '');">Add</button></th>
</tr>
</thead>
<tbody id="tableDhcpScopeReservedLeases"></tbody>
</table>
</div>
<div class="col-sm-offset-3 col-sm-8" style="padding-top: 5px;">The reserved IP addresses to be assigned to specific clients based on their MAC address. Set a hostname to override the client's hostname.</div>
</div>
</div>
<div class="form-group" style="margin-bottom: 0px;">
<button type="submit" class="btn btn-primary" style="width: 100px;" id="btnSaveDhcpScope" data-loading-text="Saving..." onclick="saveDhcpScope(); return false;">Save</button>
<button type="button" class="btn btn-default" style="width: 100px;" onclick="refreshDhcpScopes();">Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div id="mainPanelTabPaneAdmin" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<div>
<ul class="nav nav-tabs" role="tablist">
<li id="adminTabListSessions" role="presentation" class="active"><a href="#adminTabPaneSessions" aria-controls="adminTabPaneSessions" role="tab" data-toggle="tab" onclick="refreshAdminSessions();">Sessions</a></li>
<li id="adminTabListUsers" role="presentation"><a href="#adminTabPaneUsers" aria-controls="adminTabPaneUsers" role="tab" data-toggle="tab" onclick="refreshAdminUsers();">Users</a></li>
<li id="adminTabListGroups" role="presentation"><a href="#adminTabPaneGroups" aria-controls="adminTabPaneGroups" role="tab" data-toggle="tab" onclick="refreshAdminGroups();">Groups</a></li>
<li id="adminTabListPermissions" role="presentation"><a href="#adminTabPanePermissions" aria-controls="adminTabPanePermissions" role="tab" data-toggle="tab" onclick="refreshAdminPermissions();">Permissions</a></li>
<li id="adminTabListCluster" role="presentation"><a href="#adminTabPaneCluster" aria-controls="adminTabPaneCluster" role="tab" data-toggle="tab" onclick="refreshAdminCluster();">Cluster</a></li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tab-content">
<div id="adminTabPaneSessions" class="tab-pane active">
<div id="divAdminSessionsLoader" style="margin-top: 10px; height: 350px;"></div>
<div id="divAdminSessionsView" style="margin-top: 10px;">
<div class="form-inline pull-right" style="padding: 2px 0px;">
<button id="btnAdminSessionsCreateToken" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showCreateApiTokenModal();">Create Token</button>
<select id="optAdminSessionsClusterNode" class="form-control cluster-node-dropdown" onchange="refreshAdminSessions();"></select>
</div>
<div style="clear: both;"></div>
<table id="tableAdminSessions" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyAdminSessions', 0); return false;">Username</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminSessions', 1); return false;">Session</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminSessions', 2); return false;">Last Seen</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminSessions', 3); return false;">Remote Address</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminSessions', 4); return false;">User Agent</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyAdminSessions">
</tbody>
<tfoot>
<tr><th colspan="6" id="tfootAdminSessions"></th></tr>
</tfoot>
</table>
</div>
</div>
<div id="adminTabPaneUsers" class="tab-pane">
<div id="divAdminUsersLoader" style="margin-top: 10px; height: 350px;"></div>
<div id="divAdminUsersView" style="margin-top: 10px;">
<div style="float: right; padding: 2px 0px;">
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showAddUserModal();">Add User</button>
</div>
<div style="clear: both;"></div>
<table id="tableAdminUsers" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyAdminUsers', 0); return false;">Username</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminUsers', 1); return false;">Display Name</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminUsers', 2); return false;">2FA Status</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminUsers', 3); return false;">Status</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminUsers', 4); return false;">Recent Login</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminUsers', 5); return false;">Previous Login</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyAdminUsers">
</tbody>
<tfoot>
<tr><th colspan="7" id="tfootAdminUsers"></th></tr>
</tfoot>
</table>
</div>
</div>
<div id="adminTabPaneGroups" class="tab-pane">
<div id="divAdminGroupsLoader" style="margin-top: 10px; height: 350px;"></div>
<div id="divAdminGroupsView" style="margin-top: 10px;">
<div style="float: right; padding: 2px 0px;">
<button type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showAddGroupModal();">Add Group</button>
</div>
<div style="clear: both;"></div>
<table id="tableAdminGroups" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyAdminGroups', 0); return false;">Name</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminGroups', 1); return false;">Description</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyAdminGroups">
</tbody>
<tfoot>
<tr><th colspan="3" id="tfootAdminGroups"></th></tr>
</tfoot>
</table>
</div>
</div>
<div id="adminTabPanePermissions" class="tab-pane">
<div id="divAdminPermissionsLoader" style="margin-top: 10px; height: 350px;"></div>
<div id="divAdminPermissionsView" style="margin-top: 10px;">
<table id="tableAdminPermissions" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyAdminPermissions', 0); return false;">Section</a></th>
<th>User Permissions</th>
<th>Group Permissions</th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyAdminPermissions">
</tbody>
<tfoot>
<tr><th colspan="4" id="tfootAdminPermissions"></th></tr>
</tfoot>
</table>
</div>
</div>
<div id="adminTabPaneCluster" class="tab-pane">
<div id="divAdminClusterLoader" style="margin-top: 10px; height: 350px;"></div>
<div id="divAdminClusterView" style="margin-top: 10px;">
<div class="form-inline pull-right" style="padding: 2px 0px;">
<div id="divAdminClusterInitialize" class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" style="padding: 2px 0px; width: 100px;" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Initialize <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li id="lnkAdminClusterInitializeNewCluster"><a href="#" onclick="showInitializeClusterModal(); return false;">New Cluster</a></li>
<li id="lnkAdminClusterInitializeJoinCluster"><a href="#" onclick="showInitializeJoinClusterModal(); return false;">Join Cluster</a></li>
</ul>
</div>
<button id="btnClusterResync" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="resyncCluster(this);" data-loading-text="Resyncing...">Resync</button>
<button id="btnClusterOptions" type="button" class="btn btn-primary" style="padding: 2px 0px; width: 100px;" onclick="showClusterOptionsModal();">Options</button>
<button id="btnClusterLeave" type="button" class="btn btn-warning" style="padding: 2px 0px; width: 100px;" onclick="showLeaveClusterModal();">Leave Cluster</button>
<button id="btnClusterDelete" type="button" class="btn btn-danger" style="padding: 2px 0px; width: 100px;" onclick="showDeleteClusterModal();">Delete Cluster</button>
<select id="optAdminClusterNode" class="form-control cluster-node-dropdown" onchange="refreshAdminCluster();"></select>
</div>
<div style="clear: both;"></div>
<table id="tableAdminCluster" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyAdminCluster', 0); return false;">Node Name</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminCluster', 1); return false;">IP Address</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminCluster', 2); return false;">URL</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminCluster', 3); return false;">Type</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminCluster', 4); return false;">State</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminCluster', 5); return false;">Up Since</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminCluster', 6); return false;">Last Seen</a></th>
<th><a href="#" onclick="sortTable('tbodyAdminCluster', 7); return false;">Last Synced</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyAdminCluster">
</tbody>
<tfoot>
<tr><th colspan="9" id="tfootAdminCluster"></th></tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
<div id="mainPanelTabPaneLogs" role="tabpanel" class="tab-pane" style="padding: 10px 0 0 0;">
<ul class="nav nav-tabs" role="tablist">
<li id="logsTabListLogViewer" role="presentation" class="active"><a href="#logsTabPaneLogViewer" aria-controls="logsTabPaneLogViewer" role="tab" data-toggle="tab" onclick="refreshLogFilesList();">View Logs</a></li>
<li id="logsTabListQueryLogs" role="presentation"><a href="#logsTabPaneQueryLogs" aria-controls="logsTabPaneQueryLogs" role="tab" data-toggle="tab" onclick="refreshQueryLogsTab();">Query Logs</a></li>
<li class="pull-right">
<select id="optLogsClusterNode" class="form-control pull-right cluster-node-dropdown" style="margin-left: 0px;" onchange="logsClusterNodeChanged();"></select>
</li>
</ul>
<div class="tab-content">
<div id="logsTabPaneLogViewer" class="tab-pane active" style="padding-top: 15px;">
<div class="well well-sm log-list-pane">
<div id="lstLogFiles" class="logs">
</div>
</div>
<div id="divLogViewer" class="log-viewer-pane">
<div class="panel panel-default">
<div class="panel-heading" style="height: 36px; padding: 4px 6px;">
<div id="txtLogViewerTitle" style="float: left; padding: 4px;">20171012</div>
<div style="float: right;">
<button type="button" class="btn btn-default" data-loading-text="Download" onclick="downloadLog(this);" style="font-size: 12px; padding: 4px 6px;">Download</button>
<button id="btnDeleteLog" type="button" class="btn btn-danger" data-loading-text="Delete" onclick="deleteLog();" style="font-size: 12px; padding: 4px 6px;">Delete</button>
</div>
</div>
<div class="panel-body">
<div id="divLogViewerLoader" style="margin-top: 20px; height: 400px;"></div>
<pre id="preLogViewerBody" style="display: none; word-wrap: normal; word-break: normal;"></pre>
</div>
</div>
</div>
</div>
<div id="logsTabPaneQueryLogs" class="tab-pane active" style="padding-top: 15px;">
<form id="frmQueryLogs" class="form-inline well" style="padding-bottom: 6px;">
<div class="form-group">
<label for="optQueryLogsAppName">App Name</label>
<select class="form-control" id="optQueryLogsAppName">
</select>
</div>
<div class="form-group">
<label for="optQueryLogsClassPath">Class Path</label>
<select class="form-control" id="optQueryLogsClassPath">
</select>
</div>
<div class="form-group">
<label for="txtQueryLogPageNumber">Page Number</label>
<input id="txtQueryLogPageNumber" type="number" class="form-control" style="width: 120px;" value="1" />
</div>
<div class="form-group">
<label for="optQueryLogsEntriesPerPage">Logs Per Page</label>
<select class="form-control" id="optQueryLogsEntriesPerPage">
<option>10</option>
<option>25</option>
<option>50</option>
<option>100</option>
<option>250</option>
<option>500</option>
</select>
</div>
<div class="form-group">
<label for="optQueryLogsDescendingOrder">Order</label>
<select class="form-control" id="optQueryLogsDescendingOrder">
<option value="false">Ascending</option>
<option value="true" selected>Descending</option>
</select>
</div>
<div class="form-group">
<label for="txtQueryLogStart">From</label>
<input id="txtQueryLogStart" type="datetime-local" class="form-control" />
</div>
<div class="form-group">
<label for="txtQueryLogEnd">To</label>
<input id="txtQueryLogEnd" type="datetime-local" class="form-control" />
</div>
<div class="form-group">
<label for="txtQueryLogClientIpAddress">Client IP Address</label>
<input id="txtQueryLogClientIpAddress" type="text" class="form-control" style="min-width: 170px;" />
</div>
<div class="form-group">
<label for="optQueryLogsProtocol">Protocol</label>
<select class="form-control" id="optQueryLogsProtocol">
<option selected></option>
<option value="Udp">UDP</option>
<option value="Tcp">TCP</option>
<option value="Tls">TLS</option>
<option value="Https">HTTPS</option>
<option value="Quic">QUIC</option>
<option value="UdpProxy">UDP Proxy</option>
<option value="TcpProxy">TCP Proxy</option>
</select>
</div>
<div class="form-group">
<label for="optQueryLogsResponseType">Response Type</label>
<select class="form-control" id="optQueryLogsResponseType">
<option selected></option>
<option>Authoritative</option>
<option>Recursive</option>
<option>Cached</option>
<option>Blocked</option>
<option>UpstreamBlocked</option>
<option>UpstreamBlockedCached</option>
</select>
</div>
<div class="form-group">
<label for="optQueryLogsResponseCode">RCODE</label>
<select class="form-control" id="optQueryLogsResponseCode">
<option selected></option>
<option value="NoError">No Error</option>
<option value="FormatError">Format Error</option>
<option value="ServerFailure">Server Failure</option>
<option value="NxDomain">NX Domain</option>
<option value="NotImplemented">Not Implemented</option>
<option value="Refused">Refused</option>
<option value="YXDomain">YX Domain</option>
<option value="YXRRSet">YX RRSet</option>
<option value="NXRRSet">NX RRSet</option>
<option value="NotAuth">Not Auth</option>
<option value="NotZone">Not Zone</option>
</select>
</div>
<div class="form-group">
<label for="txtQueryLogQName">Domain</label>
<input id="txtQueryLogQName" type="text" class="form-control" style="min-width: 300px;" />
</div>
<div class="form-group">
<label for="txtQueryLogQType">Type</label>
<input id="txtQueryLogQType" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="optQueryLogQClass">Class</label>
<select class="form-control" id="optQueryLogQClass">
<option selected></option>
<option>IN</option>
<option>CS</option>
<option>CH</option>
<option>HS</option>
<option>NONE</option>
<option>ANY</option>
</select>
</div>
<div class="form-group" style="display: block;">
<button type="submit" class="btn btn-primary" id="btnQueryLogs" data-loading-text="Querying..." onclick="queryLogs(); return false;" style="margin-right: 6px;">Query</button>
<button type="button" class="btn btn-default" data-loading-text="Export" onclick="exportQueryLogsCsv(this);" style="margin-right: 6px;">Export</button>
<button type="reset" class="btn btn-default" onclick="resetQueryLogsForm();" style="margin-right: 12px;">Reset</button>
<div class="checkbox">
<label>
<input type="checkbox" id="chkQueryLogsLiveUpdate"> Live Update
</label>
</div>
</div>
</form>
<div id="divQueryLogsLoader" style="margin-top: 20px; height: 300px;"></div>
<div id="divQueryLogsTable" style="display: none;">
<div style="padding: 8px;">
<div class="pull-left" style="padding-top: 8px;">
<b id="tableQueryLogsTopStatus">Found: 0 logs</b>
</div>
<div class="pull-right">
<nav aria-label="Page navigation">
<ul id="tableQueryLogsTopPagination" class="pagination" style="margin: 0;">
<li><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
<li><a href="#">1</a></li>
<li><a href="#" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
</ul>
</nav>
</div>
<div class="clearfix"></div>
</div>
<table class="table table-hover query-logs">
<thead>
<tr>
<th>#</th>
<th style="width: 95px;">Timestamp</th>
<th>Client IP Address</th>
<th>Protocol</th>
<th>Response Type</th>
<th>RCODE</th>
<th style="min-width: 200px;">Domain</th>
<th>Type</th>
<th>Class</th>
<th>Answer</th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tableQueryLogsBody">
</tbody>
<tfoot>
<tr>
<td colspan="11">
<div>
<div class="pull-left" style="padding-top: 8px;">
<b id="tableQueryLogsFooterStatus">Found: 0 logs</b>
</div>
<div class="pull-right">
<nav aria-label="Page navigation">
<ul id="tableQueryLogsFooterPagination" class="pagination" style="margin: 0;">
<li><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
<li><a href="#">1</a></li>
<li><a href="#" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
</ul>
</nav>
</div>
<div class="clearfix"></div>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
<div id="mainPanelTabPaneAbout" role="tabpanel" class="tab-pane" style="padding: 40px 0 20px 0;">
<div class="about" style="text-align: center;">
<img src="img/logo.png" alt="Technitium Logo" />
<h1>Technitium DNS Server</h1>
<p>Version <span id="lblAboutVersion"></span></p>
<p>Server up since <span id="lblAboutUptime"></span></p>
<p style="max-width: 800px; margin: 0 auto 10px auto;">
Copyright (C) 2025 Shreyas Zare (shreyas@technitium.com)<br />
This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions.<br />
</p>
<p>Source code available under <a href="https://go.technitium.com/?id=24" target="_blank">GNU General Public License v3.0</a> on <a href="https://github.com/TechnitiumSoftware/DnsServer" target="_blank"><i class="fa fa-github"></i>&nbsp;GitHub</a></p>
<h3 style="margin-top: 40px;"><a href="https://go.technitium.com/?id=23" target="_blank">What's New?</a></h3>
<p>Read the <a href="https://go.technitium.com/?id=23" target="_blank">change log</a> to know what's new in this release.</p>
<h3 style="margin-top: 40px;"><a href="https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md" target="_blank">API Documentation</a></h3>
<p>The DNS server HTTP API allows any 3rd party app or script to configure the DNS server. The HTTP API is used by this web console and thus all the actions that this web console does can be performed via the API. Read the <a href="https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md" target="_blank">HTTP API documentation</a> for complete details.</p>
<h3 style="margin-top: 40px;"><a href="https://go.technitium.com/?id=25" target="_blank">Help Topics</a></h3>
<p>Read the latest <a href="https://go.technitium.com/?id=25" target="_blank">online help topics</a> which contains the DNS Server user manual and covers frequently asked questions.</p>
<h3 style="margin-top: 40px;">Support</h3>
<p>For support, send an email to <a href="mailto:support@technitium.com" target="_blank">support@technitium.com</a>.</p>
<p>
Follow <a href="https://mastodon.social/@technitium" target="_blank">@technitium@mastodon.social</a> on Mastodon.<br />
Checkout <a href="https://blog.technitium.com/" target="_blank">Technitium Blog</a>.
</p>
<p>
Join <a href="https://www.reddit.com/r/technitium/" target="_blank">/r/technitium</a> on Reddit.
</p>
<h3 style="margin-top: 40px;"><a href="https://go.technitium.com/?id=35" target="_blank">Donate</a></h3>
<p>Make a contribution to Technitium and help making new software, updates, and features possible.</p>
<p>
<a href="https://go.technitium.com/?id=35" target="_blank">Donate Now!</a>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="modalMyProfile" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 940px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">My Profile</h4>
</div>
<div class="modal-body">
<div id="divMyProfileAlert"></div>
<div id="divMyProfileLoader" style="height: 500px;"></div>
<div id="divMyProfileViewer" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div class="form-group">
<label for="txtMyProfileDisplayName" class="col-sm-4 control-label">Display Name</label>
<div class="col-sm-7">
<input id="txtMyProfileDisplayName" type="text" class="form-control" placeholder="display name" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtMyProfileUsername" class="col-sm-4 control-label">Username</label>
<div class="col-sm-7">
<input id="txtMyProfileUsername" type="text" class="form-control" placeholder="username" disabled>
</div>
</div>
<div class="form-group">
<label for="lblMyProfile2FAStatus" class="col-sm-4 control-label">2FA Status</label>
<div class="col-sm-7">
<div id="lblMyProfile2FAStatus" style="padding: 6px 0; font-weight: bold;"></div>
</div>
</div>
<div class="form-group">
<label for="txtMyProfileSessionTimeout" class="col-sm-4 control-label">Session Timeout</label>
<div class="col-sm-7">
<input id="txtMyProfileSessionTimeout" type="number" class="form-control" placeholder="1800" style="width: 100px; display: inline;">
<span>seconds (valid range 0-604800; default 1800; set 0 to disable)</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Member Of</label>
<div class="col-sm-7">
<table class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyMyProfileMemberOf', 0); return false;">Group</a></th>
</tr>
</thead>
<tbody id="tbodyMyProfileMemberOf">
</tbody>
<tfoot>
<tr><th colspan="1" id="tfootMyProfileMemberOf"></th></tr>
</tfoot>
</table>
</div>
</div>
<div class="well well-sm" style="background-color: #fbfbfb;">
<p style="font-size: 16px; font-weight: bold;">Active Sessions</p>
<table id="tableMyProfileActiveSessions" class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyMyProfileActiveSessions', 0); return false;">Session</a></th>
<th><a href="#" onclick="sortTable('tbodyMyProfileActiveSessions', 1); return false;">Last Seen</a></th>
<th><a href="#" onclick="sortTable('tbodyMyProfileActiveSessions', 2); return false;">Remote Address</a></th>
<th><a href="#" onclick="sortTable('tbodyMyProfileActiveSessions', 3); return false;">User Agent</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyMyProfileActiveSessions">
</tbody>
<tfoot>
<tr><th colspan="5" id="tfootMyProfileActiveSessions"></th></tr>
</tfoot>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveMyProfile(this); return false;">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalCreateApiToken" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Create API Token</h4>
</div>
<div class="modal-body">
<div id="divCreateApiTokenAlert"></div>
<div id="divCreateApiTokenLoader" style="height: 350px;"></div>
<div id="divCreateApiTokenForm">
<div class="form-group">
<label for="txtCreateApiTokenUsername" class="col-sm-4 control-label">Username</label>
<div class="col-sm-7">
<input id="txtCreateApiTokenUsername" type="text" class="form-control" placeholder="username" disabled>
<select id="optCreateApiTokenUsername" class="form-control"></select>
</div>
</div>
<div class="form-group" id="divCreateApiTokenPassword">
<label for="txtCreateApiTokenPassword" class="col-sm-4 control-label">Password</label>
<div class="col-sm-7">
<input id="txtCreateApiTokenPassword" type="password" class="form-control" placeholder="password" maxlength="255">
</div>
</div>
<div class="form-group" id="divCreateApiToken2FAOTP">
<label for="txtCreateApiToken2FATOTP" class="col-sm-4 control-label">Enter OTP</label>
<div class="col-sm-7">
<input id="txtCreateApiToken2FATOTP" type="text" class="form-control" style="width: 100px;" placeholder="OTP" maxlength="6" autocomplete="off">
<div style="padding-top: 5px;">Enter the 6-digit code you see in your authenticator app.</div>
</div>
</div>
<div class="form-group">
<label for="txtCreateApiTokenName" class="col-sm-4 control-label">Token Name</label>
<div class="col-sm-7">
<input id="txtCreateApiTokenName" type="text" class="form-control" placeholder="token name" maxlength="255">
</div>
</div>
<div>
<b>Warning!</b> The token allows access to API calls with the same privileges as that of the user account. Thus its recommended to create a separate user account with limited permissions as required by the specific task that the token will be used for. The token cannot be used to change the user's password, or update the user profile details.
</div>
</div>
<div id="divCreateApiTokenOutput">
<div class="form-group">
<label class="col-sm-3 control-label">Username</label>
<div class="col-sm-9">
<div id="lblCreateApiTokenOutputUsername" style="padding-top: 7px;"></div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Token Name</label>
<div class="col-sm-9">
<div id="lblCreateApiTokenOutputTokenName" style="padding-top: 7px; word-wrap: anywhere;"></div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Token</label>
<div class="col-sm-9">
<div id="lblCreateApiTokenOutputToken" style="padding-top: 7px;"></div>
</div>
</div>
<div>
<b>Warning!</b> The token value above will not be displayed later. You must copy the token value immediately and save it for later use.
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnCreateApiToken" type="submit" class="btn btn-primary" data-loading-text="Creating...">Create</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalChangePassword" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 id="titleChangePassword" class="modal-title">Change Password</h4>
</div>
<div class="modal-body">
<div id="divChangePasswordAlert"></div>
<div class="form-group">
<label for="txtChangePasswordUsername" class="col-sm-4 control-label">Username</label>
<div class="col-sm-7">
<input id="txtChangePasswordUsername" type="text" class="form-control" placeholder="username" disabled>
</div>
</div>
<div id="divChangePasswordCurrentPassword" class="form-group">
<label for="txtChangePasswordCurrentPassword" class="col-sm-4 control-label">Current Password</label>
<div class="col-sm-7">
<input id="txtChangePasswordCurrentPassword" type="password" class="form-control" placeholder="current password" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtChangePasswordNewPassword" class="col-sm-4 control-label">New Password</label>
<div class="col-sm-7">
<input id="txtChangePasswordNewPassword" type="password" class="form-control" placeholder="new password" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtChangePasswordConfirmPassword" class="col-sm-4 control-label">Confirm Password</label>
<div class="col-sm-7">
<input id="txtChangePasswordConfirmPassword" type="password" class="form-control" placeholder="confirm password" maxlength="255">
</div>
</div>
<div id="divChangePassword2FATOTP" class="form-group">
<label for="txtChangePassword2FATOTP" class="col-sm-4 control-label">Enter OTP</label>
<div class="col-sm-7">
<input id="txtChangePassword2FATOTP" type="text" class="form-control" style="width: 100px;" placeholder="OTP" maxlength="6" autocomplete="off">
<div style="padding-top: 5px;">Enter the 6-digit code you see in your authenticator app.</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnChangePassword" type="submit" class="btn btn-primary" data-loading-text="Working...">Change</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalConfigure2FA" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 750px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Configure Two-factor Authentication (2FA)</h4>
</div>
<div class="modal-body">
<div id="divConfigure2FAAlert"></div>
<div id="divConfigure2FALoader" style="height: 400px;"></div>
<div id="divConfigure2FAViewer">
<div>
<p>When you enable Two-factor Authentication (2FA) using Time-based One-time Password (TOTP), you will be required to enter a one-time password (OTP) in addition to your password when you login. You will need to use an authenticator app like <b>Microsoft Authenticator</b> or <b>Google Authenticator</b> to generate the OTP when you login.</p>
</div>
<div class="form-group">
<label for="txtConfigure2FAUsername" class="col-sm-3 control-label">Username</label>
<div class="col-sm-7">
<input id="txtConfigure2FAUsername" type="text" class="form-control" placeholder="username" disabled>
</div>
</div>
<div class="form-group">
<label for="lblConfigure2FAStatus" class="col-sm-3 control-label">2FA Status</label>
<div class="col-sm-8">
<div id="lblConfigure2FAStatus" style="padding: 6px 0; font-weight: bold;"></div>
</div>
</div>
<div id="divConfigure2FAInitialize">
<div class="form-group">
<label class="col-sm-3 control-label">Secret Key</label>
<div class="col-sm-8">
<div id="lblConfigure2FAQRCode" style="margin: -6px 0px 0px -12px;"></div>
<div id="lblConfigure2FASecret" style="padding: 4px 0; font-weight: bold;"></div>
<div style="padding-top: 5px;">Scan the QR Code or manually enter the secret key (spaces don't matter) given above in your authenticator app.</div>
</div>
</div>
<div class="form-group">
<label for="txtConfigure2FATOTP" class="col-sm-3 control-label">Enter OTP</label>
<div class="col-sm-8">
<input id="txtConfigure2FATOTP" type="text" class="form-control" style="width: 100px;" placeholder="OTP" maxlength="6" autocomplete="off">
<div style="padding-top: 5px;">Enter the 6-digit code you see in your authenticator app.</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnEnable2FA" type="submit" class="btn btn-primary" data-loading-text="Working..." onclick="enable2FA(this); return false;">Enable</button>
<button id="btnDisable2FA" type="button" class="btn btn-warning" data-loading-text="Working..." onclick="disable2FA(this); return false;">Disable</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalForgotPassword" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Forgot Password?</h4>
</div>
<div class="modal-body">
<p>To reset your password, you need to contact the DNS server administrator.</p>
<p>If you are an administrator, follow these steps to reset the 'admin' user's password:</p>
<ol>
<li>Stop the DNS server.</li>
<li>Find the DNS Server config folder and locate the <b>auth.config</b> file. The config folder will be found where the DNS Server is installed on Windows or /etc/dns/ folder on Linux.</li>
<li>Rename the <b>auth.config</b> file as <b>resetadmin.config</b></li>
<li>Start the DNS Server.</li>
<li>Just refresh this web page in the web browser to auto login with default credentials and quickly change the password.</li>
</ol>
<p>On Linux, stop the DNS server by running 'sudo systemctl stop dns' command and 'sudo systemctl start dns' command to start it.</p>
<p>On Windows, press Win+R to open Run, enter 'services.msc', and press enter to open Services console. Find service named 'Technitium DNS Server' and use the Action menu to start/stop it.</p>
<p><b>Note: </b>To reset 'admin' password, you will need file system access on the server running this DNS Server. If the 'admin' user does not exists then it will be created automatically. If the 'admin' user has Two-factor Authentication (2FA) configured then it will be disabled too.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalUpdateAvailable" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="lblUpdateAvailableTitle">New Update Available</h4>
</div>
<div class="modal-body">
<div style="margin-bottom: 20px;">
<div id="lblUpdateMessage" style="margin-bottom: 10px;"></div>
<a id="lnkUpdateDownload" href="#" target="_blank" style="font-weight: bold; font-size: 18px;">Download Now!</a>
<a id="lnkUpdateInstructions" href="#" target="_blank" style="font-weight: bold; font-size: 18px;">Update Instructions</a>
</div>
<div style="margin-bottom: 10px;">
<div style="font-weight: bold;">Update Version: <span id="lblUpdateVersion"></span></div>
<div>Current Version: <span id="lblCurrentVersion"></span></div>
</div>
<div style="margin-bottom: 10px;">
<a id="lnkUpdateChangeLog" href="#" target="_blank" style="font-weight: bold;">Read Change Logs</a>
</div>
<div style="margin-bottom: 10px;">
Note! It is highly recommended to Backup Settings before installing the update.
</div>
<div>
Note! You will have to refresh this web page manually after updating the DNS server so that new UI changes are loaded.
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalAddZone" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Add Zone</h4>
</div>
<div class="modal-body">
<div id="divAddZoneAlert"></div>
<div style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div class="form-group">
<label for="txtAddZone" class="col-sm-4 control-label">Zone</label>
<div class="col-sm-7">
<input id="txtAddZone" type="text" class="form-control" placeholder="example.com or 192.168.0.0/24 or 2001:db8::/64" maxlength="255">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Type</label>
<div class="col-sm-7">
<div class="radio">
<label>
<input type="radio" name="rdAddZoneType" id="rdAddZoneTypePrimary" value="Primary" checked>
Primary Zone (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneType" value="Secondary">
Secondary Zone
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneType" value="Stub">
Stub Zone
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneType" value="Forwarder">
Conditional Forwarder Zone
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneType" value="SecondaryForwarder">
Secondary Conditional Forwarder Zone
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneType" value="Catalog">
Catalog Zone
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneType" value="SecondaryCatalog">
Secondary Catalog Zone
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneType" value="SecondaryRoot">
Secondary ROOT Zone (<a href="https://datatracker.ietf.org/doc/rfc8806/" target="_blank">RFC 8806</a>)
</label>
</div>
</div>
</div>
<div class="form-group" id="divAddZoneCatalogZone">
<label class="col-sm-4 control-label">Catalog Zone</label>
<div class="col-sm-7">
<select id="optAddZoneCatalogZoneName" class="form-control"></select>
<div style="padding-top: 5px;">Select a Catalog zone to register as its member zone.</div>
</div>
</div>
<div class="form-group" id="divAddZoneInitializeForwarder">
<label class="col-sm-4 control-label">Conditional Forwarder</label>
<div class="col-sm-7">
<div class="checkbox" style="margin-bottom: 6px;">
<label>
<input id="chkAddZoneInitializeForwarder" type="checkbox"> Initialize Forwarder (FWD) Record
</label>
</div>
</div>
</div>
<div id="divAddZoneImportZoneFile" class="form-group">
<label for="fileAddZoneImportZone" class="col-sm-4 control-label">Import Zone File (Optional)</label>
<div class="col-sm-7">
<input type="file" class="form-control" id="fileAddZoneImportZone">
</div>
</div>
<div class="form-group" id="divAddZoneUseSoaSerialDateScheme">
<label class="col-sm-4 control-label">Zone Serial</label>
<div class="col-sm-7">
<div class="checkbox">
<label>
<input id="chkAddZoneUseSoaSerialDateScheme" type="checkbox"> Use SOA Serial Date Scheme
</label>
</div>
</div>
</div>
<div class="form-group" id="divAddZonePrimaryNameServerAddresses">
<label id="lblAddZonePrimaryNameServerAddresses" for="txtAddZonePrimaryNameServerAddresses" class="col-sm-4 control-label">Primary Name Server Addresses (Optional)</label>
<div class="col-sm-7">
<textarea id="txtAddZonePrimaryNameServerAddresses" class="form-control" rows="4" spellcheck="false" placeholder="192.168.1.1
2001:db8::
ns1.example.com (192.168.1.1)
ns1.example.com ([2001:db8::])
"></textarea>
<div id="divAddZonePrimaryNameServerAddressesInfo" style="padding-top: 5px;">Enter the primary name server addresses to sync the zone from. When unspecified, the SOA Primary Name Server will be resolved and used.</div>
</div>
</div>
<div class="form-group" id="divAddZoneZoneTransferProtocol">
<label class="col-sm-4 control-label">Zone Transfer Protocol</label>
<div class="col-sm-7">
<div class="radio">
<label>
<input type="radio" name="rdAddZoneZoneTransferProtocol" id="rdAddZoneZoneTransferProtocolTcp" value="Tcp" checked>
XFR-over-TCP (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneZoneTransferProtocol" value="Tls">
XFR-over-TLS
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneZoneTransferProtocol" value="Quic">
XFR-over-QUIC
</label>
</div>
</div>
</div>
<div class="form-group" id="divAddZoneTsigKeyName">
<label for="optAddZoneTsigKeyName" class="col-sm-4 control-label">TSIG Key Name (Optional)</label>
<div class="col-sm-7">
<select id="optAddZoneTsigKeyName" class="form-control"></select>
</div>
</div>
<div class="form-group" id="divAddZoneValidateZone">
<label class="col-sm-4 control-label">Zone Validation</label>
<div class="col-sm-7">
<div class="checkbox">
<label>
<input id="chkAddZoneValidateZone" type="checkbox"> Use <a href="https://datatracker.ietf.org/doc/rfc8976/" target="_blank">ZONEMD</a> to Validate Zone
</label>
<div style="padding-top: 5px; padding-left: 20px;">When enabled, the secondary zone will be validated using the ZONEMD record after every zone transfer. The zone will get disabled if the validation fails. The zone must be DNSSEC signed for the validation to work.</div>
</div>
</div>
</div>
<div class="form-group" id="divAddZoneForwarderProtocol">
<label class="col-sm-4 control-label">Protocol</label>
<div class="col-sm-7">
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProtocol" id="rdAddZoneForwarderProtocolUdp" value="Udp" checked>
DNS-over-UDP (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProtocol" value="Tcp">
DNS-over-TCP
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProtocol" value="Tls">
DNS-over-TLS
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProtocol" value="Https">
DNS-over-HTTPS
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProtocol" value="Quic">
DNS-over-QUIC
</label>
</div>
</div>
</div>
<div class="form-group" id="divAddZoneForwarder">
<label for="txtAddZoneForwarder" class="col-sm-4 control-label">Forwarder</label>
<div class="col-sm-7">
<div class="checkbox">
<label>
<input id="chkAddZoneForwarderThisServer" type="checkbox" onclick="updateAddZoneFormForwarderThisServer();"> Use "This Server"
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px; padding-bottom: 10px;">
When using "This Server", if a record does not exists in the zone then the request is forwarded to the DNS server's resolver internally. This allows you to override any record for the forwarded domain name or control its DNSSEC validation.
</div>
<input id="txtAddZoneForwarder" type="text" class="form-control" placeholder="8.8.8.8">
<div style="padding-top: 5px;">Enter a forwarder server address above. You can add more forwarders by adding FWD records after the zone is added.</div>
</div>
</div>
<div class="form-group" id="divAddZoneForwarderDnssecValidation">
<label class="col-sm-4 control-label">DNSSEC</label>
<div class="col-sm-7">
<div class="checkbox" style="margin-bottom: 6px;">
<label>
<input id="chkAddZoneForwarderDnssecValidation" type="checkbox"> Enable DNSSEC Validation
</label>
</div>
</div>
</div>
<div id="divAddZoneForwarderProxy">
<div class="form-group">
<label class="col-sm-4 control-label">Network Proxy</label>
<div class="col-sm-7">
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProxyType" value="NoProxy">
No Proxy
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProxyType" id="rdAddZoneForwarderProxyTypeDefaultProxy" value="DefaultProxy" checked>
Default Proxy (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProxyType" value="Http">
HTTP Proxy
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddZoneForwarderProxyType" value="Socks5">
SOCKS5 Proxy
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="txtAddZoneForwarderProxyAddress" class="col-sm-4 control-label">Proxy Server Address</label>
<div class="col-sm-7">
<input id="txtAddZoneForwarderProxyAddress" type="text" class="form-control" placeholder="domain name or IP address">
</div>
</div>
<div class="form-group">
<label for="txtAddZoneForwarderProxyPort" class="col-sm-4 control-label">Proxy Server Port</label>
<div class="col-sm-7">
<input id="txtAddZoneForwarderProxyPort" type="number" class="form-control" placeholder="port" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddZoneForwarderProxyUsername" class="col-sm-4 control-label">Proxy Server Username</label>
<div class="col-sm-7">
<input id="txtAddZoneForwarderProxyUsername" type="text" class="form-control" placeholder="username">
</div>
</div>
<div class="form-group">
<label for="txtAddZoneForwarderProxyPassword" class="col-sm-4 control-label">Proxy Server Password</label>
<div class="col-sm-7">
<input id="txtAddZoneForwarderProxyPassword" type="password" class="form-control" placeholder="password">
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="pull-left" style="text-align: left;">
<a href="https://blog.technitium.com/2022/06/how-to-self-host-your-own-domain-name.html" target="_blank">Help: How To Self Host Your Own Domain Name</a>
</div>
<div class="pull-right">
<button id="btnAddZone" type="submit" class="btn btn-primary" data-loading-text="Adding..." onclick="addZone(); return false;">Add</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</form>
</div>
<div id="modalAddEditRecord" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 id="titleAddEditRecord" class="modal-title">Add Edit Record</h4>
</div>
<div class="modal-body">
<div id="divAddEditRecordAlert"></div>
<div style="max-height: 500px; overflow-y: auto; padding: 0 15px; overflow-x: hidden;">
<div class="form-group">
<label for="txtAddEditRecordName" class="col-sm-4 control-label">Name</label>
<div class="col-sm-7">
<input id="txtAddEditRecordName" type="text" class="form-control" placeholder="@">
<div style="margin-top: 6px; font-weight: 700;">.<span id="lblAddEditRecordZoneName">example.com</span></div>
</div>
</div>
<div class="form-group">
<label for="optAddEditRecordType" class="col-sm-4 control-label">Type</label>
<div class="col-sm-7">
<select id="optAddEditRecordType" class="form-control" onchange="modifyAddRecordFormByType(true);" style="width: auto;">
<option>A</option>
<option>NS</option>
<option id="optEditRecordTypeSoa">SOA</option>
<option>CNAME</option>
<option>PTR</option>
<option>MX</option>
<option>TXT</option>
<option>RP</option>
<option>AAAA</option>
<option>SRV</option>
<option>NAPTR</option>
<option>DNAME</option>
<option id="optAddEditRecordTypeDs">DS</option>
<option id="optAddEditRecordTypeSshfp">SSHFP</option>
<option id="optAddEditRecordTypeTlsa">TLSA</option>
<option>SVCB</option>
<option>HTTPS</option>
<option>URI</option>
<option>CAA</option>
<option id="optAddEditRecordTypeAName">ANAME</option>
<option id="optAddEditRecordTypeFwd">FWD</option>
<option id="optAddEditRecordTypeApp">APP</option>
<option>Unknown</option>
</select>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordTtl" class="col-sm-4 control-label">TTL</label>
<div class="col-sm-7">
<input id="txtAddEditRecordTtl" type="text" class="form-control" placeholder="3600" style="width: 100px; display: inline;">
<span id="spanAddEditRecordTtlUnit">seconds (default 3600/1h)</span>
</div>
</div>
<div id="divAddEditRecordData">
<div id="divAddEditRecordDataUnknownType" class="form-group">
<label for="txtAddEditRecordDataUnknownType" class="col-sm-4 control-label">RR Type</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataUnknownType" type="text" class="form-control" placeholder="type" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label id="lblAddEditRecordDataValue" for="txtAddEditRecordDataValue" class="col-sm-4 control-label">Value</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataValue" type="text" class="form-control">
</div>
</div>
<div id="divAddEditRecordDataPtr" class="form-group">
<div class="col-sm-offset-4 col-sm-7">
<div class="checkbox">
<label>
<input id="chkAddEditRecordDataPtr" type="checkbox"> <span id="chkAddEditRecordDataPtrLabel">Add reverse (PTR) record</span>
</label>
</div>
<div class="checkbox">
<label>
<input id="chkAddEditRecordDataCreatePtrZone" type="checkbox"> Create reverse zone for PTR record
</label>
</div>
</div>
</div>
</div>
<div id="divAddEditRecordDataNs" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataNsNameServer" class="col-sm-4 control-label">Name Server</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataNsNameServer" type="text" class="form-control">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataNsGlue" class="col-sm-4 control-label">Glue Addresses</label>
<div class="col-sm-7">
<textarea id="txtAddEditRecordDataNsGlue" class="form-control" rows="3" spellcheck="false" placeholder="192.168.1.1
2001:db8::"></textarea>
</div>
</div>
</div>
<div id="divEditRecordDataSoa" style="display: none;">
<div class="form-group">
<label for="txtEditRecordDataSoaPrimaryNameServer" class="col-sm-4 control-label">Primary Name Server</label>
<div class="col-sm-7">
<input id="txtEditRecordDataSoaPrimaryNameServer" type="text" class="form-control">
</div>
</div>
<div class="form-group">
<label for="txtEditRecordDataSoaResponsiblePerson" class="col-sm-4 control-label">Responsible Person</label>
<div class="col-sm-7">
<input id="txtEditRecordDataSoaResponsiblePerson" type="text" class="form-control" placeholder="email address">
</div>
</div>
<div class="form-group">
<label for="txtEditRecordDataSoaSerial" class="col-sm-4 control-label">Serial</label>
<div class="col-sm-7">
<input id="txtEditRecordDataSoaSerial" type="number" class="form-control" style="width: 150px;">
</div>
<div id="divEditRecordDataSoaUseSerialDateScheme" class="col-sm-offset-4 col-sm-7">
<div class="checkbox">
<label>
<input id="chkEditRecordDataSoaUseSerialDateScheme" type="checkbox"> Use Serial Date Scheme
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="txtEditRecordDataSoaRefresh" class="col-sm-4 control-label">Refresh</label>
<div class="col-sm-7">
<input id="txtEditRecordDataSoaRefresh" type="text" class="form-control" style="width: 100px; display: inline;">
<span>seconds</span>
</div>
</div>
<div class="form-group">
<label for="txtEditRecordDataSoaRetry" class="col-sm-4 control-label">Retry</label>
<div class="col-sm-7">
<input id="txtEditRecordDataSoaRetry" type="text" class="form-control" style="width: 100px; display: inline;">
<span>seconds</span>
</div>
</div>
<div class="form-group">
<label for="txtEditRecordDataSoaExpire" class="col-sm-4 control-label">Expire</label>
<div class="col-sm-7">
<input id="txtEditRecordDataSoaExpire" type="text" class="form-control" style="width: 100px; display: inline;">
<span>seconds</span>
</div>
</div>
<div class="form-group">
<label for="txtEditRecordDataSoaMinimum" class="col-sm-4 control-label">Minimum</label>
<div class="col-sm-7">
<input id="txtEditRecordDataSoaMinimum" type="text" class="form-control" style="width: 100px; display: inline;">
<span>seconds</span>
</div>
</div>
</div>
<div id="divAddEditRecordDataMx" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataMxPreference" class="col-sm-4 control-label">Preference</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataMxPreference" type="number" class="form-control" placeholder="1" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataMxExchange" class="col-sm-4 control-label">Exchange</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataMxExchange" type="text" class="form-control">
</div>
</div>
</div>
<div id="divAddEditRecordDataTxt" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataTxt" class="col-sm-4 control-label">Text Data</label>
<div class="col-sm-7">
<textarea id="txtAddEditRecordDataTxt" class="form-control" rows="5" spellcheck="false"></textarea>
<div class="checkbox">
<label>
<input id="chkAddEditRecordDataTxtSplitText" type="checkbox"> Use New Line To Split Text Into Multiple Character-Strings
</label>
</div>
</div>
</div>
</div>
<div id="divAddEditRecordDataRp" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataRpMailbox" class="col-sm-4 control-label">Mailbox</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataRpMailbox" type="text" class="form-control" placeholder="email address">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataRpTxtDomain" class="col-sm-4 control-label">TXT Domain</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataRpTxtDomain" type="text" class="form-control" placeholder=".">
</div>
</div>
</div>
<div id="divAddEditRecordDataSrv" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataSrvPriority" class="col-sm-4 control-label">Priority</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataSrvPriority" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataSrvWeight" class="col-sm-4 control-label">Weight</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataSrvWeight" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataSrvPort" class="col-sm-4 control-label">Port</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataSrvPort" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataSrvTarget" class="col-sm-4 control-label">Target</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataSrvTarget">
</div>
</div>
</div>
<div id="divAddEditRecordDataNaptr" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataNaptrOrder" class="col-sm-4 control-label">Order</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataNaptrOrder" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataNaptrPreference" class="col-sm-4 control-label">Preference</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataNaptrPreference" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataNaptrFlags" class="col-sm-4 control-label">Flags</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataNaptrFlags">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataNaptrServices" class="col-sm-4 control-label">Services</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataNaptrServices">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataNaptrRegExp" class="col-sm-4 control-label">Regular Expression</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataNaptrRegExp">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataNaptrReplacement" class="col-sm-4 control-label">Replacement</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataNaptrReplacement">
</div>
</div>
</div>
<div id="divAddEditRecordDataDs" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataDsKeyTag" class="col-sm-4 control-label">Key Tag</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataDsKeyTag" placeholder="key tag" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="optAddEditRecordDataDsAlgorithm" class="col-sm-4 control-label">DNSSEC Algorithm</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataDsAlgorithm" class="form-control">
<option value="RSAMD5">RSAMD5 (1)</option>
<option value="RSASHA1">RSASHA1 (5)</option>
<option value="RSASHA256">RSASHA256 (8)</option>
<option value="RSASHA512">RSASHA512 (10)</option>
<option value="ECDSAP256SHA256">ECDSAP256SHA256 (13)</option>
<option value="ECDSAP384SHA384">ECDSAP384SHA384 (14)</option>
<option value="ED25519">ED25519 (15)</option>
<option value="ED448">ED448 (16)</option>
</select>
</div>
</div>
<div class="form-group">
<label for="optAddEditRecordDataDsDigestType" class="col-sm-4 control-label">Digest Type</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataDsDigestType" class="form-control">
<option value="SHA1">SHA1 (1)</option>
<option value="SHA256">SHA256 (2)</option>
<option value="SHA384">SHA384 (4)</option>
</select>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataDsDigest" class="col-sm-4 control-label">Digest</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataDsDigest" placeholder="hash string">
</div>
</div>
</div>
<div id="divAddEditRecordDataSshfp" style="display: none;">
<div class="form-group">
<label for="optAddEditRecordDataSshfpAlgorithm" class="col-sm-4 control-label">Algorithm</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataSshfpAlgorithm" class="form-control">
<option>RSA</option>
<option>DSA</option>
<option>ECDSA</option>
<option>Ed25519</option>
<option>Ed448</option>
</select>
</div>
</div>
<div class="form-group">
<label for="optAddEditRecordDataSshfpFingerprintType" class="col-sm-4 control-label">Fingerprint Type</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataSshfpFingerprintType" class="form-control">
<option>SHA1</option>
<option>SHA256</option>
</select>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataSshfpFingerprint" class="col-sm-4 control-label">Fingerprint</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataSshfpFingerprint" placeholder="hash string">
</div>
</div>
</div>
<div id="divAddEditRecordDataTlsa" style="display: none;">
<div class="form-group">
<label for="optAddEditRecordDataTlsaCertificateUsage" class="col-sm-4 control-label">Certificate Usage</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataTlsaCertificateUsage" class="form-control">
<option>PKIX-TA</option>
<option>PKIX-EE</option>
<option>DANE-TA</option>
<option>DANE-EE</option>
</select>
</div>
</div>
<div class="form-group">
<label for="optAddEditRecordDataTlsaSelector" class="col-sm-4 control-label">Selector</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataTlsaSelector" class="form-control">
<option>Cert</option>
<option>SPKI</option>
</select>
</div>
</div>
<div class="form-group">
<label for="optAddEditRecordDataTlsaMatchingType" class="col-sm-4 control-label">Matching Type</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataTlsaMatchingType" class="form-control">
<option>Full</option>
<option>SHA2-256</option>
<option>SHA2-512</option>
</select>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataTlsaCertificateAssociationData" class="col-sm-4 control-label">Certificate Association Data</label>
<div class="col-sm-7">
<textarea id="txtAddEditRecordDataTlsaCertificateAssociationData" class="form-control" rows="6" spellcheck="false" placeholder="5F95253A20A0957648DEBAAEB032F7C5720CD4F0DCF928840C55650687921DAE
OR
-----BEGIN CERTIFICATE-----
MII...
-----END CERTIFICATE-----
"></textarea>
<div style="padding-top: 5px;">Enter either a hash value that you have independently generated, OR enter the certificate in PEM format to automatically generate the association data based on the Selector and Matching Type values.</div>
</div>
</div>
</div>
<div id="divAddEditRecordDataSvcb" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataSvcbPriority" class="col-sm-4 control-label">Priority</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataSvcbPriority" style="width: 100px; display: inline;">
<span>(set 0 for alias mode)</span>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataSvcbTargetName" class="col-sm-4 control-label">Target Name</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataSvcbTargetName">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Params</label>
<div class="col-sm-7">
<table class="table" style="margin-bottom: 0px;">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
<th style="width: 94px;">
<button type="button" class="btn btn-default" style="padding: 0px 25px;" onclick="addSvcbRecordParamEditRow('', '');">Add</button>
</th>
</tr>
</thead>
<tbody id="tableAddEditRecordDataSvcbParams">
</tbody>
</table>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Automatic Hints</label>
<div class="col-sm-7">
<div class="checkbox">
<label>
<input id="chkAddEditRecordDataSvcbAutoIpv4Hint" type="checkbox"> Use Automatic IPv4 Hint
</label>
</div>
</div>
<div class="col-sm-offset-4 col-sm-7">
<div class="checkbox">
<label>
<input id="chkAddEditRecordDataSvcbAutoIpv6Hint" type="checkbox"> Use Automatic IPv6 Hint
</label>
</div>
</div>
</div>
</div>
<div id="divAddEditRecordDataUri" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataUriPriority" class="col-sm-4 control-label">Priority</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataUriPriority" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataUriWeight" class="col-sm-4 control-label">Weight</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataUriWeight" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataUri" class="col-sm-4 control-label">URI</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataUri">
</div>
</div>
</div>
<div id="divAddEditRecordDataCaa" style="display: none;">
<div class="form-group">
<label for="txtAddEditRecordDataCaaFlags" class="col-sm-4 control-label">Flags</label>
<div class="col-sm-7">
<input type="number" class="form-control" id="txtAddEditRecordDataCaaFlags" placeholder="0" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataCaaTag" class="col-sm-4 control-label">Tag</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataCaaTag" placeholder="issue" style="width: 150px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataCaaValue" class="col-sm-4 control-label">Authority</label>
<div class="col-sm-7">
<input type="text" class="form-control" id="txtAddEditRecordDataCaaValue">
</div>
</div>
</div>
<div id="divAddEditRecordDataForwarder" style="display: none;">
<div class="form-group">
<label class="col-sm-4 control-label">Protocol</label>
<div class="col-sm-7">
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProtocol" id="rdAddEditRecordDataForwarderProtocolUdp" value="Udp" checked>
DNS-over-UDP (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProtocol" id="rdAddEditRecordDataForwarderProtocolTcp" value="Tcp">
DNS-over-TCP
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProtocol" id="rdAddEditRecordDataForwarderProtocolTls" value="Tls">
DNS-over-TLS
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProtocol" id="rdAddEditRecordDataForwarderProtocolHttps" value="Https">
DNS-over-HTTPS
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProtocol" id="rdAddEditRecordDataForwarderProtocolQuic" value="Quic">
DNS-over-QUIC
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataForwarder" class="col-sm-4 control-label">Forwarder</label>
<div class="col-sm-7">
<div class="checkbox">
<label>
<input id="chkAddEditRecordDataForwarderThisServer" type="checkbox" onclick="updateAddEditFormForwarderThisServer();"> Use "This Server"
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px; padding-bottom: 10px;">
When using "This Server", if a record does not exists in the zone then the request is forwarded to the DNS server's resolver internally. This allows you to override any record for the forwarded domain name or control its DNSSEC validation.
</div>
<input id="txtAddEditRecordDataForwarder" type="text" class="form-control" placeholder="8.8.8.8">
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Priority</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataForwarderPriority" type="number" class="form-control" placeholder="0" style="width: 100px; display: inline;">
<span>(valid range 0-255; default 0)</span>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
Forwarders are sorted by priority value i.e. forwarder with low priority value will be queried before trying for forwarder with high priority value. Forwarders with the same priority value will be queried concurrently.
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">DNSSEC</label>
<div class="col-sm-7">
<div class="checkbox" style="margin-bottom: 6px;">
<label>
<input id="chkAddEditRecordDataForwarderDnssecValidation" type="checkbox"> Enable DNSSEC Validation
</label>
</div>
</div>
</div>
<div id="divAddEditRecordDataForwarderProxy">
<div class="form-group">
<label class="col-sm-4 control-label">Network Proxy</label>
<div class="col-sm-7">
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProxyType" id="rdAddEditRecordDataForwarderProxyTypeNoProxy" value="NoProxy">
No Proxy
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProxyType" id="rdAddEditRecordDataForwarderProxyTypeDefaultProxy" value="DefaultProxy" checked>
Default Proxy (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProxyType" id="rdAddEditRecordDataForwarderProxyTypeHttp" value="Http">
HTTP Proxy
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdAddEditRecordDataForwarderProxyType" id="rdAddEditRecordDataForwarderProxyTypeSocks5" value="Socks5">
SOCKS5 Proxy
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataForwarderProxyAddress" class="col-sm-4 control-label">Proxy Server Address</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataForwarderProxyAddress" type="text" class="form-control" placeholder="domain name or IP address">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataForwarderProxyPort" class="col-sm-4 control-label">Proxy Server Port</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataForwarderProxyPort" type="number" class="form-control" placeholder="port" style="width: 100px;">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataForwarderProxyUsername" class="col-sm-4 control-label">Proxy Server Username</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataForwarderProxyUsername" type="text" class="form-control" placeholder="username">
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataForwarderProxyPassword" class="col-sm-4 control-label">Proxy Server Password</label>
<div class="col-sm-7">
<input id="txtAddEditRecordDataForwarderProxyPassword" type="password" class="form-control" placeholder="password">
</div>
</div>
</div>
</div>
<div id="divAddEditRecordDataApplication" style="display: none;">
<div class="form-group">
<label for="optAddEditRecordDataAppName" class="col-sm-4 control-label">App Name</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataAppName" class="form-control"></select>
</div>
</div>
<div class="form-group">
<label for="optAddEditRecordDataClassPath" class="col-sm-4 control-label">Class Path</label>
<div class="col-sm-7">
<select id="optAddEditRecordDataClassPath" class="form-control"></select>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordDataData" class="col-sm-4 control-label">Record Data (if any)</label>
<div class="col-sm-7">
<textarea id="txtAddEditRecordDataData" class="form-control" rows="6" spellcheck="false"></textarea>
</div>
</div>
</div>
<div id="divAddEditRecordOverwrite" class="form-group">
<div class="col-sm-offset-4 col-sm-7">
<div class="checkbox">
<label>
<input id="chkAddEditRecordOverwrite" type="checkbox"> Overwrite existing records
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="txtAddEditRecordComments" class="col-sm-4 control-label">Comments</label>
<div class="col-sm-7">
<textarea id="txtAddEditRecordComments" class="form-control" rows="3" maxlength="255"></textarea>
</div>
</div>
<div class="form-group" id="divAddEditRecordExpiryTtl">
<label for="txtAddEditRecordExpiryTtl" class="col-sm-4 control-label">Expiry TTL</label>
<div class="col-sm-7">
<input id="txtAddEditRecordExpiryTtl" type="text" class="form-control" placeholder="0" style="width: 100px; display: inline;">
<span>seconds (set 0 to disable)</span>
</div>
<div class="col-sm-offset-4 col-sm-7" style="padding-top: 5px;">Set to automatically delete the record when the value in seconds elapses since the records last modified time.</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" id="btnAddEditRecord" data-loading-text="Saving...">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalImportZone" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Import - <span id="lblImportZoneName"></span></h4>
</div>
<div class="modal-body">
<div id="divImportZoneAlert"></div>
<div class="form-horizontal">
<div class="form-group">
<label class="col-sm-4 control-label">Import Options</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input id="chkImportZoneOverwrite" type="checkbox"> Overwrite existing records
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to overwrite existing records for the record types being imported.</div>
</div>
<div class="checkbox">
<label>
<input id="chkImportZoneOverwriteSoaSerial" type="checkbox"> Overwrite SOA Serial
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enable this option to overwrite existing SOA record serial with the imported SOA record serial.</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Import Type</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdImportZoneType" id="rdImportZoneTypeFile" value="File">
Zone File
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdImportZoneType" id="rdImportZoneTypeText" value="Text">
Text Editor
</label>
</div>
</div>
</div>
<div id="divImportZoneFile" class="form-group">
<label for="fileImportZone" class="col-sm-4 control-label">Zone File</label>
<div class="col-sm-6">
<input type="file" class="form-control" id="fileImportZone">
</div>
</div>
</div>
<div id="divImportZoneTextEditor">
<div class="form-group">
<label for="txtImportZoneText" class="control-label">Text Editor</label>
<textarea id="txtImportZoneText" class="form-control" rows="15" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter the records to be imported above in standard zone file format.</div>
</div>
</div>
<p>Note! The <code>$ORIGIN</code> and <code>$TTL</code> values will be automatically set if not specified.</p>
<p>Warning! Overwrite SOA serial option when used to set a lower SOA serial value than the current SOA serial will cause secondary zones to fail to sync.</p>
</div>
<div class="modal-footer">
<button id="btnImportZone" type="submit" class="btn btn-primary" data-loading-text="Importing..." onclick="importZone(); return false;">Import</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalCloneZone" class="modal fade" tabindex="-1" role="dialog">
<form>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Clone Zone - <span id="lblCloneZoneZoneName"></span></h4>
</div>
<div class="modal-body">
<div id="divCloneZoneAlert"></div>
<div class="form-horizontal">
<div class="form-group">
<label for="txtCloneZoneSourceZoneName" class="col-sm-4 control-label">Source Zone</label>
<div class="col-sm-7">
<input id="txtCloneZoneSourceZoneName" type="text" class="form-control" disabled>
</div>
</div>
<div class="form-group">
<label for="txtCloneZoneZoneName" class="col-sm-4 control-label">New Zone</label>
<div class="col-sm-7">
<input id="txtCloneZoneZoneName" type="text" class="form-control" placeholder="example.com">
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnCloneZone" type="submit" class="btn btn-primary" data-loading-text="Cloning..." onclick="cloneZone(this); return false;">Clone Zone</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalConvertZone" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Convert Zone - <span id="lblConvertZoneZoneName"></span></h4>
</div>
<div class="modal-body">
<div id="divConvertZoneAlert"></div>
<div class="form-horizontal">
<div class="form-group">
<label class="col-sm-4 control-label">Convert To</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdConvertZoneToType" id="rdConvertZoneToTypePrimary" value="Primary" />
Primary Zone
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdConvertZoneToType" id="rdConvertZoneToTypeForwarder" value="Forwarder" />
Conditional Forwarder Zone
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdConvertZoneToType" id="rdConvertZoneToTypeCatalog" value="Catalog" />
Catalog Zone
</label>
</div>
</div>
</div>
<p>
<b>Note!</b> The conversion process may take a while depending on the number of records the zone has. When converting a Secondary Catalog zone to a Catalog zone, all member zones too will be converted to either Primary or Conditional Forwarder zone depending on their existing zone type. Please be patient till the conversion process completes.
</p>
</div>
</div>
<div class="modal-footer">
<button id="btnConvertZone" type="submit" class="btn btn-warning" data-loading-text="Converting..." onclick="convertZone(this); return false;">Convert Zone</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalZoneOptions" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Zone Options - <span id="lblZoneOptionsZoneName"></span></h4>
</div>
<div class="modal-body">
<div id="divZoneOptionsAlert"></div>
<div id="divZoneOptionsLoader" style="height: 500px;"></div>
<div id="divZoneOptions" style="max-height: 500px;">
<div>
<ul class="nav nav-tabs" role="tablist">
<li id="tabListZoneOptionsGeneral" role="presentation" class="active"><a href="#tabPaneZoneOptionsGeneral" aria-controls="tabPaneZoneOptionsGeneral" role="tab" data-toggle="tab">General</a></li>
<li id="tabListZoneOptionsQueryAccess" role="presentation"><a href="#tabPaneZoneOptionsQueryAccess" aria-controls="tabPaneZoneOptionsQueryAccess" role="tab" data-toggle="tab">Query Access</a></li>
<li id="tabListZoneOptionsZoneTranfer" role="presentation"><a href="#tabPaneZoneOptionsZoneTransfer" aria-controls="tabPaneZoneOptionsZoneTransfer" role="tab" data-toggle="tab">Zone Transfer</a></li>
<li id="tabListZoneOptionsNotify" role="presentation"><a href="#tabPaneZoneOptionsNotify" aria-controls="tabPaneZoneOptionsNotify" role="tab" data-toggle="tab">Notify</a></li>
<li id="tabListZoneOptionsUpdate" role="presentation"><a href="#tabPaneZoneOptionsUpdate" aria-controls="tabPaneZoneOptionsUpdate" role="tab" data-toggle="tab">Dynamic Updates (RFC 2136)</a></li>
</ul>
<div class="tab-content">
<div id="tabPaneZoneOptionsGeneral" role="tabpanel" class="tab-pane active" style="padding: 0 6px 0 0; max-height: 450px; margin: 10px 0 0 0; overflow-y: auto; overflow-x: hidden;">
<div class="well well-sm form-horizontal" id="divZoneOptionsGeneralCatalogZone">
<div class="form-group">
<label for="optZoneOptionsCatalogZoneName" class="col-sm-4 control-label">Catalog Zone</label>
<div class="col-sm-7">
<select id="optZoneOptionsCatalogZoneName" class="form-control"></select>
<div style="padding-top: 5px;">Select a Catalog zone to register as its member zone.</div>
</div>
</div>
<div id="divZoneOptionsCatalogOverrideOptions" class="form-group">
<label class="col-sm-4 control-label">Override Options</label>
<div class="col-sm-7">
<div class="checkbox">
<label>
<input id="chkZoneOptionsCatalogOverrideQueryAccess" type="checkbox"> Override Query Access Option
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enable to override Query Access option in the Catalog zone.</div>
</div>
<div class="checkbox" id="divZoneOptionsCatalogOverrideZoneTransfer">
<label>
<input id="chkZoneOptionsCatalogOverrideZoneTransfer" type="checkbox"> Override Zone Transfer Option
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enable to override Zone Transfer option in the Catalog zone.</div>
</div>
<div class="checkbox" id="divZoneOptionsCatalogOverrideNotify">
<label>
<input id="chkZoneOptionsCatalogOverrideNotify" type="checkbox"> Override Notify Option
</label>
<div style="padding-top: 5px; padding-left: 20px;">Enable to override Notify option in the Catalog zone.</div>
</div>
</div>
</div>
<div id="divZoneOptionsCatalogNotifyFailedNameServers" class="form-group" style="display: none;">
<label class="col-sm-4 control-label">Notify Failed Name Servers</label>
<div class="col-sm-7">
<span id="lblZoneOptionsCatalogNotifyFailedNameServers" class="form-control" style="height: auto;"></span>
</div>
</div>
<div>Note! When a zone becomes a member of a Catalog zone, all of the Catalog zone's Options are inherited unless they are explicitly overridden using the Override Options.</div>
</div>
<div class="well well-sm form-horizontal" id="divZoneOptionsGeneralPrimaryServer">
<div class="form-group">
<label id="lblZoneOptionsPrimaryNameServerAddresses" for="txtZoneOptionsPrimaryNameServerAddresses" class="col-sm-4 control-label">Primary Name Server Addresses (Optional)</label>
<div class="col-sm-7">
<textarea id="txtZoneOptionsPrimaryNameServerAddresses" class="form-control" rows="4" spellcheck="false" placeholder="192.168.1.1
2001:db8::
ns1.example.com (192.168.1.1)
ns1.example.com ([2001:db8::])
"></textarea>
<div id="divZoneOptionsPrimaryNameServerAddressesInfo" style="padding-top: 5px;">Enter the primary name server addresses to sync the zone from. When unspecified, the SOA Primary Name Server will be resolved and used.</div>
</div>
</div>
<div class="form-group" id="divZoneOptionsPrimaryServerZoneTransferProtocol">
<label class="col-sm-4 control-label">Zone Transfer Protocol</label>
<div class="col-sm-7">
<div class="radio">
<label>
<input type="radio" name="rdPrimaryZoneTransferProtocol" id="rdPrimaryZoneTransferProtocolTcp" value="Tcp" checked>
XFR-over-TCP (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdPrimaryZoneTransferProtocol" id="rdPrimaryZoneTransferProtocolTls" value="Tls">
XFR-over-TLS
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdPrimaryZoneTransferProtocol" id="rdPrimaryZoneTransferProtocolQuic" value="Quic">
XFR-over-QUIC
</label>
</div>
</div>
</div>
<div class="form-group" id="divZoneOptionsPrimaryServerZoneTransferTsigKeyName">
<label for="optZoneOptionsPrimaryZoneTransferTsigKeyName" class="col-sm-4 control-label">TSIG Key Name (Optional)</label>
<div class="col-sm-7">
<select id="optZoneOptionsPrimaryZoneTransferTsigKeyName" class="form-control"></select>
</div>
</div>
<div class="form-group" id="divZoneOptionsPrimaryServerValidateZone">
<label class="col-sm-4 control-label">Zone Validation</label>
<div class="col-sm-7">
<div class="checkbox">
<label>
<input id="chkZoneOptionsValidateZone" type="checkbox"> Use <a href="https://datatracker.ietf.org/doc/rfc8976/" target="_blank">ZONEMD</a> to Validate Zone
</label>
<div style="padding-top: 5px; padding-left: 20px;">When enabled, the secondary zone will be validated using the ZONEMD record after every zone transfer. The zone will get disabled if the validation fails. The zone must be DNSSEC signed for the validation to work.</div>
</div>
</div>
</div>
</div>
</div>
<div id="tabPaneZoneOptionsQueryAccess" role="tabpanel" class="tab-pane" style="padding: 0 6px 0 0; max-height: 450px; margin: 10px 0 0 0; overflow-y: auto; overflow-x: hidden;">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Query Access</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdQueryAccess" id="rdQueryAccessDeny" value="Deny">
Deny
</label>
<div style="padding-top: 5px; padding-left: 20px;">Denies everyone from querying the zone by refusing the request.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdQueryAccess" id="rdQueryAccessAllow" value="Allow">
Allow (default)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows everyone to query the zone.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdQueryAccess" id="rdQueryAccessAllowOnlyPrivateNetworks" value="AllowOnlyPrivateNetworks">
Allow Only Private Networks
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows only private networks to query the zone. Any request from a public network will be refused.</div>
</div>
<div class="radio" id="divQueryAccessAllowOnlyZoneNameServers">
<label>
<input type="radio" name="rdQueryAccess" id="rdQueryAccessAllowOnlyZoneNameServers" value="AllowOnlyZoneNameServers">
Allow Only Name Servers In Zone
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows only the name servers with an NS record in the zone to query the zone.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdQueryAccess" id="rdQueryAccessUseSpecifiedNetworkACL" value="UseSpecifiedNetworkACL">
Use Specified Network Access Control List (ACL)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Uses the specified network access control list to allow/deny to query the zone.</div>
</div>
<div class="radio" id="divQueryAccessAllowZoneNameServersAndUseSpecifiedNetworkACL">
<label>
<input type="radio" name="rdQueryAccess" id="rdQueryAccessAllowZoneNameServersAndUseSpecifiedNetworkACL" value="AllowZoneNameServersAndUseSpecifiedNetworkACL">
Allow Zone Name Servers And Use Specified Network Access Control List (ACL)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows zone's name servers and uses specified network access control list to allow/deny to query the zone.</div>
</div>
</div>
</div>
<div class="form-group">
<label for="txtQueryAccessNetworkACL" class="col-sm-3 control-label">Network Access Control List (ACL)</label>
<div class="col-sm-8">
<textarea id="txtQueryAccessNetworkACL" class="form-control" rows="5" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter IP addresses or network addresses one below another to allow access. Add <code>!</code> character at the start to deny access, e.g. <code>!192.168.10.0/24</code> will deny entire subnet. The ACL is processed in the same order its listed. If no networks match, the default policy is to deny all.</div>
</div>
</div>
<div>Note! The zone can always be queried from loopback IP addresses and internally by the DNS server irrespective of the Query Access configuration.</div>
</div>
</div>
<div id="tabPaneZoneOptionsZoneTransfer" role="tabpanel" class="tab-pane" style="padding: 0 6px 0 0; max-height: 450px; margin: 10px 0 0 0; overflow-y: auto; overflow-x: hidden;">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Zone Transfer</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdZoneTransfer" id="rdZoneTransferDeny" value="Deny">
Deny
</label>
<div style="padding-top: 5px; padding-left: 20px;">Denies everyone from performing a zone transfer.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdZoneTransfer" id="rdZoneTransferAllow" value="Allow">
Allow
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows everyone to perform a zone transfer.</div>
</div>
<div class="radio" id="divZoneTransferAllowOnlyZoneNameServers">
<label>
<input type="radio" name="rdZoneTransfer" id="rdZoneTransferAllowOnlyZoneNameServers" value="AllowOnlyZoneNameServers">
Allow Only Name Servers In Zone
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows only the name servers with an NS record in the zone to perform a zone transfer.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdZoneTransfer" id="rdZoneTransferUseSpecifiedNetworkACL" value="UseSpecifiedNetworkACL">
Use Specified Network Access Control List (ACL)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Uses the specified network access control list to allow/deny to perform a zone transfer.</div>
</div>
<div class="radio" id="divZoneTransferAllowZoneNameServersAndUseSpecifiedNetworkACL">
<label>
<input type="radio" name="rdZoneTransfer" id="rdZoneTransferAllowZoneNameServersAndUseSpecifiedNetworkACL" value="AllowZoneNameServersAndUseSpecifiedNetworkACL">
Allow Zone Name Servers And Use Specified Network Access Control List (ACL)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows zone's name servers and uses specified network access control list to allow/deny to perform a zone transfer.</div>
</div>
</div>
</div>
<div class="form-group">
<label for="txtZoneTransferNetworkACL" class="col-sm-3 control-label">Network Access Control List (ACL)</label>
<div class="col-sm-8">
<textarea id="txtZoneTransferNetworkACL" class="form-control" rows="5" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter IP addresses or network addresses one below another to allow access. Add <code>!</code> character at the start to deny access, e.g. <code>!192.168.10.0/24</code> will deny entire subnet. The ACL is processed in the same order its listed. If no networks match, the default policy is to deny all.</div>
</div>
</div>
<div>Note! Zone transfer should be allowed only for trusted name servers to sync their secondary zone.</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label for="txtZoneOptionsZoneTransferTsigKeyNames" class="col-sm-3 control-label">Zone Transfer TSIG Key Names</label>
<div class="col-sm-8">
<textarea id="txtZoneOptionsZoneTransferTsigKeyNames" class="form-control" rows="3" spellcheck="false"></textarea>
<label for="optZoneOptionsQuickTsigKeyNames" class="control-label">Quick Add</label>
<select id="optZoneOptionsQuickTsigKeyNames" class="form-control">
</select>
</div>
</div>
<div>Note! TSIG key names must be configured from the Settings before using them here. Entering one or more TSIG key names above will cause the DNS server to authenticate all zone transfer requests. A secondary zone must be configured with one of the above keys to be able to perform a zone transfer.</div>
</div>
</div>
<div id="tabPaneZoneOptionsNotify" role="tabpanel" class="tab-pane" style="padding: 0 6px 0 0; max-height: 450px; margin: 10px 0 0 0; overflow-y: auto; overflow-x: hidden; ">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Notify</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdZoneNotify" id="rdZoneNotifyNone" value="None">
None
</label>
<div style="padding-top: 5px; padding-left: 20px;">Does not notify any name server when the zone is updated.</div>
</div>
<div class="radio" id="divZoneNotifyZoneNameServers">
<label>
<input type="radio" name="rdZoneNotify" id="rdZoneNotifyZoneNameServers" value="ZoneNameServers">
Name Servers In Zone
</label>
<div style="padding-top: 5px; padding-left: 20px;">Notifies only the name servers with an NS record in the zone when the zone is updated.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdZoneNotify" id="rdZoneNotifySpecifiedNameServers" value="SpecifiedNameServers">
Specified Name Servers
</label>
<div style="padding-top: 5px; padding-left: 20px;">Notifies only the specified name servers when the zone is updated.</div>
</div>
<div class="radio" id="divZoneNotifyBothZoneAndSpecifiedNameServers">
<label>
<input type="radio" name="rdZoneNotify" id="rdZoneNotifyBothZoneAndSpecifiedNameServers" value="BothZoneAndSpecifiedNameServers">
Both Zone Name Servers And Specified Name Servers
</label>
<div style="padding-top: 5px; padding-left: 20px;">Notifies both the zone's name servers and the specified name servers when the zone is updated.</div>
</div>
<div class="radio" id="divZoneNotifySeparateNameServersForCatalogAndMemberZones">
<label>
<input type="radio" name="rdZoneNotify" id="rdZoneNotifySeparateNameServersForCatalogAndMemberZones" value="SeparateNameServersForCatalogAndMemberZones">
Separate Name Servers For Catalog And Member Zones
</label>
<div style="padding-top: 5px; padding-left: 20px;">Notifies specified name servers for member zone updates and secondary catalog name servers for catalog zone updates.</div>
</div>
</div>
</div>
<div class="form-group">
<label for="txtZoneNotifyNameServers" class="col-sm-3 control-label">Specified Name Servers</label>
<div class="col-sm-8">
<textarea id="txtZoneNotifyNameServers" class="form-control" rows="5" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter only the IP addresses of the name servers above.</div>
</div>
</div>
<div id="divZoneNotifySecondaryCatalogNameServers" class="form-group">
<label for="txtZoneNotifySecondaryCatalogNameServers" class="col-sm-3 control-label">Secondary Catalog Name Servers</label>
<div class="col-sm-8">
<textarea id="txtZoneNotifySecondaryCatalogNameServers" class="form-control" rows="5" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter only the IP addresses of the Secondary Catalog name servers above.</div>
</div>
</div>
<div id="divZoneNotifyFailedNameServers" class="form-group" style="display: none;">
<label class="col-sm-3 control-label">Notify Failed Name Servers</label>
<div class="col-sm-8">
<span id="lblZoneNotifyFailedNameServers" class="form-control" style="height: auto;"></span>
</div>
</div>
<div>Note! Notification must be enabled to allow other name servers to trigger a zone transfer immediately when the zone is updated.</div>
</div>
</div>
<div id="tabPaneZoneOptionsUpdate" role="tabpanel" class="tab-pane" style="padding: 0 6px 0 0; max-height: 450px; margin: 10px 0 0 0; overflow-y: auto; overflow-x: hidden;">
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-3 control-label">Dynamic Updates</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdDynamicUpdate" id="rdDynamicUpdateDeny" value="Deny">
Deny (default)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Denies everyone from performing dynamic updates.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDynamicUpdate" id="rdDynamicUpdateAllow" value="Allow">
Allow
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows everyone to perform dynamic updates.</div>
</div>
<div class="radio" id="divDynamicUpdateAllowOnlyZoneNameServers">
<label>
<input type="radio" name="rdDynamicUpdate" id="rdDynamicUpdateAllowOnlyZoneNameServers" value="AllowOnlyZoneNameServers">
Allow Only Name Servers In Zone
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows only the name servers with an NS record in the zone to perform dynamic updates.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDynamicUpdate" id="rdDynamicUpdateUseSpecifiedNetworkACL" value="UseSpecifiedNetworkACL">
Use Specified Network Access Control List (ACL)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Uses the specified network access control list to allow/deny to perform dynamic updates.</div>
</div>
<div class="radio" id="divDynamicUpdateAllowZoneNameServersAndUseSpecifiedNetworkACL">
<label>
<input type="radio" name="rdDynamicUpdate" id="rdDynamicUpdateAllowZoneNameServersAndUseSpecifiedNetworkACL" value="AllowZoneNameServersAndUseSpecifiedNetworkACL">
Allow Zone Name Servers And Use Specified Network Access Control List (ACL)
</label>
<div style="padding-top: 5px; padding-left: 20px;">Allows zone's name servers and uses specified network access control list to allow/deny to perform dynamic updates.</div>
</div>
</div>
</div>
<div class="form-group">
<label for="txtDynamicUpdateNetworkACL" class="col-sm-3 control-label">Network Access Control List (ACL)</label>
<div class="col-sm-8">
<textarea id="txtDynamicUpdateNetworkACL" class="form-control" rows="5" spellcheck="false"></textarea>
<div style="padding-top: 5px;">Enter IP addresses or network addresses one below another to allow access. Add <code>!</code> character at the start to deny access, e.g. <code>!192.168.10.0/24</code> will deny entire subnet. The ACL is processed in the same order its listed. If no networks match, the default policy is to deny all.</div>
</div>
</div>
<div>Note! Dynamic updates should be allowed only to trusted IP addresses since they will be able to add/delete records in the zone.</div>
<div style="padding-top: 10px;">Warning! If no security policy is configured in the Primary Zone then access will be provided only based on the options selected here. Thus setting up a security policy in the Primary Zone is highly recommended.</div>
</div>
<div id="divDynamicUpdateSecurityPolicy" class="well well-sm form-horizontal">
<p style="font-size: 16px; font-weight: bold;">Security Policy</p>
<table id="tableDynamicUpdateSecurityPolicy" class="table table-hover">
<thead>
<tr>
<th>TSIG Key Name</th>
<th>Domain Name</th>
<th>Allowed Record Types</th>
<th style="width: 84px;">
<button type="button" class="btn btn-default" style="padding: 0px 20px;" onclick="addZoneOptionsDynamicUpdatesSecurityPolicyRow();">Add</button>
</th>
</tr>
</thead>
<tbody id="tbodyDynamicUpdateSecurityPolicy"></tbody>
</table>
<div>Note! Configuring a security policy above will cause the DNS server to authenticate all dynamic update requests. A TSIG key can add/delete records only for the specified domain name and allowed record types. TSIG key names must be configured from the Settings before using them here. Use wildcard domain name to specify all sub domain names. Use a comma separator to specify more than one record type. Use ANY to specify all record types.</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnSaveZoneOptions" type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveZoneOptions(); return false;">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalDnssecSignZone" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Sign Zone - <span id="lblDnssecSignZoneZoneName"></span></h4>
</div>
<div class="modal-body">
<div id="divDnssecSignZoneAlert"></div>
<div class="form-horizontal" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div class="form-group">
<label class="col-sm-4 control-label">DNSKEY Algorithm</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneAlgorithm" id="rdDnssecSignZoneAlgorithmRsa" value="RSA">
RSA
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneAlgorithm" id="rdDnssecSignZoneAlgorithmEcdsa" value="ECDSA">
ECDSA (recommended)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneAlgorithm" id="rdDnssecSignZoneAlgorithmEddsa" value="EDDSA">
EdDSA
</label>
</div>
</div>
</div>
<div id="divDnssecSignZoneRsaParameters">
<div class="form-group">
<label for="optDnssecSignZoneRsaHashAlgorithm" class="col-sm-4 control-label">Hash Algorithm</label>
<div class="col-sm-8">
<select id="optDnssecSignZoneRsaHashAlgorithm" class="form-control" style="width: auto;">
<option value="MD5">MD5 (obsolete)</option>
<option value="SHA1">SHA1 (obsolete)</option>
<option value="SHA256">SHA256 (default)</option>
<option>SHA512</option>
</select>
</div>
</div>
</div>
<div id="divDnssecSignZoneEcdsaParameters">
<div class="form-group">
<label for="optDnssecSignZoneEcdsaCurve" class="col-sm-4 control-label">ECDSA Curve</label>
<div class="col-sm-8">
<select id="optDnssecSignZoneEcdsaCurve" class="form-control" style="width: auto;">
<option value="P256">P256 (default)</option>
<option>P384</option>
</select>
</div>
</div>
</div>
<div id="divDnssecSignZoneEddsaParameters">
<div class="form-group">
<label for="optDnssecSignZoneEddsaCurve" class="col-sm-4 control-label">EdDSA Curve</label>
<div class="col-sm-8">
<select id="optDnssecSignZoneEddsaCurve" class="form-control" style="width: auto;">
<option value="ED25519">Ed25519 (default)</option>
<option value="ED448">Ed448</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Key Signing Key (KSK)</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneKskGeneration" id="rdDnssecSignZoneKskGenerationAutomatic" value="Automatic">
Automatic Private Key Generation (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneKskGeneration" id="rdDnssecSignZoneKskGenerationUseSpecified" value="UseSpecified">
Use Specified Private Key
</label>
</div>
</div>
</div>
<div id="divDnssecSignZoneRsaKskKeySize">
<div class="form-group">
<label for="optDnssecSignZoneRsaKskKeySize" class="col-sm-4 control-label">KSK Size</label>
<div class="col-sm-8">
<select id="optDnssecSignZoneRsaKskKeySize" class="form-control" style="width: auto; display: inline;">
<option>1024</option>
<option>1280</option>
<option>1536</option>
<option>2048</option>
<option>3072</option>
<option>4096</option>
</select>
<span>bits (recommended 2048)</span>
</div>
</div>
</div>
<div id="divDnssecSignZonePemKskPrivateKey">
<div class="form-group">
<label for="txtDnssecSignZonePemKskPrivateKey" class="col-sm-4 control-label">KSK Private Key</label>
<div class="col-sm-7">
<textarea id="txtDnssecSignZonePemKskPrivateKey" class="form-control" rows="4" spellcheck="false" placeholder="-----BEGIN PRIVATE KEY-----
MII...
-----END PRIVATE KEY-----"></textarea>
<div style="padding-top: 5px;">Enter a private key in PEM format.</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Zone Signing Key (ZSK)</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneZskGeneration" id="rdDnssecSignZoneZskGenerationAutomatic" value="Automatic">
Automatic Private Key Generation (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneZskGeneration" id="rdDnssecSignZoneZskGenerationUseSpecified" value="UseSpecified">
Use Specified Private Key
</label>
</div>
</div>
</div>
<div id="divDnssecSignZoneRsaZskKeySize">
<div class="form-group">
<label for="optDnssecSignZoneRsaZskKeySize" class="col-sm-4 control-label">ZSK Size</label>
<div class="col-sm-8">
<select id="optDnssecSignZoneRsaZskKeySize" class="form-control" style="width: auto; display: inline;">
<option>1024</option>
<option>1280</option>
<option>1536</option>
<option>2048</option>
<option>3072</option>
<option>4096</option>
</select>
<span>bits (default 1280)</span>
</div>
</div>
</div>
<div id="divDnssecSignZonePemZskPrivateKey">
<div class="form-group">
<label for="txtDnssecSignZonePemZskPrivateKey" class="col-sm-4 control-label">ZSK Private Key</label>
<div class="col-sm-7">
<textarea id="txtDnssecSignZonePemZskPrivateKey" class="form-control" rows="4" spellcheck="false" placeholder="-----BEGIN PRIVATE KEY-----
MII...
-----END PRIVATE KEY-----"></textarea>
<div style="padding-top: 5px;">Enter a private key in PEM format.</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Proof of Non-Existence</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneNxProof" id="rdDnssecSignZoneNxProofNSEC" value="NSEC">
Next Secure (NSEC) (recommended)
</label>
<div style="padding-top: 5px; padding-left: 20px;">
With NSEC, all the records in your zone can be discovered by anyone using "zone walking" technique. NSEC is recommended if your zone does not contain any private/internal records.
</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDnssecSignZoneNxProof" id="rdDnssecSignZoneNxProofNSEC3" value="NSEC3">
Next Secure 3 (NSEC3)
</label>
<div style="padding-top: 5px; padding-left: 20px;">
NSEC3, makes it difficult to perform "zone walking" since it uses hashing with a random salt. NSEC3 should be used if your zone contains any private/internal records that you do not wish to be enumerable.
</div>
</div>
</div>
</div>
<div id="divDnssecSignZoneNSEC3Parameters">
<div class="form-group">
<label for="txtDnssecSignZoneNSEC3Iterations" class="col-sm-4 control-label">NSEC3 Iterations</label>
<div class="col-sm-8">
<input id="txtDnssecSignZoneNSEC3Iterations" type="number" class="form-control" placeholder="iterations" style="width: 100px; display: inline;">
<span>(valid range 0-50, recommended 0)</span>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
The number of iterations used by NSEC3 for hashing the domain names. It is recommended to use 0 iterations since more iterations will increase computational costs for both the DNS server and resolver while not providing much value against "zone walking" [<a href="https://www.rfc-editor.org/rfc/rfc9276.html#name-iterations" target="_blank">RFC 9276</a>].
</div>
</div>
<div class="form-group">
<label for="txtDnssecSignZoneNSEC3SaltLength" class="col-sm-4 control-label">NSEC3 Salt Length</label>
<div class="col-sm-8">
<input id="txtDnssecSignZoneNSEC3SaltLength" type="number" class="form-control" placeholder="length" style="width: 100px; display: inline;">
<span>bytes (valid range 0-32, recommended 0)</span>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
The number of bytes of random salt to generate to be used with the NSEC3 hash computation. It is recommended to not use salt by setting the length to 0 [<a href="https://www.rfc-editor.org/rfc/rfc9276.html#name-salt" target="_blank">RFC 9276</a>].
</div>
</div>
</div>
<div class="form-group">
<label for="txtDnssecSignZoneDnsKeyTtl" class="col-sm-4 control-label">DNSKEY TTL</label>
<div class="col-sm-8">
<input id="txtDnssecSignZoneDnsKeyTtl" type="text" class="form-control" placeholder="ttl" style="width: 100px; display: inline;">
<span>seconds (default 3600/1h)</span>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
The TTL value to be used for DNSKEY records. A lower value will allow quicker addition or rollover to a new DNS Key at the cost of increased frequency of DNSKEY queries by resolvers.
</div>
</div>
<div class="form-group">
<label for="txtDnssecSignZoneZskAutoRollover" class="col-sm-4 control-label">ZSK Automatic Rollover</label>
<div class="col-sm-8">
<input id="txtDnssecSignZoneZskAutoRollover" type="number" class="form-control" placeholder="days" style="width: 100px; display: inline;">
<span>days (valid range 0-365; default 30; set 0 to disable)</span>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
The frequency at which the DNS server must automatically rollover the Zone Signing Key (ZSK).
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="pull-left" style="padding: 6px 0;">
<a href="https://blog.technitium.com/2022/07/how-to-secure-your-domain-name-with-.html" target="_blank">Help: How To Secure Your Domain Name With DNSSEC</a>
</div>
<div class="pull-right">
<button id="btnDnssecSignZone" type="submit" class="btn btn-primary" data-loading-text="Signing..." onclick="signPrimaryZone(); return false;">Sign Zone</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
<div id="modalDnssecUnsignZone" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Unsign Zone - <span id="lblDnssecUnsignZoneZoneName"></span></h4>
</div>
<div class="modal-body">
<div id="divDnssecUnsignZoneAlert"></div>
<p><b>Warning!</b> Unsigning the zone without removing all DS records from its parent zone will cause DNSSEC validating recursive resolvers to mark the zone as <b>bogus</b> and fail to resolve it.</p>
<p><b>Warning!</b> Make sure that you have removed all of the DS records from the parent zone and sufficient time has passed before unsigning this zone. You MUST wait for at least the number of seconds specified by the DS record's TTL value to elapse before unsigning the zone to ensure that all recursive resolvers would have expired the DS records from its cache. For example, if you have DS records at the parent zone with TTL value set to 86400 then you must wait for 86400 seconds (24 hours) to pass after you delete the DS records from the parent zone. Once you have ensured that you have waited for the appropriate time then you can unsign the zone safely.</p>
<p><b>Note!</b> You can find out the TTL value of DS records for your zone by querying for DS records using the DNS Client tab.</p>
<p><b>Warning!</b> Unsigning the zone will permanently delete all of the private keys associated with it. Consider taking a backup before proceeding.</p>
<p>&nbsp;</p>
<p>Are you sure you want to proceed to unsign the zone now?</p>
</div>
<div class="modal-footer">
<button id="btnDnssecUnsignZone" type="submit" class="btn btn-danger" data-loading-text="Unsigning..." onclick="unsignPrimaryZone(); return false;">Unsign Zone</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalDnssecViewDs" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document" style="width: 940px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">View DS Info - <span id="lblDnssecViewDsZoneName"></span></h4>
</div>
<div class="modal-body">
<div id="divDnssecViewDsAlert"></div>
<div id="divDnssecViewDsLoader" style="height: 500px;"></div>
<div id="divDnssecViewDs" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<p>
Use the DNS Key data given below to add DS records for your zone. Before adding the DS records, you must read and understand the following points:
<ul>
<li>The Key State for a newly published DNS Key must be <code>Ready</code> before you can add a DS record for it. Adding DS record for a DNS Key with <code>Published</code> Key State may cause DNSSEC validation to fail for some DNS resolvers. A "ready by" timestamp is displayed to let you know when a DS record can be added for a DNS Key that is not "Ready" yet.</li>
<li>You should add only one DS record for each Key Tag. That is, do not create multiple DS records for each Digest Type, instead use the Digest Type that is supported by your Domain Registrar.</li>
<li>Use the provided Public Key if the Domain Registrar requires it instead of the Digest.</li>
<li>When doing a Key Signing Key (KSK) rollover, you can immediately delete the old DS record after adding the new DS record.</li>
</ul>
</p>
<table class="table well well-sm">
<thead>
<tr>
<th><a>Key Tag</a></th>
<th><a>Key State</a></th>
<th><a>Algorithm</a></th>
<th><a>Digest Type</a></th>
<th><a>Digest</a></th>
</tr>
</thead>
<tbody id="tableDnssecViewDsBody">
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalDnssecProperties" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document" style="width: 940px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">DNSSEC Properties - <span id="lblDnssecPropertiesZoneName"></span></h4>
</div>
<div class="modal-body">
<div id="divDnssecPropertiesAlert"></div>
<div id="divDnssecPropertiesLoader" style="height: 500px;"></div>
<div id="divDnssecProperties" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div class="well well-sm form-horizontal">
<table class="table table-hover" style="margin-bottom: 10px;">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tableDnssecPropertiesPrivateKeysBody', 0); return false;">Key Tag</a></th>
<th><a href="#" onclick="sortTable('tableDnssecPropertiesPrivateKeysBody', 1); return false;">Key Type</a></th>
<th><a href="#" onclick="sortTable('tableDnssecPropertiesPrivateKeysBody', 2); return false;">Algorithm</a></th>
<th><a href="#" onclick="sortTable('tableDnssecPropertiesPrivateKeysBody', 3); return false;">State</a></th>
<th><a href="#" onclick="sortTable('tableDnssecPropertiesPrivateKeysBody', 4); return false;">State Changed</a></th>
<th><a href="#" onclick="sortTable('tableDnssecPropertiesPrivateKeysBody', 5); return false;">Rollover (days)</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tableDnssecPropertiesPrivateKeysBody">
</tbody>
</table>
<div>
<button type="button" class="btn btn-primary" style="padding: 2px 0; width: 120px;" data-toggle="collapse" data-target="#divDnssecPropertiesAddKey" aria-expanded="false" aria-controls="divDnssecPropertiesAddKey">Add Private Key</button>
<button id="btnDnssecPropertiesPublishKeys" type="button" class="btn btn-warning" style="padding: 2px 0; width: 120px;" data-loading-text="Publishing..." onclick="publishAllDnssecPrivateKeys(this);">Publish All Keys</button>
</div>
<div id="divDnssecPropertiesAddKey" class="collapse">
<div class="panel panel-default" style="margin-bottom: 0px; margin-top: 10px; padding-top: 15px;">
<div class="form-group">
<label for="optDnssecPropertiesAddKeyKeyType" class="col-sm-4 control-label">Key Type</label>
<div class="col-sm-8">
<select id="optDnssecPropertiesAddKeyKeyType" class="form-control" style="width: auto;">
<option value="KeySigningKey">Key Signing Key (KSK)</option>
<option value="ZoneSigningKey">Zone Signing Key (ZSK)</option>
</select>
</div>
</div>
<div class="form-group">
<label for="optDnssecPropertiesAddKeyAlgorithm" class="col-sm-4 control-label">Algorithm</label>
<div class="col-sm-8">
<select id="optDnssecPropertiesAddKeyAlgorithm" class="form-control" style="width: auto;">
<option>RSA</option>
<option value="ECDSA">ECDSA (recommended)</option>
<option value="EDDSA">EdDSA</option>
</select>
</div>
</div>
<div id="divDnssecPropertiesAddKeyRsaParameters">
<div class="form-group">
<label for="optDnssecPropertiesAddKeyRsaHashAlgorithm" class="col-sm-4 control-label">Hash Algorithm</label>
<div class="col-sm-8">
<select id="optDnssecPropertiesAddKeyRsaHashAlgorithm" class="form-control" style="width: auto;">
<option value="MD5">MD5 (obsolete)</option>
<option value="SHA1">SHA1 (obsolete)</option>
<option value="SHA256">SHA256 (default)</option>
<option>SHA512</option>
</select>
</div>
</div>
</div>
<div id="divDnssecPropertiesAddKeyEcdsaParameters">
<div class="form-group">
<label for="optDnssecPropertiesAddKeyEcdsaCurve" class="col-sm-4 control-label">ECDSA Curve</label>
<div class="col-sm-8">
<select id="optDnssecPropertiesAddKeyEcdsaCurve" class="form-control" style="width: auto;">
<option value="P256">P256 (default)</option>
<option>P384</option>
</select>
</div>
</div>
</div>
<div id="divDnssecPropertiesAddKeyEddsaParameters">
<div class="form-group">
<label for="optDnssecPropertiesAddKeyEddsaCurve" class="col-sm-4 control-label">EdDSA Curve</label>
<div class="col-sm-8">
<select id="optDnssecPropertiesAddKeyEddsaCurve" class="form-control" style="width: auto;">
<option value="ED25519">Ed25519 (default)</option>
<option value="ED448">Ed448</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Key Generation</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdDnssecPropertiesKeyGeneration" id="rdDnssecPropertiesKeyGenerationAutomatic" value="Automatic">
Automatic Private Key Generation (default)
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDnssecPropertiesKeyGeneration" id="rdDnssecPropertiesKeyGenerationUseSpecified" value="UseSpecified">
Use Specified Private Key
</label>
</div>
</div>
</div>
<div id="divDnssecPropertiesAddKeyRsaKeySize">
<div class="form-group">
<label for="optDnssecPropertiesAddKeyRsaKeySize" class="col-sm-4 control-label">Key Size</label>
<div class="col-sm-8">
<select id="optDnssecPropertiesAddKeyRsaKeySize" class="form-control" style="width: auto; display: inline;">
<option>1024</option>
<option>1280</option>
<option>1536</option>
<option>2048</option>
<option>3072</option>
<option>4096</option>
</select>
<span>bits</span>
</div>
</div>
</div>
<div id="divDnssecPropertiesPemPrivateKey">
<div class="form-group">
<label for="txtDnssecPropertiesPemPrivateKey" class="col-sm-4 control-label">Private Key</label>
<div class="col-sm-7">
<textarea id="txtDnssecPropertiesPemPrivateKey" class="form-control" rows="4" spellcheck="false" placeholder="-----BEGIN PRIVATE KEY-----
MII...
-----END PRIVATE KEY-----"></textarea>
<div style="padding-top: 5px;">Enter a private key in PEM format.</div>
</div>
</div>
</div>
<div id="divDnssecPropertiesAddKeyAutomaticRollover" class="form-group">
<label for="txtDnssecPropertiesAddKeyAutomaticRollover" class="col-sm-4 control-label">Automatic Key Rollover</label>
<div class="col-sm-8">
<div>
<input id="txtDnssecPropertiesAddKeyAutomaticRollover" type="number" class="form-control" placeholder="days" style="width: 100px; display: inline;">
<span>days (valid range 0-365; default 30; set 0 to disable)</span>
</div>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
The frequency at which the DNS server must automatically rollover the key.
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<button type="button" class="btn btn-primary" style="padding: 2px 10px;" data-loading-text="Generating..." onclick="addDnssecPrivateKey(this);">Add Key</button>
</div>
</div>
</div>
</div>
<div id="divDnssecPropertiesNoteReadyBy" style="margin-top: 10px; display: none;">
Note! The Key State for a newly published Key Signing Key (KSK) must be <code>Ready</code> before you can add a DS record for it. Use the <b>View DS Info</b> option for more details on adding DS record.
</div>
<div id="divDnssecPropertiesNoteActiveBy" style="margin-top: 10px; display: none;">
Note! The Key State for a Key Signing Key (KSK) will automatically switch from <code>Ready</code> to <code>Active</code> once you have added DS record for it and the DNS server is able to detect it. Use the <b>View DS Info</b> option for more details on adding DS record. If this is a private zone, then you should manually activate the KSK so that the DNS Server stops the detection process which queries for DS records periodically.
</div>
<div id="divDnssecPropertiesNoteRetiredRevoked" style="margin-top: 10px; display: none;">
Note! The keys with <code>Retired</code> or <code>Revoked</code> Key State will be automatically unpublished and removed when its safe to do so.
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group">
<label class="col-sm-4 control-label">Proof of Non-Existence</label>
<div class="col-sm-8">
<div class="radio">
<label>
<input type="radio" name="rdDnssecPropertiesNxProof" id="rdDnssecPropertiesNxProofNSEC" value="NSEC">
Next Secure (NSEC) (recommended)
</label>
<div style="padding-top: 5px; padding-left: 20px;">
With NSEC, all the records in your zone can be discovered by anyone using "zone walking" technique. NSEC is recommended if your zone does not contain any private/internal records.
</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdDnssecPropertiesNxProof" id="rdDnssecPropertiesNxProofNSEC3" value="NSEC3">
Next Secure 3 (NSEC3)
</label>
<div style="padding-top: 5px; padding-left: 20px;">
NSEC3, makes it difficult to perform "zone walking" since it uses hashing with a random salt. NSEC3 should be used if your zone contains any private/internal records that you do not wish to be enumerable.
</div>
</div>
</div>
</div>
<div id="divDnssecPropertiesNSEC3Parameters">
<div class="form-group">
<label for="txtDnssecPropertiesNSEC3Iterations" class="col-sm-4 control-label">NSEC3 Iterations</label>
<div class="col-sm-8">
<input id="txtDnssecPropertiesNSEC3Iterations" type="number" class="form-control" placeholder="iterations" style="width: 100px; display: inline;">
<span>(valid range 0-50, recommended 0)</span>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
The number of iterations used by NSEC3 for hashing the domain names. It is recommended to use 0 iterations since more iterations will increase computational costs for both the DNS server and resolver while not providing much value against "zone walking" [<a href="https://www.rfc-editor.org/rfc/rfc9276.html#name-iterations" target="_blank">RFC 9276</a>].
</div>
</div>
<div class="form-group">
<label for="txtDnssecPropertiesNSEC3SaltLength" class="col-sm-4 control-label">NSEC3 Salt Length</label>
<div class="col-sm-8">
<input id="txtDnssecPropertiesNSEC3SaltLength" type="number" class="form-control" placeholder="length" style="width: 100px; display: inline;">
<span>bytes (valid range 0-32, recommended 0)</span>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
The number of bytes of random salt to generate to be used with the NSEC3 hash computation. It is recommended to not use salt by setting the length to 0 [<a href="https://www.rfc-editor.org/rfc/rfc9276.html#name-salt" target="_blank">RFC 9276</a>].
</div>
</div>
</div>
<div class="form-group" style="margin-bottom: 5px;">
<div class="col-sm-offset-4 col-sm-8">
<button id="btnDnssecPropertiesChangeNxProof" type="button" class="btn btn-warning" style="padding: 2px 0; width: 100px;" data-loading-text="Changing..." onclick="changeDnssecNxProof(this);">Change</button>
</div>
</div>
</div>
<div class="well well-sm form-horizontal">
<div class="form-group" style="margin-bottom: 5px;">
<label for="txtDnssecPropertiesDnsKeyTtl" class="col-sm-4 control-label">DNSKEY TTL</label>
<div class="col-sm-8">
<div>
<input id="txtDnssecPropertiesDnsKeyTtl" type="text" class="form-control" placeholder="ttl" style="width: 100px; display: inline;">
<span>seconds (default 3600/1h)</span>
</div>
<div style="margin-top: 10px;">
<button type="button" class="btn btn-default" style="padding: 2px 0; width: 100px;" data-loading-text="Updating..." onclick="updateDnssecDnsKeyTtl(this);">Update TTL</button>
</div>
</div>
<div class="col-sm-offset-4 col-sm-8" style="padding-top: 5px;">
The TTL value to be used for DNSKEY records. A lower value will allow quicker addition or rollover to a new DNS Key at the cost of increased frequency of DNSKEY queries by resolvers.
</div>
</div>
<div style="margin-top: 10px;">
Warning! You MUST wait for at least the number of seconds specified by the the old TTL value to elapse before making any changes to the DNS keys above to ensure that all recursive resolvers would have expired the DNSKEY records from its cache. For example, if the old TTL value was 3600, then you must wait for 3600 seconds (1 hour) to pass before making any changes to the DNS keys.
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalImportAllowedZones" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Import Allowed Zones</h4>
</div>
<div class="modal-body">
<div id="divImportAllowedZonesAlert"></div>
<p>Enter domain names one below other to import into Allowed Zone:</p>
<div class="form-group">
<label for="txtImportAllowedZones" class="control-label">Allowed Zones</label>
<textarea id="txtImportAllowedZones" class="form-control" rows="15" spellcheck="false"></textarea>
</div>
</div>
<div class="modal-footer">
<button id="btnImportAllowedZones" type="submit" class="btn btn-primary" data-loading-text="Importing..." onclick="importAllowedZones(); return false;">Import</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalImportBlockedZones" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Import Blocked Zones</h4>
</div>
<div class="modal-body">
<div id="divImportBlockedZonesAlert"></div>
<p>Enter domain names one below other to import into blocked zone:</p>
<div class="form-group">
<label for="txtImportBlockedZones" class="control-label">Blocked Zones</label>
<textarea id="txtImportBlockedZones" class="form-control" rows="15" spellcheck="false"></textarea>
</div>
</div>
<div class="modal-footer">
<button id="btnImportBlockedZones" type="submit" class="btn btn-primary" data-loading-text="Importing..." onclick="importBlockedZones(); return false;">Import</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalStoreApps" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 800px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">DNS App Store</h4>
</div>
<div class="modal-body">
<div id="divStoreAppsAlert"></div>
<div id="divStoreAppsLoader" style="height: 500px;"></div>
<div id="divStoreApps" style="max-height: 500px; overflow-y: auto; display: none;">
<table class="table table-hover">
<thead>
<tr>
<th style="min-width: 120px;"><a href="#" onclick="sortTable('tableStoreAppsBody', 0); return false;">Store Apps</a></th>
<th style="width: 96px;"></th>
</tr>
</thead>
<tbody id="tableStoreAppsBody">
</tbody>
<tfoot id="tableStoreAppsFooter">
<tr><td colspan="3"><b>Total Apps: 0</b></td></tr>
</tfoot>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalInstallApp" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Install App</h4>
</div>
<div class="modal-body">
<div id="divInstallAppAlert"></div>
<div class="form-group">
<label for="txtInstallApp" class="col-sm-4 control-label">App Name</label>
<div class="col-sm-7">
<input id="txtInstallApp" type="text" class="form-control">
</div>
</div>
<div class="form-group">
<label for="fileAppZip" class="col-sm-4 control-label">App Zip File</label>
<div class="col-sm-7">
<input type="file" class="form-control" id="fileAppZip">
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnInstallApp" type="submit" class="btn btn-primary" data-loading-text="Installing..." onclick="installApp(); return false;">Install</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalUpdateApp" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Update App</h4>
</div>
<div class="modal-body">
<div id="divUpdateAppAlert"></div>
<div class="form-group">
<label for="txtUpdateApp" class="col-sm-4 control-label">App Name</label>
<div class="col-sm-7">
<input id="txtUpdateApp" type="text" class="form-control" disabled>
</div>
</div>
<div class="form-group">
<label for="fileUpdateAppZip" class="col-sm-4 control-label">App Zip File</label>
<div class="col-sm-7">
<input type="file" class="form-control" id="fileUpdateAppZip">
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnUpdateApp" type="submit" class="btn btn-primary" data-loading-text="Updating..." onclick="updateApp(); return false;">Update</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalAppConfig" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">App Config - <span id="lblAppConfigName"></span></h4>
</div>
<div class="modal-body">
<div id="divAppConfigAlert"></div>
<p>Edit the <code>dnsApp.config</code> config file below as required by the DNS application.</p>
<div class="form-group">
<label for="txtAppConfig" class="control-label">Config File</label>
<textarea id="txtAppConfig" class="form-control" rows="15" spellcheck="false"></textarea>
</div>
<p>Note: The app will reload the config automatically after you save it.</p>
</div>
<div class="modal-footer">
<button id="btnAppConfig" type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveAppConfig(); return false;">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalBackupSettings" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Backup Settings</h4>
</div>
<div class="modal-body">
<div id="divBackupSettingsAlert"></div>
<p>The backup process will create a zip file for the items selected below:</p>
<div class="form-horizontal">
<div class="form-group">
<div style="padding-left: 40px;">
<div class="checkbox">
<label>
<input id="chkBackupAuthConfig" type="checkbox" checked> Authentication Config File (auth.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupClusterConfig" type="checkbox" checked> Cluster Config File (cluster.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupWebServiceConfig" type="checkbox" checked> Web Service Config And Certificate File (webservice.config, *.pfx &amp; *.p12)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupDnsConfig" type="checkbox" checked> DNS Config And Certificate File (dns.config, *.pfx &amp; *.p12)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupLogConfig" type="checkbox" checked> Log Config File (log.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupZones" type="checkbox" checked> DNS Zone Files (*.zone)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupAllowedZones" type="checkbox" checked> Allowed Zones File (allowed.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupBlockedZones" type="checkbox" checked> Blocked Zones File (blocked.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupBlockLists" type="checkbox" checked> Block List Config And Cache Files (blocklist.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupApps" type="checkbox" checked> DNS Apps
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupScopes" type="checkbox" checked> DHCP Scope Files (*.scope)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupStats" type="checkbox" checked> Dashboard Stats Files (*.stat, *.dstat)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkBackupLogs" type="checkbox"> Log Files (*.log)
</label>
</div>
</div>
</div>
</div>
<p><b>Note!</b> The Web Service or Optional Protocols TLS certificate (.pfx or .p12) files will be included in the backup only if they exist within the DNS server's config folder.</p>
<p><b>Note!</b> It may take several minutes to generate the backup zip file if log files are selected to be backed up which will depend on the size of the log files on the disk.</p>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" data-loading-text="Backup" onclick="backupSettings(this); return false;">Backup</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalRestoreSettings" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Restore Settings</h4>
</div>
<div class="modal-body">
<div id="divRestoreSettingsAlert"></div>
<div class="form-horizontal">
<div class="form-group">
<label for="fileBackupZip" class="col-sm-3 control-label">Backup Zip File</label>
<div class="col-sm-6">
<input type="file" class="form-control" id="fileBackupZip">
</div>
</div>
<p>The restore process will restore all the selected items from the backup zip file:</p>
<div class="form-group">
<div style="padding-left: 40px;">
<div class="checkbox">
<label>
<input id="chkRestoreAuthConfig" type="checkbox" checked> Authentication Config File (auth.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreClusterConfig" type="checkbox" checked> Cluster Config File (cluster.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreWebServiceConfig" type="checkbox" checked> Web Service Config And Certificate File (webservice.config, *.pfx &amp; *.p12)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreDnsConfig" type="checkbox" checked> DNS Config And Certificate File (dns.config, *.pfx &amp; *.p12)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreLogConfig" type="checkbox" checked> Log Config File (log.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreZones" type="checkbox" checked> DNS Zone Files (*.zone)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreAllowedZones" type="checkbox" checked> Allowed Zones File (allowed.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreBlockedZones" type="checkbox" checked> Blocked Zones File (blocked.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreBlockLists" type="checkbox" checked> Block List Config And Cache Files (blocklist.config)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreApps" type="checkbox" checked> DNS Apps
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreScopes" type="checkbox" checked> DHCP Scope Files (*.scope)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreStats" type="checkbox" checked> Dashboard Stats Files (*.stat, *.dstat)
</label>
</div>
<div class="checkbox">
<label>
<input id="chkRestoreLogs" type="checkbox"> Log Files (*.log)
</label>
</div>
</div>
</div>
<p>Restore options:</p>
<div class="form-group">
<div style="padding-left: 40px;">
<div class="checkbox">
<label>
<input id="chkDeleteExistingFiles" type="checkbox" checked> Delete Existing Files For Selected Items
</label>
</div>
</div>
</div>
</div>
<p><b>Warning!</b> The restore process will overwrite existing config files on disk for above selected items and reload new settings including user accounts from the backup. The current logged in user account and current session will be added automatically.</p>
</div>
<div class="modal-footer">
<button id="btnRestoreSettings" type="submit" class="btn btn-primary" data-loading-text="Restoring..." onclick="restoreSettings(); return false;">Restore</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalTopStats" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 id="lblTopStatsTitle" class="modal-title">Top Stats</h4>
</div>
<div class="modal-body">
<div id="divTopStatsAlert"></div>
<div id="divTopStatsLoader" style="height: 500px;"></div>
<div id="divTopStatsData" style="max-height: 500px; overflow-y: auto;">
<table id="tableTopStatsClients" class="table table-hover">
<thead>
<tr>
<th>Client</th>
<th>Queries</th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyTopStatsClients">
</tbody>
<tfoot>
<tr><th colspan="3" id="tfootTopStatsClients"></th></tr>
</tfoot>
</table>
<table id="tableTopStatsDomains" class="table table-hover">
<thead>
<tr>
<th>Domain</th>
<th>Hits</th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyTopStatsDomains">
</tbody>
<tfoot>
<tr><th colspan="3" id="tfootTopStatsDomains"></th></tr>
</tfoot>
</table>
<table id="tableTopStatsBlockedDomains" class="table table-hover">
<thead>
<tr>
<th>Domain</th>
<th>Hits</th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyTopStatsBlockedDomains">
</tbody>
<tfoot>
<tr><th colspan="3" id="tfootTopStatsBlockedDomains"></th></tr>
</tfoot>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalDhcpRemoveLease" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Remove Lease?</h4>
</div>
<div class="modal-body">
<div id="divDhcpRemoveLeaseAlert"></div>
<p><b>Warning!</b> Removing a DHCP lease from the server side will NOT remove the allocated IP address from the client side. Make sure that the client assigned this lease is not connected to the network before proceeding.</p>
<p><b>Warning!</b> Removing a DHCP lease may cause IP address conflict if the DHCP server assigns the same IP address to a new client while the old client is still connected to the network.</p>
<p>It is not recommended to remove a DHCP lease when the client is still connected or may connect back later to the network before the lease expires. Use this option only as a last resort.</p>
<p>
Follow the recommendations below to avoid such a case that requires removing a DHCP lease:
<ul>
<li>Use a shorter lease time such that a dynamically allocated lease expires quickly when the client exits the network.</li>
<li>Use Exclusions to exclude IP address ranges from being dynamically allocated that you plan to assign manually to some of the devices on the network.</li>
<li>Use Exclusions to make sure that you have unallocated addresses available in the DHCP scope to be assigned as reserved leases in future.</li>
<li>Rely less on the assigned IP addresses by configuring a domain name for the DHCP scope and accessing all the devices using their domain names.</li>
</ul>
</p>
<p>&nbsp;</p>
<p>Are you sure you want to remove the DHCP lease now?</p>
</div>
<div class="modal-footer">
<button id="btnRemoveDhcpLease" type="button" class="btn btn-danger" data-loading-text="Removing...">Remove</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="modalAddUser" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Add User</h4>
</div>
<div class="modal-body">
<div id="divAddUserAlert"></div>
<div class="form-group">
<label for="txtAddUserDisplayName" class="col-sm-4 control-label">Display Name</label>
<div class="col-sm-7">
<input id="txtAddUserDisplayName" type="text" class="form-control" placeholder="display name" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtAddUserUsername" class="col-sm-4 control-label">Username</label>
<div class="col-sm-7">
<input id="txtAddUserUsername" type="text" class="form-control" placeholder="username" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtAddUserPassword" class="col-sm-4 control-label">Password</label>
<div class="col-sm-7">
<input id="txtAddUserPassword" type="password" class="form-control" placeholder="password" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtAddUserConfirmPassword" class="col-sm-4 control-label">Confirm Password</label>
<div class="col-sm-7">
<input id="txtAddUserConfirmPassword" type="password" class="form-control" placeholder="confirm password" maxlength="255">
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnAddUser" type="submit" class="btn btn-primary" data-loading-text="Adding..." onclick="addUser(this); return false;">Add</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalUserDetails" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 940px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">User Details</h4>
</div>
<div class="modal-body">
<div id="divUserDetailsAlert"></div>
<div id="divUserDetailsLoader" style="height: 500px;"></div>
<div id="divUserDetailsViewer" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div class="form-group">
<label for="txtUserDetailsDisplayName" class="col-sm-4 control-label">Display Name</label>
<div class="col-sm-7">
<input id="txtUserDetailsDisplayName" type="text" class="form-control" placeholder="display name" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtUserDetailsUsername" class="col-sm-4 control-label">Username</label>
<div class="col-sm-7">
<input id="txtUserDetailsUsername" type="text" class="form-control" placeholder="username" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="lblUserDetails2FAStatus" class="col-sm-4 control-label">2FA Status</label>
<div class="col-sm-7">
<div id="lblUserDetails2FAStatus" style="padding: 6px 0; font-weight: bold;"></div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-7">
<div class="checkbox" style="padding: 0px;">
<label>
<input id="chkUserDetailsDisableAccount" type="checkbox"> Disable User Account
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="txtUserDetailsSessionTimeout" class="col-sm-4 control-label">Session Timeout</label>
<div class="col-sm-7">
<input id="txtUserDetailsSessionTimeout" type="number" class="form-control" placeholder="1800" style="width: 100px; display: inline;">
<span>seconds (valid range 0-604800; default 1800; set 0 to disable)</span>
</div>
</div>
<div class="form-group">
<label for="txtUserDetailsMemberOf" class="col-sm-4 control-label">Member Of</label>
<div class="col-sm-7">
<textarea id="txtUserDetailsMemberOf" class="form-control" rows="5"></textarea>
<label class="control-label" for="optUserDetailsGroupList">Add Group</label>
<select id="optUserDetailsGroupList" class="form-control"></select>
</div>
</div>
<div class="well well-sm" style="background-color: #fbfbfb;">
<p style="font-size: 16px; font-weight: bold;">Active Sessions</p>
<table id="tableUserDetailsActiveSessions" class="table table-hover" style="margin-bottom: 0px;">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyUserDetailsActiveSessions', 0); return false;">Session</a></th>
<th><a href="#" onclick="sortTable('tbodyUserDetailsActiveSessions', 1); return false;">Last Seen</a></th>
<th><a href="#" onclick="sortTable('tbodyUserDetailsActiveSessions', 2); return false;">Remote Address</a></th>
<th><a href="#" onclick="sortTable('tbodyUserDetailsActiveSessions', 3); return false;">User Agent</a></th>
<th style="width: 36px;"></th>
</tr>
</thead>
<tbody id="tbodyUserDetailsActiveSessions">
</tbody>
<tfoot>
<tr><th colspan="5" id="tfootUserDetailsActiveSessions"></th></tr>
</tfoot>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnUserDetailsSave" type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveUserDetails(this); return false;">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalAddGroup" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Add Group</h4>
</div>
<div class="modal-body">
<div id="divAddGroupAlert"></div>
<div class="form-group">
<label for="txtAddGroupName" class="col-sm-4 control-label">Name</label>
<div class="col-sm-7">
<input id="txtAddGroupName" type="text" class="form-control" placeholder="group name" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtAddGroupDescription" class="col-sm-4 control-label">Description</label>
<div class="col-sm-7">
<textarea id="txtAddGroupDescription" class="form-control" rows="5" maxlength="255"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnAddGroup" type="submit" class="btn btn-primary" data-loading-text="Adding..." onclick="addGroup(this); return false;">Add</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalGroupDetails" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Group Details</h4>
</div>
<div class="modal-body">
<div id="divGroupDetailsAlert"></div>
<div id="divGroupDetailsLoader" style="height: 500px;"></div>
<div id="divGroupDetailsViewer" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div class="form-group">
<label for="txtGroupDetailsName" class="col-sm-4 control-label">Name</label>
<div class="col-sm-7">
<input id="txtGroupDetailsName" type="text" class="form-control" placeholder="group name" maxlength="255">
</div>
</div>
<div class="form-group">
<label for="txtGroupDetailsDescription" class="col-sm-4 control-label">Description</label>
<div class="col-sm-7">
<textarea id="txtGroupDetailsDescription" class="form-control" rows="3" maxlength="255"></textarea>
</div>
</div>
<div class="form-group">
<label for="txtGroupDetailsMembers" class="col-sm-4 control-label">Members</label>
<div class="col-sm-7">
<textarea id="txtGroupDetailsMembers" class="form-control" rows="7"></textarea>
<label class="control-label" for="optGroupDetailsUserList">Add User</label>
<select id="optGroupDetailsUserList" class="form-control"></select>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnGroupDetailsSave" type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveGroupDetails(this); return false;">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalEditPermissions" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Edit Permissions - <span id="lblEditPermissionsName"></span></h4>
</div>
<div class="modal-body">
<div id="divEditPermissionsAlert"></div>
<div id="divEditPermissionsLoader" style="height: 500px;"></div>
<div id="divEditPermissionsViewer" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div class="well well-sm" style="background-color: #fbfbfb;">
<div class="form-group">
<label class="col-sm-3 control-label">User Permissions</label>
<div class="col-sm-9">
<table id="tableEditPermissionsUser" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyEditPermissionsUser', 0); return false;">Username</a></th>
<th><a href="#" onclick="sortTable('tbodyEditPermissionsUser', 0); return false;" style="width: 65px;">View</a></th>
<th><a href="#" onclick="sortTable('tbodyEditPermissionsUser', 0); return false;" style="width: 65px;">Modify</a></th>
<th><a href="#" onclick="sortTable('tbodyEditPermissionsUser', 0); return false;" style="width: 65px;">Delete</a></th>
<th style="width: 76px;"></th>
</tr>
</thead>
<tbody id="tbodyEditPermissionsUser"></tbody>
</table>
<label class="control-label" for="optEditPermissionsUserList">Add User</label>
<select id="optEditPermissionsUserList" class="form-control"></select>
</div>
</div>
</div>
<div class="well well-sm" style="background-color: #fbfbfb;">
<div class="form-group">
<label class="col-sm-3 control-label">Group Permissions</label>
<div class="col-sm-9">
<table id="tableEditPermissionsGroup" class="table table-hover">
<thead>
<tr>
<th><a href="#" onclick="sortTable('tbodyEditPermissionsGroup', 0); return false;">Group</a></th>
<th><a href="#" onclick="sortTable('tbodyEditPermissionsGroup', 0); return false;" style="width: 65px;">View</a></th>
<th><a href="#" onclick="sortTable('tbodyEditPermissionsGroup', 0); return false;" style="width: 65px;">Modify</a></th>
<th><a href="#" onclick="sortTable('tbodyEditPermissionsGroup', 0); return false;" style="width: 65px;">Delete</a></th>
<th style="width: 76px;"></th>
</tr>
</thead>
<tbody id="tbodyEditPermissionsGroup"></tbody>
</table>
<label class="control-label" for="optEditPermissionsGroupList">Add Group</label>
<select id="optEditPermissionsGroupList" class="form-control"></select>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnEditPermissionsSave" type="submit" class="btn btn-primary" data-loading-text="Saving...">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalInitializeNewCluster" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Initialize New Cluster</h4>
</div>
<div class="modal-body">
<div id="divInitializeNewClusterAlert"></div>
<div id="divInitializeNewClusterLoader" style="height: 350px;"></div>
<div id="divInitializeNewClusterView" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<p>
The initialization of a new Cluster will make the current DNS server its Primary node. You can add other DNS servers to this Cluster later which will get added as Secondary nodes. No data will be lost on this DNS server in this process.
</p>
<div class="form-group">
<label for="txtInitializeNewClusterDomain" class="col-sm-4 control-label">Cluster Domain</label>
<div class="col-sm-7">
<input id="txtInitializeNewClusterDomain" type="text" class="form-control" placeholder="domain name" maxlength="255">
<div style="padding-top: 5px;">The fully qualified domain name to be used to identify the new Cluster.</div>
</div>
</div>
<div class="form-group">
<label for="txtInitializeNewClusterPrimaryNodeIpAddresses" class="col-sm-4 control-label">Primary Node IP Addresses</label>
<div class="col-sm-7">
<textarea id="txtInitializeNewClusterPrimaryNodeIpAddresses" class="form-control" rows="3" spellcheck="false"></textarea>
<label for="optInitializeNewClusterQuickIpAddresses" class="control-label">Quick Add</label>
<select id="optInitializeNewClusterQuickIpAddresses" class="form-control"></select>
<div style="padding-top: 5px;">The static IP addresses of this DNS server that will be accessible by all other DNS Servers to be added later as Secondary nodes.</div>
<div style="padding-top: 5px;">Enter IP addresses one below another in the above text field or use the Quick Add list to add available IP addresses on the server.</div>
</div>
</div>
<p>
<b>Note!</b> When the Cluster is initialized, the DNS Server Domain Name will be changed such that the current hostname is a subdomain name of the Cluster Domain name specified above. For example, if the current DNS Server Domain Name is <code>ns1.mydomain.tld</code> or just <code>ns1</code> then the new domain name will be <code>ns1.mycluster.tld</code>.
</p>
<p>
<b>Note!</b> If the web service does not have HTTPS enabled, then the initialization process will enable it automatically with a self-signed certificate. However, it is recommended to manually configure HTTPS with a valid certificate before initializing the Cluster. This certificate must include the new expected DNS Server Domain Name, as mentioned in the above note, as the Subject Common Name or Subject Alternative Name (SAN) so that it validates when a Secondary node tries to join the Cluster. Once a node joins the Cluster, it uses DANE-EE for server authentication and the domain name in the certificate is no longer required to match the DNS Server Domain Name.
</p>
<p>
<b>Note!</b> The initialization process will create two zones if they do not exist. The first zone will be the Cluster Primary zone named as the Cluster Domain name specified above where the Cluster will automatically manage domain name records for all the nodes. The second zone will be the Cluster Catalog zone that uses <code>cluster-catalog</code> as the subdomain name of the Cluster Domain name. Use this Cluster Catalog zone for automatic provisioning of Secondary zones on all of the Cluster Secondary nodes.
</p>
<p>
<b>Warning!</b> The Cluster Domain name cannot be changed later. Make sure that you enter the correct domain name before proceeding. You can update the DNS Server Domain Name later if needed from Settings but it must always be a subdomain name of the Cluster Domain name.
</p>
</div>
</div>
<div class="modal-footer">
<div class="pull-left">
<a href="https://blog.technitium.com/2025/11/understanding-clustering-and-how-to.html" target="_blank">Help: Understanding Clustering And How To Configure It</a>
</div>
<div class="pull-right">
<button type="submit" class="btn btn-primary" data-loading-text="Working..." onclick="initializeNewCluster(this); return false;">Initialize</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</form>
</div>
<div id="modalInitializeJoinCluster" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Join Cluster</h4>
</div>
<div class="modal-body">
<div id="divInitializeJoinClusterAlert"></div>
<div id="divInitializeJoinClusterLoader" style="height: 500px;"></div>
<div id="divInitializeJoinClusterView" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<p>
Joining a Cluster will make this DNS server its Secondary node. This process will overwrite configuration on this DNS server for Allowed, Blocked, Apps, Settings and Administration sections. The DNS server will automatically synchronize its configuration with the Primary node in the Cluster.
</p>
<div class="form-group">
<label for="txtInitializeJoinClusterSecondaryNodeIpAddresses" class="col-sm-4 control-label">Secondary Node IP Addresses</label>
<div class="col-sm-7">
<textarea id="txtInitializeJoinClusterSecondaryNodeIpAddresses" class="form-control" rows="3" spellcheck="false"></textarea>
<label for="optInitializeJoinClusterQuickIpAddresses" class="control-label">Quick Add</label>
<select id="optInitializeJoinClusterQuickIpAddresses" class="form-control"></select>
<div style="padding-top: 5px;">The static IP addresses of this DNS server that will be accessible by all other DNS Server nodes in the Cluster.</div>
<div style="padding-top: 5px;">Enter IP addresses one below another in the above text field or use the Quick Add list to add available IP addresses on the server.</div>
</div>
</div>
<div class="form-group">
<label for="txtInitializeJoinClusterPrimaryNodeUrl" class="col-sm-4 control-label">Primary Node URL</label>
<div class="col-sm-7">
<input id="txtInitializeJoinClusterPrimaryNodeUrl" type="text" class="form-control" placeholder="URL" maxlength="255">
<div style="padding-top: 5px;">The web service HTTPS URL of the Primary node in the Cluster.</div>
</div>
</div>
<div class="form-group">
<label for="txtInitializeJoinClusterPrimaryNodeIpAddress" class="col-sm-4 control-label">Primary Node IP Address (Optional)</label>
<div class="col-sm-7">
<input id="txtInitializeJoinClusterPrimaryNodeIpAddress" type="text" class="form-control" placeholder="IP address" maxlength="255">
<div style="padding-top: 5px;">The IP address of the Primary node in the Cluster. When unspecified, domain name in the Primary node URL will be resolved and used.</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Certificate Validation</label>
<div class="col-sm-7">
<div class="radio">
<label>
<input type="radio" name="rdInitializeJoinClusterCertificateValidation" id="rdInitializeJoinClusterCertificateValidationDefault" value="false">
Validate Certificate With PKI and DANE (Recommended)
</label>
<div style="padding-top: 5px; padding-left: 20px;">
The Primary node web service TLS certificate will be validated using PKI and DANE to ensure that your connection is secure.
</div>
</div>
<div class="radio">
<label>
<input type="radio" name="rdInitializeJoinClusterCertificateValidation" id="rdInitializeJoinClusterCertificateValidationIgnore" value="true">
Ignore Certificate Validation Errors
</label>
<div style="padding-top: 5px; padding-left: 20px;">
Use this options only when you know that the Primary node web service is using a self-signed TLS certificate and is reachable on a private network.
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="txtInitializeJoinClusterPrimaryNodeUsername" class="col-sm-4 control-label">Primary Node Username</label>
<div class="col-sm-7">
<input id="txtInitializeJoinClusterPrimaryNodeUsername" type="text" class="form-control" placeholder="username" maxlength="255">
<div style="padding-top: 5px;">The username of an administrator on the Primary node in the Cluster.</div>
</div>
</div>
<div class="form-group">
<label for="txtInitializeJoinClusterPrimaryNodePassword" class="col-sm-4 control-label">Primary Node Password</label>
<div class="col-sm-7">
<input id="txtInitializeJoinClusterPrimaryNodePassword" type="password" class="form-control" maxlength="255">
<div style="padding-top: 5px;">The password of the administrator user specified above.</div>
</div>
</div>
<div id="divInitializeJoinClusterPrimaryNode2faTotp" class="form-group">
<label for="txtInitializeJoinClusterPrimaryNode2faTotp" class="col-sm-4 control-label">Primary Node OTP</label>
<div class="col-sm-7">
<input id="txtInitializeJoinClusterPrimaryNode2faTotp" type="text" class="form-control" placeholder="OTP" maxlength="6" autocomplete="off">
<div style="padding-top: 5px;">Enter the 6-digit code you see in your authenticator app for the administrator user specified above.</div>
</div>
</div>
<p>
<b>Note!</b> The process to join the Cluster may take a while to complete depending on the amount of initial config data that needs to be synchronized from the Primary node. Please be patient till the process completes.
</p>
<p>
<b>Note!</b> If the web service does not have HTTPS enabled, then the joining process will enable it automatically with a self-signed certificate. However, its recommended to manually configure HTTPS with a valid certificate before joining the cluster. This certificate should optionally include the new expected DNS Server Domain Name, which will be a subdomain name of the Cluster Domain name, as the Subject Common Name or Subject Alternative Name (SAN).
</p>
<p>
<b>Note!</b> The Ignore Certificate Validation Errors option when selected is used only for the initial connection to the Primary node during the joining process. Once the DNS server joins the Cluster, it will always use DANE-EE for authentication using the TLSA records in the Cluster Primary zone that are added for each node in the Cluster.
</p>
<p>
<b>Warning!</b> Joining a Cluster will cause configuration on this DNS Server to be overwritten permanently for Allowed, Blocked, Apps, Settings and Administration sections!
</p>
</div>
</div>
<div class="modal-footer">
<div class="pull-left">
<a href="https://blog.technitium.com/2025/11/understanding-clustering-and-how-to.html" target="_blank">Help: Understanding Clustering And How To Configure It</a>
</div>
<div class="pull-right">
<button type="submit" class="btn btn-primary" data-loading-text="Joining..." onclick="initializeJoinCluster(this); return false;">Join</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</form>
</div>
<div id="modalClusterOptions" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Cluster Options</h4>
</div>
<div class="modal-body">
<div id="divClusterOptionsAlert"></div>
<div id="divClusterOptionsLoader" style="height: 100px;"></div>
<div id="divClusterOptionsView" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div class="form-group">
<label for="txtClusterOptionsClusterDomain" class="col-sm-4 control-label">Cluster Domain</label>
<div class="col-sm-7">
<input id="txtClusterOptionsClusterDomain" type="text" class="form-control" placeholder="domain name" maxlength="255" disabled>
<div style="padding-top: 5px;">The fully qualified domain name of the Cluster.</div>
</div>
</div>
<div class="form-group">
<label for="txtClusterOptionsHeartbeatRefreshIntervalSeconds" class="col-sm-4 control-label">Heartbeat Refresh Interval</label>
<div class="col-sm-7">
<div>
<input id="txtClusterOptionsHeartbeatRefreshIntervalSeconds" type="number" class="form-control" placeholder="seconds" maxlength="5" style="width: 100px; display: inline;">
<span>seconds (valid range 10-300; default 30)</span>
</div>
<div style="padding-top: 5px;">The interval in seconds in which the DNS server must refresh the state of all nodes in the Cluster.</div>
</div>
</div>
<div class="form-group">
<label for="txtClusterOptionsHeartbeatRetryIntervalSeconds" class="col-sm-4 control-label">Heartbeat Retry Interval</label>
<div class="col-sm-7">
<div>
<input id="txtClusterOptionsHeartbeatRetryIntervalSeconds" type="number" class="form-control" placeholder="seconds" maxlength="5" style="width: 100px; display: inline;">
<span>seconds (valid range 10-300; default 10)</span>
</div>
<div style="padding-top: 5px;">The interval in seconds in which the DNS server must retry the state refresh process for all nodes in case of a failure.</div>
</div>
</div>
<div class="form-group">
<label for="txtClusterOptionsConfigRefreshIntervalSeconds" class="col-sm-4 control-label">Config Refresh Interval</label>
<div class="col-sm-7">
<div>
<input id="txtClusterOptionsConfigRefreshIntervalSeconds" type="number" class="form-control" placeholder="seconds" maxlength="5" style="width: 100px; display: inline;">
<span>seconds (valid range 30-3600; default 900)</span>
</div>
<div style="padding-top: 5px;">The interval in seconds in which the DNS server must refresh the configuration from the Primary node.</div>
</div>
</div>
<div class="form-group">
<label for="txtClusterOptionsConfigRetryIntervalSeconds" class="col-sm-4 control-label">Config Retry Interval</label>
<div class="col-sm-7">
<div>
<input id="txtClusterOptionsConfigRetryIntervalSeconds" type="number" class="form-control" placeholder="seconds" maxlength="5" style="width: 100px; display: inline;">
<span>seconds (valid range 30-3600; default 60)</span>
</div>
<div style="padding-top: 5px;">The interval in seconds in which the DNS server must retry the configuration refresh process for the Primary node in case of a failure.</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnClusterOptionsSave" type="submit" class="btn btn-primary" data-loading-text="Saving..." onclick="saveClusterOptions(this); return false;">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalEditClusterNode" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document" style="width: 780px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Edit Node - <span id="lblEditClusterNodeName">node1.example.com</span></h4>
</div>
<div class="modal-body">
<div id="divEditClusterNodeAlert"></div>
<div id="divEditClusterNodeLoader" style="height: 100px;"></div>
<div id="divEditClusterNodeView" style="max-height: 500px; overflow-y: auto; padding: 0 6px; overflow-x: hidden;">
<div id="divEditClusterNodeSelfNode">
<div class="form-group">
<label for="txtEditClusterNodeSelfNodeIpAddresses" class="col-sm-4 control-label">Node IP Addresses</label>
<div class="col-sm-7">
<textarea id="txtEditClusterNodeSelfNodeIpAddresses" class="form-control" rows="3" spellcheck="false"></textarea>
<label for="optEditClusterNodeQuickSelfIpAddresses" class="control-label">Quick Add</label>
<select id="optEditClusterNodeQuickSelfIpAddresses" class="form-control"></select>
<div style="padding-top: 5px;">The static IP addresses of this DNS server that will be accessible by all other DNS Server nodes in the Cluster.</div>
<div style="padding-top: 5px;">Enter IP addresses one below another in the above text field or use the Quick Add list to add available IP addresses on the server.</div>
</div>
</div>
</div>
<div id="divEditClusterNodePrimaryNode">
<div class="form-group">
<label for="txtEditClusterNodePrimaryNodeUrl" class="col-sm-4 control-label">Primary Node URL</label>
<div class="col-sm-7">
<input id="txtEditClusterNodePrimaryNodeUrl" type="text" class="form-control" placeholder="URL" maxlength="255">
<div style="padding-top: 5px;">The web service HTTPS URL of the Primary node in the Cluster.</div>
</div>
</div>
<div class="form-group">
<label for="txtEditClusterNodePrimaryNodeIpAddresses" class="col-sm-4 control-label">Primary Node IP Addresses (Optional)</label>
<div class="col-sm-7">
<textarea id="txtEditClusterNodePrimaryNodeIpAddresses" class="form-control" rows="3" spellcheck="false"></textarea>
<div style="padding-top: 5px;">The IP addresses of the Primary node in the Cluster. When unspecified, domain name in the Primary node URL will be resolved and used.</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btnEditClusterNodeSave" type="submit" class="btn btn-primary" data-loading-text="Saving...">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalRemoveClusterNode" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Remove Node - <span id="lblRemoveClusterNodeName">node1.example.com</span></h4>
</div>
<div class="modal-body">
<div id="divRemoveClusterNodeAlert"></div>
<p>
The Remove Node process will ask the selected Secondary node to leave the Cluster gracefully. The Secondary will then initiate Leave Cluster process as if the Leave Cluster action was performed on that node itself.
</p>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<div class="checkbox">
<label>
<input id="chkRemoveClusterNodeForceRemove" type="checkbox"> Force Remove Node
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enabling this option will cause the Secondary node to be deleted from the Cluster without asking the node to leave gracefully.</div>
</div>
</div>
<p>
Are you sure you want to remove the Secondary node from the Cluster?
</p>
<p>
<b>Note!</b> Use the Force Remove Node option only when the Secondary node is unreachable/decommissioned and cannot leave the Cluster gracefully.
</p>
</div>
<div class="modal-footer">
<button id="btnRemoveClusterNode" type="submit" class="btn btn-warning" data-loading-text="Removing..." onclick="removeSecondaryClusterNode(this); return false;">Remove</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalPromoteToPrimaryClusterNode" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Promote To Primary Node - <span id="lblPromoteToPrimaryClusterNodeName"></span></h4>
</div>
<div class="modal-body">
<div id="divPromoteToPrimaryClusterNodeAlert"></div>
<p>
The promote To Primary node process will resync complete configuration from the Primary node and then proceed to delete it from the Cluster followed by upgrading the selected Secondary node to become the Primary node in the Cluster. The former Primary node when deleted will cause it to delete all its own Cluster configuration leaving the Cluster without causing any other data loss.
</p>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<div class="checkbox">
<label>
<input id="chkPromoteToPrimaryClusterNodeForceDeletePrimary" type="checkbox"> Force Delete Current Primary Node
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enabling this option will cause the current Primary node to be deleted from the Cluster without resyncing complete configuration from it and without inform it.</div>
</div>
</div>
<p>
Are you sure you want to promote the selected Secondary node to become the Primary node in the Cluster?
</p>
<p>
<b>Note!</b> Use the Force Delete Current Primary Node option only when the Primary node is unreachable/decommissioned and thus cannot be deleted from the Cluster gracefully.
</p>
<p>
<b>Note!</b> The process to promote to Primary node may take a while to complete depending on the size of the complete configuration being resynced and the number of local zones that need to be converted. Please be patient till the process completes.
</p>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-warning" data-loading-text="Promoting..." onclick="promoteToPrimaryClusterNode(this); return false;">Promote</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalLeaveCluster" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Leave Cluster</h4>
</div>
<div class="modal-body">
<div id="divLeaveClusterAlert"></div>
<p>
The Leave Cluster process will remove all Cluster configuration from this Secondary node and leave the Cluster gracefully. There will be no data loss except for the Cluster configuration. You will need to re-join the Cluster again to use this DNS server as a Secondary node.
</p>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<div class="checkbox">
<label>
<input id="chkLeaveClusterForceLeave" type="checkbox"> Force Leave Cluster
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enabling this option will cause this Secondary node to leave the Cluster without informing the Primary node.</div>
</div>
</div>
<p>
Are you sure you want to leave the Cluster?
</p>
<p>
<b>Note!</b> Use the Force Leave Cluster option only when the Primary node is unreachable/decommissioned and thus cannot leave the Cluster gracefully.
</p>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-warning" data-loading-text="Leaving..." onclick="leaveCluster(this); return false;">Leave</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="modalDeleteCluster" class="modal fade" tabindex="-1" role="dialog">
<form class="form-horizontal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Delete Cluster</h4>
</div>
<div class="modal-body">
<div id="divDeleteClusterAlert"></div>
<p>
The Delete Cluster process will remove all Cluster configuration from this Primary node. There will be no data loss except for the Cluster configuration. You will need to re-initialize the Cluster again to use clustering features on this DNS server.
</p>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<div class="checkbox">
<label>
<input id="chkDeleteClusterForceDelete" type="checkbox"> Force Delete Cluster
</label>
</div>
<div style="padding-top: 5px; padding-left: 20px;">Enabling this option will cause this Primary node to delete the Cluster for itself even when other Secondary nodes still exist, orphaning them.</div>
</div>
</div>
<p>
Are you sure you want to delete the Cluster?
</p>
<p>
<b>Note!</b> You can delete the Cluster only when there are no Secondary nodes in the Cluster. Use the Force Delete Cluster option only when you wish this Primary node to be removed from the Cluster even when there are Secondary nodes in the Cluster. In this case, the Secondary nodes will become orphaned and you will need to promote one of them to be the new Primary node manually.
</p>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-danger" data-loading-text="Deleting..." onclick="deleteCluster(this); return false;">Delete</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</form>
</div>
<div id="footer"></div>
</body>
</html>