374 lines
14 KiB
HTML
374 lines
14 KiB
HTML
<style>
|
|
#custom-dns-current td.long {
|
|
word-break: break-all;
|
|
}
|
|
</style>
|
|
|
|
<h2>Custom DNS</h2>
|
|
|
|
<p class="text-warning">This is an advanced configuration page.</p>
|
|
|
|
<p>It is possible to set custom DNS records on domains hosted here.</p>
|
|
|
|
<h3>Set custom DNS records</h3>
|
|
|
|
<p>You can set additional DNS records, such as if you have a website running on another server, to add DKIM records for
|
|
external mail providers, or for various confirmation-of-ownership tests.</p>
|
|
|
|
<form class="form-horizontal" role="form" onsubmit="do_set_custom_dns(); return false;">
|
|
<div class="col-lg-10 col-xl-7 mb-3">
|
|
<div class="input-group">
|
|
<label class="input-group-text">Name</label>
|
|
<input type="text" class="form-control" id="customdnsQname" placeholder="subdomain">
|
|
<label class="input-group-text">.</label>
|
|
<select id="customdnsZone" class="form-select"></select>
|
|
</div>
|
|
<small>Leave the left field blank to set a record on the chosen domain name, or enter a subdomain.</small>
|
|
</div>
|
|
<div class="col-lg-10 col-xl-7 mb-3">
|
|
<div class="input-group">
|
|
<label for="customdnsType" class="input-group-text">Type</label>
|
|
<select id="customdnsType" class="form-select" onchange="show_customdns_rtype_hint()">
|
|
<option value="A"
|
|
data-hint="Enter an IPv4 address (i.e. a dotted quad, such as 123.456.789.012). The 'local' alias sets the record to this box's public IPv4 address.">
|
|
A (IPv4 address)</option>
|
|
<option value="AAAA"
|
|
data-hint="Enter an IPv6 address. The 'local' alias sets the record to this box's public IPv6 address.">
|
|
AAAA (IPv6 address)</option>
|
|
<option value="CAA"
|
|
data-hint="Enter a CA that can issue certificates for this domain in the form of FLAG TAG VALUE. (0 issuewild "letsencrypt.org")">
|
|
CAA (Certificate Authority Authorization)</option>
|
|
<option value="CNAME"
|
|
data-hint="Enter another domain name followed by a period at the end (e.g. mypage.github.io.).">
|
|
CNAME (DNS forwarding)</option>
|
|
<option value="TXT" data-hint="Enter arbitrary text.">TXT (text record)</option>
|
|
<option value="MX"
|
|
data-hint="Enter record in the form of PRIORITY DOMAIN., including trailing period (e.g. 20 mx.example.com.).">
|
|
MX (mail exchanger)</option>
|
|
<option value="SRV"
|
|
data-hint="Enter record in the form of PRIORITY WEIGHT PORT TARGET., including trailing period (e.g. 10 10 5060 sip.example.com.).">
|
|
SRV (service record)</option>
|
|
<option value="SSHFP" data-hint="Enter record in the form of ALGORITHM TYPE FINGERPRINT.">SSHFP (SSH
|
|
fingerprint record)</option>
|
|
<option value="NS" data-hint="Enter a hostname to which this subdomain should be delegated to">NS (DNS
|
|
subdomain delegation)</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-10 col-xl-7 mb-3">
|
|
<div class="input-group">
|
|
<label for="customdnsValue" class="input-group-text">Value</label>
|
|
<input type="text" class="form-control" id="customdnsValue" placeholder="">
|
|
<label for="customdnsTtl" class="input-group-text">TTL</label>
|
|
<input type="number" class="form-control" id="customdnsTtl" placeholder="default">
|
|
</div>
|
|
<small id="customdnsTypeHint" class="text-info" style="margin-top: .5em"></small>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary mb-3">Set Record</button>
|
|
</form>
|
|
|
|
<div style="font-size: 90%;">
|
|
<b>Sort by:</b>
|
|
<a href="#"
|
|
onclick="window.miab_custom_dns_data_sort_order='qname'; show_current_custom_dns_update_after_sort(); return false;">Domain
|
|
name</a>
|
|
<b>|</b>
|
|
<a href="#"
|
|
onclick="window.miab_custom_dns_data_sort_order='created'; show_current_custom_dns_update_after_sort(); return false;">Created</a>
|
|
</div>
|
|
<table id="custom-dns-current" class="table col-12" style="display: none; margin-top: 0;">
|
|
<caption></caption>
|
|
<thead>
|
|
<th>Domain Name</th>
|
|
<th>Record Type</th>
|
|
<th>Value</th>
|
|
<th>TTL</th>
|
|
<th></th>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td colspan="5">Loading...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h3>Using a secondary nameserver</h3>
|
|
|
|
<p>If your TLD requires you to have two separate nameservers, you can either set up <a href="#"
|
|
onclick="return show_panel('external_dns')">external DNS</a> and ignore the DNS server on this box entirely, or
|
|
use the DNS server on this box but add a secondary (aka “slave”) nameserver.</p>
|
|
<p>If you choose to use a secondary nameserver, you must find a secondary nameserver service provider. Your domain name
|
|
registrar or virtual cloud provider may provide this service for you. Once you set up the secondary nameserver
|
|
service, enter the hostname (not the IP address) of <em>their</em> secondary nameserver in the box below.</p>
|
|
|
|
<form class="form-horizontal" role="form" onsubmit="do_set_secondary_dns(); return false;">
|
|
<div class="col-12 form-floating mb-3">
|
|
<textarea type="text" class="form-control font-monospace" id="secondarydnsHostname"
|
|
placeholder="ns1.example.com"></textarea>
|
|
<label for="secondarydnsHostname">Secondary Nameservers</label>
|
|
<div>
|
|
<p class="small">
|
|
Multiple secondary servers can be separated with commas or spaces (i.e., <span
|
|
class="font-monospace">ns2.hostingcompany.com ns3.hostingcompany.com</span>).
|
|
To enable zone transfers to additional servers without listing them as secondary nameservers, add an IP
|
|
address or subnet using <span class="font-monospace">xfr:10.20.30.40</span> or <span
|
|
class="font-monospace">xfr:10.0.0.0/8</span>.
|
|
</p>
|
|
<p id="secondarydns-clear-instructions" style="display: none" class="small">
|
|
Clear the input field above and click Update to use this machine itself as secondary DNS, which is the
|
|
default/normal setup.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary">Update</button>
|
|
</form>
|
|
|
|
|
|
<h3>Custom DNS API</h3>
|
|
|
|
<p>Use your box’s DNS API to set custom DNS records on domains hosted here. For instance, you can create your own
|
|
dynamic DNS service.</p>
|
|
|
|
<p>Usage:</p>
|
|
|
|
<pre>curl -X <b>VERB</b> [-d "<b>value</b>"] --user {email}:{password} https://{{hostname}}/admin/dns/custom[/<b>qname</b>[/<b>rtype</b>]]</pre>
|
|
|
|
<p>(Brackets denote an optional argument.)</p>
|
|
|
|
<h4>Verbs</h4>
|
|
|
|
<table class="table">
|
|
<caption></caption>
|
|
<thead>
|
|
<th>Verb</th>
|
|
<th>Usage</th>
|
|
</thead>
|
|
<tr>
|
|
<td class="font-monospace"><b>GET</b></td>
|
|
<td>Returns matching custom DNS records as a JSON array of objects. Each object has the keys <code>qname</code>,
|
|
<code>rtype</code>, and <code>value</code>. The optional <code>qname</code> and <code>rtype</code>
|
|
parameters in the request URL filter the records returned in the response. The request body
|
|
(<code>-d "..."</code>) must be omitted.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="font-monospace"><b>PUT</b></td>
|
|
<td>Sets a custom DNS record replacing any existing records with the same <code>qname</code> and
|
|
<code>rtype</code>. Use PUT (instead of POST) when you only have one value for a <code>qname</code> and
|
|
<code>rtype</code>, such as typical <code>A</code> records (without round-robin).</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="font-monospace"><b>POST</b></td>
|
|
<td>Adds a new custom DNS record. Use POST when you have multiple <code>TXT</code> records or round-robin
|
|
<code>A</code> records. (PUT would delete previously added records.)</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="font-monospace"><b>DELETE</b></td>
|
|
<td>Deletes custom DNS records. If the request body (<code>-d "..."</code>) is empty or omitted, deletes all
|
|
records matching the <code>qname</code> and <code>rtype</code>. If the request body is present, deletes only
|
|
the record matching the <code>qname</code>, <code>rtype</code> and value.</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h4>Parameters</h4>
|
|
|
|
<table class="table">
|
|
<caption></caption>
|
|
<thead>
|
|
<th>Parameter</th>
|
|
<th>Value</th>
|
|
</thead>
|
|
<tr>
|
|
<td class="font-monospace"><b>email</b></td>
|
|
<td>The email address of any administrative user here.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="font-monospace"><b>password</b></td>
|
|
<td>That user’s password.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="font-monospace"><b>qname</b></td>
|
|
<td>The fully qualified domain name for the record you are trying to set. It must be one of the domain names or
|
|
a subdomain of one of the domain names hosted on this box. (Add mail users or aliases to add new domains.)
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="font-monospace"><b>rtype</b></td>
|
|
<td>The resource type. Defaults to <code>A</code> if omitted. Possible values: <code>A</code> (an IPv4 address),
|
|
<code>AAAA</code> (an IPv6 address), <code>TXT</code> (a text string), <code>CNAME</code> (an alias, which
|
|
is a fully qualified domain name — don’t forget the final period), <code>MX</code>,
|
|
<code>SRV</code>, <code>SSHFP</code>, <code>CAA</code> or <code>NS</code>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="font-monospace"><b>value</b></td>
|
|
<td>For PUT, POST, and DELETE, the record’s value. If the <code>rtype</code> is <code>A</code> or
|
|
<code>AAAA</code> and <code>value</code> is empty or omitted, the IPv4 or IPv6 address of the remote host is
|
|
used (be sure to use the <code>-4</code> or <code>-6</code> options to curl). This is handy for dynamic DNS!
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p>Strict <a href="http://tools.ietf.org/html/rfc4408">SPF</a> and <a
|
|
href="https://datatracker.ietf.org/doc/draft-kucherawy-dmarc-base/?include_text=1">DMARC</a> records will be
|
|
added to all custom domains unless you override them.</p>
|
|
|
|
<h4>Examples:</h4>
|
|
|
|
<p>Try these examples. For simplicity the examples omit the <code>--user me@mydomain.com:yourpassword</code> command
|
|
line argument which you must fill in with your email address and password.</p>
|
|
|
|
<pre># sets laptop.mydomain.com to point to the IP address of the machine you are executing curl on
|
|
curl -X PUT https://{{hostname}}/admin/dns/custom/laptop.mydomain.com
|
|
|
|
# deletes that record and all A records for that domain name
|
|
curl -X DELETE https://{{hostname}}/admin/dns/custom/laptop.mydomain.com
|
|
|
|
# sets a CNAME alias
|
|
curl -X PUT -d "bar.mydomain.com." https://{{hostname}}/admin/dns/custom/foo.mydomain.com/cname
|
|
|
|
# deletes that CNAME and all CNAME records for that domain name
|
|
curl -X DELETE https://{{hostname}}/admin/dns/custom/foo.mydomain.com/cname
|
|
|
|
# adds a TXT record using POST to preserve any previous TXT records
|
|
curl -X POST -d "some text here" https://{{hostname}}/admin/dns/custom/foo.mydomain.com/txt
|
|
|
|
# deletes that one TXT record while preserving other TXT records
|
|
curl -X DELETE -d "some text here" https://{{hostname}}/admin/dns/custom/foo.mydomain.com/txt
|
|
</pre>
|
|
|
|
<script>
|
|
function show_custom_dns() {
|
|
api(
|
|
"/dns/secondary-nameserver",
|
|
"GET",
|
|
{},
|
|
function (data) {
|
|
$('#secondarydnsHostname').val(data.hostnames.join(' '));
|
|
$('#secondarydns-clear-instructions').toggle(data.hostnames.length > 0);
|
|
});
|
|
|
|
api(
|
|
"/dns/zones",
|
|
"GET",
|
|
{},
|
|
function (data) {
|
|
$('#customdnsZone').text('');
|
|
for (var i = 0; i < data.length; i++) {
|
|
$('#customdnsZone').append($('<option/>').text(data[i]));
|
|
}
|
|
});
|
|
|
|
show_current_custom_dns();
|
|
show_customdns_rtype_hint();
|
|
}
|
|
|
|
function show_current_custom_dns() {
|
|
api(
|
|
"/dns/custom",
|
|
"GET",
|
|
{},
|
|
function (data) {
|
|
if (data.length > 0)
|
|
$('#custom-dns-current').fadeIn();
|
|
else
|
|
$('#custom-dns-current').fadeOut();
|
|
window.miab_custom_dns_data = data;
|
|
show_current_custom_dns_update_after_sort();
|
|
});
|
|
}
|
|
|
|
function show_current_custom_dns_update_after_sort() {
|
|
var data = window.miab_custom_dns_data;
|
|
var sort_key = window.miab_custom_dns_data_sort_order || "qname";
|
|
|
|
data.sort(function (a, b) { return a["sort-order"][sort_key] - b["sort-order"][sort_key] });
|
|
|
|
var tbody = $('#custom-dns-current').find("tbody");
|
|
tbody.text('');
|
|
var last_zone = null;
|
|
for (var i = 0; i < data.length; i++) {
|
|
if (sort_key == "qname" && data[i].zone != last_zone) {
|
|
var r = $("<tr><th colspan=5 class='bg-light'></th></tr>");
|
|
r.find("th").text(data[i].zone);
|
|
tbody.append(r);
|
|
last_zone = data[i].zone;
|
|
}
|
|
|
|
var tr = $("<tr/>");
|
|
tbody.append(tr);
|
|
tr.attr('data-qname', data[i].qname);
|
|
tr.attr('data-rtype', data[i].rtype);
|
|
tr.attr('data-value', data[i].value);
|
|
tr.append($('<td class="long"/>').text(data[i].qname));
|
|
tr.append($('<td/>').text(data[i].rtype));
|
|
tr.append($('<td class="long font-monospace" style="max-width: 40em"/>').text(data[i].value));
|
|
if (data[i].ttl) {
|
|
tr.append($('<td/>').text(data[i].ttl));
|
|
} else {
|
|
tr.append($('<td/>').html('<i class="">default</i>'));
|
|
}
|
|
tr.append($('<td class="col-1">[<a href="#" onclick="return delete_custom_dns_record(this)">delete</a>]</td>'));
|
|
}
|
|
}
|
|
|
|
function delete_custom_dns_record(elem) {
|
|
var qname = $(elem).parents('tr').attr('data-qname');
|
|
var rtype = $(elem).parents('tr').attr('data-rtype');
|
|
var value = $(elem).parents('tr').attr('data-value');
|
|
do_set_custom_dns(qname, rtype, value, "DELETE");
|
|
return false;
|
|
}
|
|
|
|
function do_set_secondary_dns() {
|
|
api(
|
|
"/dns/secondary-nameserver",
|
|
"POST",
|
|
{
|
|
hostnames: $('#secondarydnsHostname').val()
|
|
},
|
|
function (data) {
|
|
if (data == "") return; // nothing updated
|
|
show_modal_error("Secondary DNS", $("<pre/>").text(data));
|
|
$('#secondarydns-clear-instructions').slideDown();
|
|
},
|
|
function (err) {
|
|
show_modal_error("Secondary DNS", $("<pre/>").text(err));
|
|
});
|
|
}
|
|
|
|
function do_set_custom_dns(qname, rtype, value, method) {
|
|
if (!qname) {
|
|
if ($('#customdnsQname').val() != '')
|
|
qname = $('#customdnsQname').val() + '.' + $('#customdnsZone').val();
|
|
else
|
|
qname = $('#customdnsZone').val();
|
|
rtype = $('#customdnsType').val();
|
|
value = {
|
|
value: $('#customdnsValue').val(),
|
|
ttl: $('#customdnsTtl').val()
|
|
};
|
|
method = 'POST';
|
|
} else {
|
|
value = {
|
|
value: value
|
|
}
|
|
}
|
|
|
|
api(
|
|
"/dns/custom/" + qname + "/" + rtype,
|
|
method,
|
|
value,
|
|
function (data) {
|
|
if (data == "") return; // nothing updated
|
|
show_modal_error("Custom DNS", $("<pre/>").text(data));
|
|
show_current_custom_dns();
|
|
},
|
|
function (err) {
|
|
show_modal_error("Custom DNS (Error)", $("<pre/>").text(err));
|
|
});
|
|
}
|
|
|
|
function show_customdns_rtype_hint() {
|
|
$('#customdnsTypeHint').text($("#customdnsType").find('option:selected').attr('data-hint'));
|
|
}
|
|
</script>
|