mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-22 02:17:26 +00:00
clean up multiple secondary nameservers and zone xfr ip addresses
This commit is contained in:
parent
09133c8f59
commit
5dd5fc4a1c
@ -222,14 +222,14 @@ def dns_update():
|
|||||||
@authorized_personnel_only
|
@authorized_personnel_only
|
||||||
def dns_get_secondary_nameserver():
|
def dns_get_secondary_nameserver():
|
||||||
from dns_update import get_custom_dns_config, get_secondary_dns
|
from dns_update import get_custom_dns_config, get_secondary_dns
|
||||||
return json_response({ "hostname": get_secondary_dns(get_custom_dns_config(env)) })
|
return json_response({ "hostnames": get_secondary_dns(get_custom_dns_config(env), mode=None) })
|
||||||
|
|
||||||
@app.route('/dns/secondary-nameserver', methods=['POST'])
|
@app.route('/dns/secondary-nameserver', methods=['POST'])
|
||||||
@authorized_personnel_only
|
@authorized_personnel_only
|
||||||
def dns_set_secondary_nameserver():
|
def dns_set_secondary_nameserver():
|
||||||
from dns_update import set_secondary_dns
|
from dns_update import set_secondary_dns
|
||||||
try:
|
try:
|
||||||
return set_secondary_dns(request.form.get('hostname').split(","), env)
|
return set_secondary_dns([ns.strip() for ns in re.split(r"[, ]+", request.form.get('hostnames') or "") if ns.strip() != ""], env)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return (str(e), 400)
|
return (str(e), 400)
|
||||||
|
|
||||||
|
@ -145,12 +145,10 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en
|
|||||||
|
|
||||||
# Define ns2.PRIMARY_HOSTNAME or whatever the user overrides.
|
# Define ns2.PRIMARY_HOSTNAME or whatever the user overrides.
|
||||||
# User may provide one or more additional nameservers
|
# User may provide one or more additional nameservers
|
||||||
secondary_dns_records = get_secondary_dns(additional_records)
|
secondary_ns_list = get_secondary_dns(additional_records, mode="NS") \
|
||||||
if len(secondary_dns_records) > 0:
|
or ["ns2." + env["PRIMARY_HOSTNAME"]]
|
||||||
for secondary_ns in secondary_dns_records:
|
for secondary_ns in secondary_ns_list:
|
||||||
records.append((None, "NS", secondary_ns+'.', False))
|
records.append((None, "NS", secondary_ns+'.', False))
|
||||||
else:
|
|
||||||
records.append((None, "NS", "ns2." + env["PRIMARY_HOSTNAME"] + '.', False))
|
|
||||||
|
|
||||||
|
|
||||||
# In PRIMARY_HOSTNAME...
|
# In PRIMARY_HOSTNAME...
|
||||||
@ -469,21 +467,8 @@ zone:
|
|||||||
|
|
||||||
# If custom secondary nameservers have been set, allow zone transfers
|
# If custom secondary nameservers have been set, allow zone transfers
|
||||||
# and notifies to them.
|
# and notifies to them.
|
||||||
if get_secondary_dns(additional_records, ['_secondary_nameserver']):
|
for ipaddr in get_secondary_dns(additional_records, mode="xfr"):
|
||||||
for hostname in get_secondary_dns(additional_records):
|
nsdconf += "\n\tnotify: %s NOKEY\n\tprovide-xfr: %s NOKEY\n" % (ipaddr, ipaddr)
|
||||||
# Get the IP address of the nameserver by resolving it.
|
|
||||||
resolver = dns.resolver.get_default_resolver()
|
|
||||||
response = dns.resolver.query(hostname+'.', "A")
|
|
||||||
ipaddr = str(response[0])
|
|
||||||
nsdconf += "\n\tnotify: %s NOKEY\n\tprovide-xfr: %s NOKEY" % (ipaddr, ipaddr)
|
|
||||||
# Some providers use different servers for zone transfers and notifies
|
|
||||||
# such as DNS Made Easy. This allows us to set these IP addresses as well manually
|
|
||||||
# in custom.yaml
|
|
||||||
if get_secondary_dns(additional_records, ["_secondary_notify_xfr"]):
|
|
||||||
for ipaddr in get_secondary_dns(additional_records, ["_secondary_notify_xfr"]):
|
|
||||||
nsdconf += "\n\tnotify: %s NOKEY\n\tprovide-xfr: %s NOKEY" % (ipaddr, ipaddr)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check if the file is changing. If it isn't changing,
|
# Check if the file is changing. If it isn't changing,
|
||||||
# return False to flag that no change was made.
|
# return False to flag that no change was made.
|
||||||
@ -800,29 +785,56 @@ def set_custom_dns_record(qname, rtype, value, action, env):
|
|||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
def get_secondary_dns(custom_dns, dns_type=['_secondary_nameserver']):
|
def get_secondary_dns(custom_dns, mode=None):
|
||||||
valid_types = set(['_secondary_nameserver', '_secondary_notify_xfr'])
|
resolver = dns.resolver.get_default_resolver()
|
||||||
if not valid_types.issuperset(set(dns_type)):
|
|
||||||
raise ValueError("Valid types are one or more of the following: %s" % ", ".join(valid_types))
|
|
||||||
|
|
||||||
values = []
|
values = []
|
||||||
for qname, rtype, value in custom_dns:
|
for qname, rtype, value in custom_dns:
|
||||||
if qname in dns_type:
|
if qname != '_secondary_nameserver': continue
|
||||||
if isinstance(value, str):
|
for hostname in value.split(" "):
|
||||||
values.append(value)
|
hostname = hostname.strip()
|
||||||
|
if mode == None:
|
||||||
|
# Just return the setting.
|
||||||
|
values.append(hostname)
|
||||||
|
|
||||||
|
# This is a hostname. Before including in zone xfr lines,
|
||||||
|
# resolve to an IP address. Otherwise just return the hostname.
|
||||||
|
if not hostname.startswith("xfr:"):
|
||||||
|
if mode == "xfr":
|
||||||
|
response = dns.resolver.query(hostname+'.', "A")
|
||||||
|
hostname = str(response[0])
|
||||||
|
values.append(hostname)
|
||||||
|
|
||||||
|
# This is a zone-xfer-only IP address. Do not return if
|
||||||
|
# we're querying for NS record hostnames. Only return if
|
||||||
|
# we're querying for zone xfer IP addresses - return the
|
||||||
|
# IP address.
|
||||||
|
elif mode == "xfr":
|
||||||
|
values.append(hostname[4:])
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def set_secondary_dns(hostname, env):
|
def set_secondary_dns(hostnames, env):
|
||||||
hostnames = [item.strip().lower() for item in hostname]
|
|
||||||
if len(hostnames) > 0:
|
if len(hostnames) > 0:
|
||||||
|
# Validate that all hostnames are valid and that all zone-xfer IP addresses are valid.
|
||||||
resolver = dns.resolver.get_default_resolver()
|
resolver = dns.resolver.get_default_resolver()
|
||||||
for item in hostnames:
|
for item in hostnames:
|
||||||
|
if not item.startswith("xfr:"):
|
||||||
|
# Resolve hostname.
|
||||||
try:
|
try:
|
||||||
response = dns.resolver.query(item, "A")
|
response = dns.resolver.query(item, "A")
|
||||||
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
||||||
raise ValueError("Could not resolve the IP address of %s." % item)
|
raise ValueError("Could not resolve the IP address of %s." % item)
|
||||||
|
else:
|
||||||
|
# Validate IP address.
|
||||||
|
try:
|
||||||
|
v = ipaddress.ip_address(item[4:]) # raises a ValueError if there's a problem
|
||||||
|
if not isinstance(v, ipaddress.IPv4Address): raise ValueError("That's an IPv6 address.")
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("'%s' is not an IPv4 address." % item[4:])
|
||||||
|
|
||||||
# Set.
|
# Set.
|
||||||
set_custom_dns_record("_secondary_nameserver", "A", {"A":hostnames}, "set", env)
|
set_custom_dns_record("_secondary_nameserver", "A", " ".join(hostnames), "set", env)
|
||||||
else:
|
else:
|
||||||
# Clear.
|
# Clear.
|
||||||
set_custom_dns_record("_secondary_nameserver", "A", None, "set", env)
|
set_custom_dns_record("_secondary_nameserver", "A", None, "set", env)
|
||||||
|
@ -370,7 +370,7 @@ def check_dns_zone(domain, env, output, dns_zonefiles):
|
|||||||
# the TLD, and so we're not actually checking the TLD. For that we'd need
|
# the TLD, and so we're not actually checking the TLD. For that we'd need
|
||||||
# to do a DNS trace.
|
# to do a DNS trace.
|
||||||
ip = query_dns(domain, "A")
|
ip = query_dns(domain, "A")
|
||||||
secondary_ns = get_secondary_dns(get_custom_dns_config(env)) or ["ns2." + env['PRIMARY_HOSTNAME']]
|
secondary_ns = get_secondary_dns(get_custom_dns_config(env), mode="NS") or ["ns2." + env['PRIMARY_HOSTNAME']]
|
||||||
existing_ns = query_dns(domain, "NS")
|
existing_ns = query_dns(domain, "NS")
|
||||||
correct_ns = "; ".join(sorted(["ns1." + env['PRIMARY_HOSTNAME']] + secondary_ns))
|
correct_ns = "; ".join(sorted(["ns1." + env['PRIMARY_HOSTNAME']] + secondary_ns))
|
||||||
if existing_ns.lower() == correct_ns.lower():
|
if existing_ns.lower() == correct_ns.lower():
|
||||||
|
@ -67,7 +67,8 @@
|
|||||||
|
|
||||||
<h3>Using a Secondary Nameserver</h3>
|
<h3>Using a Secondary Nameserver</h3>
|
||||||
|
|
||||||
<p>If your TLD requires you to have two separate nameservers, you can either set up a secondary (aka “slave”) nameserver or, alternatively, set up <a href="#" onclick="return show_panel('external_dns')">external DNS</a> and ignore the DNS server on this box. If you choose to use a seconday/slave nameserver, you must find a seconday/slave nameserver service provider. Your domain name registrar or virtual cloud provider may provide this service for you. Once you set up the seconday/slave nameserver service, enter the hostname of <em>their</em> secondary nameserver (multiple secondaries can be added separated with commas i.e. ns2.hostingcompany.com,ns3.hostingcompany.com):</p>
|
<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 seconday nameserver, you must find a seconday nameserver service provider. Your domain name registrar or virtual cloud provider may provide this service for you. Once you set up the seconday 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;">
|
<form class="form-horizontal" role="form" onsubmit="do_set_secondary_dns(); return false;">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -83,7 +84,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="secondarydns-clear-instructions" class="form-group" style="display: none">
|
<div id="secondarydns-clear-instructions" class="form-group" style="display: none">
|
||||||
<div class="col-sm-offset-1 col-sm-11">
|
<div class="col-sm-offset-1 col-sm-11">
|
||||||
<p 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>
|
<p class="small">
|
||||||
|
Multiple secondary servers can be separated with commas or spaces (i.e., <code>ns2.hostingcompany.com ns3.hostingcompany.com</code>).
|
||||||
|
To enable zone transfers to additional servers without listing them as secondary nameservers, add <code>xfr:IPADDRESS</code>.
|
||||||
|
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>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -152,8 +157,8 @@ function show_custom_dns() {
|
|||||||
"GET",
|
"GET",
|
||||||
{ },
|
{ },
|
||||||
function(data) {
|
function(data) {
|
||||||
$('#secondarydnsHostname').val(data.hostname ? data.hostname : '');
|
$('#secondarydnsHostname').val(data.hostnames.join(' '));
|
||||||
$('#secondarydns-clear-instructions').toggle(data.hostname != null);
|
$('#secondarydns-clear-instructions').toggle(data.hostnames.length > 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
api(
|
api(
|
||||||
@ -210,7 +215,7 @@ function do_set_secondary_dns() {
|
|||||||
"/dns/secondary-nameserver",
|
"/dns/secondary-nameserver",
|
||||||
"POST",
|
"POST",
|
||||||
{
|
{
|
||||||
hostname: $('#secondarydnsHostname').val()
|
hostnames: $('#secondarydnsHostname').val()
|
||||||
},
|
},
|
||||||
function(data) {
|
function(data) {
|
||||||
if (data == "") return; // nothing updated
|
if (data == "") return; // nothing updated
|
||||||
|
Loading…
Reference in New Issue
Block a user