From 8b13a3b1774a3a72fab005026a61db2d7ca1b383 Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Tue, 18 May 2021 13:28:09 +0200 Subject: [PATCH 01/12] short TTL for DNS entries if config file set --- management/dns_update.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/management/dns_update.py b/management/dns_update.py index 569de9b1..6724b6af 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -470,19 +470,35 @@ def write_nsd_zone(domain, zonefile, records, env, force): zone = """ $ORIGIN {domain}. -$TTL 86400 ; default time to live +$TTL {defttl} ; default time to live @ IN SOA ns1.{primary_domain}. hostmaster.{primary_domain}. ( - __SERIAL__ ; serial number - 7200 ; Refresh (secondary nameserver update interval) - 86400 ; Retry (when refresh fails, how often to try again) - 1209600 ; Expire (when refresh fails, how long secondary nameserver will keep records around anyway) - 86400 ; Negative TTL (how long negative responses are cached) - ) + __SERIAL__ ; serial number + {refresh} ; Refresh (secondary nameserver update interval) + {retry} ; Retry (when refresh fails, how often to try again) + {expire} ; Expire (when refresh fails, how long secondary nameserver will keep records around anyway) + {negttl} ; Negative TTL (how long negative responses are cached) + ) """ + # Default ttl values + p_defttl = 86400 + p_refresh = 7200 + p_retry = 3600 + p_expire = 1209600 + p_negttl = 86400 + + # Shorten dns ttl if file exists. Use just before moving domains, changin secondary dns servers etc + if os.path.exists("/etc/forceshortdnsttl"): + p_defttl = 300 + p_refresh = 3600 + p_retry = 1800 + p_expire = 43200 + p_negttl = 3600 + # Replace replacement strings. - zone = zone.format(domain=domain, primary_domain=env["PRIMARY_HOSTNAME"]) + zone = zone.format(domain=domain, primary_domain=env["PRIMARY_HOSTNAME"], defttl=p_defttl, + refresh=p_refresh, retry=p_retry, expire=p_expire, negttl=p_negttl) # Add records. for subdomain, querytype, value, explanation in records: @@ -620,7 +636,7 @@ def dnssec_choose_algo(domain, env): # A variety of algorithms are supported for .fund. This # is preferred. # Gandi tells me that .be does not support RSASHA1-NSEC3-SHA1 - # Nic.lv does not support RSASHA1-NSEC3-SHA1 for .lv tld's + # Nic.lv does not support RSASHA1-NSEC3-SHA1 for .lv tld's return "RSASHA256" # For any domain we were able to sign before, don't change the algorithm From b9e7175d9f94b7337fa198fa863c23b1be9c5220 Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Tue, 18 May 2021 22:51:29 +0200 Subject: [PATCH 02/12] add principal functionality to act as hidden master --- management/dns_update.py | 55 ++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/management/dns_update.py b/management/dns_update.py index 6724b6af..137bd7b8 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -145,13 +145,20 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en # 'False' in the tuple indicates these records would not be used if the zone # is managed outside of the box. if is_zone: - # Obligatory definition of ns1.PRIMARY_HOSTNAME. - records.append((None, "NS", "ns1.%s." % env["PRIMARY_HOSTNAME"], False)) - # Define ns2.PRIMARY_HOSTNAME or whatever the user overrides. # User may provide one or more additional nameservers - secondary_ns_list = get_secondary_dns(additional_records, mode="NS") \ - or ["ns2." + env["PRIMARY_HOSTNAME"]] + secondary_ns_list = get_secondary_dns(additional_records, mode="NS") + + # Need at least two nameservers in the secondary dns list + useHiddenMaster = os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1 + + if not useHiddenMaster: + # Obligatory definition of ns1.PRIMARY_HOSTNAME. + records.append((None, "NS", "ns1.%s." % env["PRIMARY_HOSTNAME"], False)) + + if len(secondary_ns_list) == 0: + secondary_ns_list = ["ns2." + env["PRIMARY_HOSTNAME"]] + for secondary_ns in secondary_ns_list: records.append((None, "NS", secondary_ns+'.', False)) @@ -466,15 +473,29 @@ def write_nsd_zone(domain, zonefile, records, env, force): # For the refresh through TTL fields, a good reference is: # http://www.peerwisdom.org/2013/05/15/dns-understanding-the-soa-record/ + + # Time To Refresh – How long in seconds a nameserver should wait prior to checking for a Serial Number + # increase within the primary zone file. An increased Serial Number means a transfer is needed to sync + # your records. Only applies to zones using secondary DNS. + # Time To Retry – How long in seconds a nameserver should wait prior to retrying to update a zone after + # a failed attempt. Only applies to zones using secondary DNS. + # Time To Expire – How long in seconds a nameserver should wait prior to considering data from a secondary + # zone invalid and stop answering queries for that zone. Only applies to zones using secondary DNS. + # Minimum TTL – How long in seconds that a nameserver or resolver should cache a negative response. + + # To make use of hidden master initialize the DNS to be used as secondary DNS. Then change the following + # in the zone file: + # - Name the secondary DNS server as primary DNS in the SOA record + # - Do not add NS records for the Mail-in-a-Box server zone = """ $ORIGIN {domain}. $TTL {defttl} ; default time to live -@ IN SOA ns1.{primary_domain}. hostmaster.{primary_domain}. ( +@ IN SOA {primary_dns}. hostmaster.{primary_domain}. ( __SERIAL__ ; serial number - {refresh} ; Refresh (secondary nameserver update interval) + {refresh} ; Refresh (secondary nameserver update interval) {retry} ; Retry (when refresh fails, how often to try again) {expire} ; Expire (when refresh fails, how long secondary nameserver will keep records around anyway) {negttl} ; Negative TTL (how long negative responses are cached) @@ -484,20 +505,28 @@ $TTL {defttl} ; default time to live # Default ttl values p_defttl = 86400 p_refresh = 7200 - p_retry = 3600 + p_retry = 1800 p_expire = 1209600 p_negttl = 86400 + primary_dns = "ns1" + env["PRIMARY_HOSTNAME"] + # Shorten dns ttl if file exists. Use just before moving domains, changin secondary dns servers etc if os.path.exists("/etc/forceshortdnsttl"): p_defttl = 300 p_refresh = 3600 - p_retry = 1800 + p_retry = 900 p_expire = 43200 - p_negttl = 3600 - + p_negttl = 300 + + secondary_ns_list = get_secondary_dns(additional_records, mode="NS") + useHiddenMaster = os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1 + + if useHiddenMaster: + primary_dns = secondary_ns_list[0] + # Replace replacement strings. - zone = zone.format(domain=domain, primary_domain=env["PRIMARY_HOSTNAME"], defttl=p_defttl, + zone = zone.format(domain=domain, primary_dns=primary_dns, primary_domain=env["PRIMARY_HOSTNAME"], defttl=p_defttl, refresh=p_refresh, retry=p_retry, expire=p_expire, negttl=p_negttl) # Add records. @@ -1027,7 +1056,7 @@ def get_custom_dns_records(custom_dns, qname, rtype): def build_recommended_dns(env): ret = [] for (domain, zonefile, records) in build_zones(env): - # remove records that we don't dislay + # remove records that we don't display records = [r for r in records if r[3] is not False] # put Required at the top, then Recommended, then everythiing else From 856d94b74f9ddf584f6087e6bb9f121e74b8eb7e Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Wed, 19 May 2021 21:17:55 +0200 Subject: [PATCH 03/12] use shorthand for ttl periods, more correct secondary ns list handling --- management/dns_update.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/management/dns_update.py b/management/dns_update.py index 137bd7b8..57e10588 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -503,22 +503,23 @@ $TTL {defttl} ; default time to live """ # Default ttl values - p_defttl = 86400 - p_refresh = 7200 - p_retry = 1800 - p_expire = 1209600 - p_negttl = 86400 + p_defttl = "1d" + p_refresh = "2h" + p_retry = "15m" + p_expire = "14d" + p_negttl = "12h" primary_dns = "ns1" + env["PRIMARY_HOSTNAME"] - # Shorten dns ttl if file exists. Use just before moving domains, changin secondary dns servers etc + # Shorten dns ttl if file exists. Use before moving domains, changing secondary dns servers etc if os.path.exists("/etc/forceshortdnsttl"): - p_defttl = 300 - p_refresh = 3600 - p_retry = 900 - p_expire = 43200 - p_negttl = 300 + p_defttl = "5m" + p_refresh = "30m" + p_retry = "5m" + p_expire = "1d" + p_negttl = "5m" + additional_records = list(get_custom_dns_config(env)) secondary_ns_list = get_secondary_dns(additional_records, mode="NS") useHiddenMaster = os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1 From 14394ef05bc1230b7602fba5e6af88565968949f Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Wed, 19 May 2021 22:01:25 +0200 Subject: [PATCH 04/12] add missing . in nameserver definition --- management/dns_update.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/management/dns_update.py b/management/dns_update.py index 57e10588..381af718 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -509,7 +509,7 @@ $TTL {defttl} ; default time to live p_expire = "14d" p_negttl = "12h" - primary_dns = "ns1" + env["PRIMARY_HOSTNAME"] + primary_dns = "ns1." + env["PRIMARY_HOSTNAME"] # Shorten dns ttl if file exists. Use before moving domains, changing secondary dns servers etc if os.path.exists("/etc/forceshortdnsttl"): From 544f06b10042d7ce9a57e847b43c09f6e85f0891 Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Wed, 19 May 2021 22:48:21 +0200 Subject: [PATCH 05/12] document DNS mods and make DNS options configurable per domain --- README.md | 6 +++++- management/dns_update.py | 39 +++++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 7c36a665..36bbd09b 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,14 @@ Functionality changes and additions * Add fail2ban filters for web scanners and badbots * Add xapian full text searching to dovecot (from https://github.com/grosjo/fts-xapian) * Add rkhunter and chkrootkit -* Configure domain names for which only www will be hosted. Edit /etc/miabwwwdomains.conf to configure. +* Configure domain names for which only www will be hosted. Edit /etc/miabwwwdomains.conf to configure. DNS entries are not handled by this box! * Add some munin plugins * Update nextcloud to 20.0.8 * Update roundcube carddav plugin to 4.1.1 +* Use shorter TTL values in the DNS server. + To be used before moving e.g. DNS provider. Shortening TTL values will propagate changes faster. For reference, default TTL is 1 day, short TTL is 5 minutes. To use, edit file /etc/forceshortdnsttl and add a line for each domain for which shorter TTLs should be used. To use short TTLs for all known domains, add "forceshortdnsttl" +* Use the box as a Hidden Master in the DNS system + Thus only the secondary DNS servers are used as public DNS servers. To use, edit file /etc/usehiddenmasterdns and add a line for each domain for which Hidden Master should be used. To use Hidden Master for all known domains, add "usehiddenmasterdns". At least two secondary servers should be set in the Custom DNS administration page. Bug fixes * Munin routes are ignored for Multi Factor Authentication [see github issue](https://github.com/mail-in-a-box/mailinabox/issues/1865) diff --git a/management/dns_update.py b/management/dns_update.py index 381af718..49752516 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -150,7 +150,13 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en secondary_ns_list = get_secondary_dns(additional_records, mode="NS") # Need at least two nameservers in the secondary dns list - useHiddenMaster = os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1 + useHiddenMaster = false + if os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1: + with open("/etc/usehiddenmasterdns") as f: + for line in f: + if line == domain or line == "usehiddenmasterdns": + useHiddenMaster = true + break if not useHiddenMaster: # Obligatory definition of ns1.PRIMARY_HOSTNAME. @@ -162,7 +168,6 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en for secondary_ns in secondary_ns_list: records.append((None, "NS", secondary_ns+'.', False)) - # In PRIMARY_HOSTNAME... if domain == env["PRIMARY_HOSTNAME"]: # Define ns1 and ns2. @@ -509,22 +514,32 @@ $TTL {defttl} ; default time to live p_expire = "14d" p_negttl = "12h" - primary_dns = "ns1." + env["PRIMARY_HOSTNAME"] - # Shorten dns ttl if file exists. Use before moving domains, changing secondary dns servers etc if os.path.exists("/etc/forceshortdnsttl"): - p_defttl = "5m" - p_refresh = "30m" - p_retry = "5m" - p_expire = "1d" - p_negttl = "5m" + with open("/etc/forceshortdnsttl") as f: + for line in f: + if line == domain or line == "forceshortdnsttl": + # Override the ttl values + p_defttl = "5m" + p_refresh = "30m" + p_retry = "5m" + p_expire = "1d" + p_negttl = "5m" + break + primary_dns = "ns1." + env["PRIMARY_HOSTNAME"] + + # Obtain the secondary nameserver list additional_records = list(get_custom_dns_config(env)) secondary_ns_list = get_secondary_dns(additional_records, mode="NS") - useHiddenMaster = os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1 - if useHiddenMaster: - primary_dns = secondary_ns_list[0] + # Using hidden master for a domain if it is configured + if os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1: + with open("/etc/usehiddenmasterdns") as f: + for line in f: + if line == domain or line == "usehiddenmasterdns": + primary_dns = secondary_ns_list[0] + break # Replace replacement strings. zone = zone.format(domain=domain, primary_dns=primary_dns, primary_domain=env["PRIMARY_HOSTNAME"], defttl=p_defttl, From eb990194c7f95c29d1377423a90547ebfe78c3e0 Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Thu, 20 May 2021 20:46:13 +0200 Subject: [PATCH 06/12] no network check vagrant file --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index b1c847d8..aaf7ce9f 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -19,7 +19,7 @@ Vagrant.configure("2") do |config| export PUBLIC_IP=auto export PUBLIC_IPV6=auto export PRIMARY_HOSTNAME=auto - #export SKIP_NETWORK_CHECKS=1 + export SKIP_NETWORK_CHECKS=1 # Start the setup script. cd /vagrant From 6be8ae1e4b1986179dc3fa6c855dec20d5db1bae Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Sat, 22 May 2021 18:47:37 +0200 Subject: [PATCH 07/12] correct use of Pyhton Booleans --- management/dns_update.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/management/dns_update.py b/management/dns_update.py index 49752516..3429db3f 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -150,12 +150,12 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en secondary_ns_list = get_secondary_dns(additional_records, mode="NS") # Need at least two nameservers in the secondary dns list - useHiddenMaster = false + useHiddenMaster = False if os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1: with open("/etc/usehiddenmasterdns") as f: for line in f: if line == domain or line == "usehiddenmasterdns": - useHiddenMaster = true + useHiddenMaster = True break if not useHiddenMaster: From e928b915f4dc73ea0ca5fdc314bea2decaf752bf Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Sun, 23 May 2021 21:47:37 +0200 Subject: [PATCH 08/12] clean strings before comparing --- management/dns_update.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/management/dns_update.py b/management/dns_update.py index 3429db3f..dfb63298 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -154,7 +154,7 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en if os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1: with open("/etc/usehiddenmasterdns") as f: for line in f: - if line == domain or line == "usehiddenmasterdns": + if line.strip() == domain or line.strip() == "usehiddenmasterdns": useHiddenMaster = True break @@ -518,7 +518,7 @@ $TTL {defttl} ; default time to live if os.path.exists("/etc/forceshortdnsttl"): with open("/etc/forceshortdnsttl") as f: for line in f: - if line == domain or line == "forceshortdnsttl": + if line.strip() == domain or line.strip() == "forceshortdnsttl": # Override the ttl values p_defttl = "5m" p_refresh = "30m" @@ -537,7 +537,7 @@ $TTL {defttl} ; default time to live if os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns_list) > 1: with open("/etc/usehiddenmasterdns") as f: for line in f: - if line == domain or line == "usehiddenmasterdns": + if line.strip() == domain or line.strip() == "usehiddenmasterdns": primary_dns = secondary_ns_list[0] break From ee87feb5719a46e82a959a8019042b4289b780b2 Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Mon, 24 May 2021 14:24:09 +0200 Subject: [PATCH 09/12] modify dns TTLs according to recommendations from zonemaster.iis.se --- management/dns_update.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/management/dns_update.py b/management/dns_update.py index 3429db3f..58b12eb4 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -507,10 +507,10 @@ $TTL {defttl} ; default time to live ) """ - # Default ttl values + # Default ttl values, following recomendations from zonemaster.iis.se p_defttl = "1d" - p_refresh = "2h" - p_retry = "15m" + p_refresh = "4h" + p_retry = "1h" p_expire = "14d" p_negttl = "12h" From 1d96be9ea900a41fe219cd82e665a0a27cf21605 Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Mon, 24 May 2021 21:32:13 +0200 Subject: [PATCH 10/12] take hidden master dns into account for the status checks --- management/status_checks.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/management/status_checks.py b/management/status_checks.py index a4e5c55e..916584f7 100755 --- a/management/status_checks.py +++ b/management/status_checks.py @@ -503,7 +503,17 @@ def check_dns_zone(domain, env, output, dns_zonefiles): secondary_ns = custom_secondary_ns or ["ns2." + env['PRIMARY_HOSTNAME']] existing_ns = query_dns(domain, "NS") + correct_ns = "; ".join(sorted(["ns1." + env['PRIMARY_HOSTNAME']] + secondary_ns)) + + # Take hidden master dns into account, the mail-in-a-box is not known as nameserver in that case + if os.path.exists("/etc/usehiddenmasterdns") and len(secondary_ns) > 1: + with open("/etc/usehiddenmasterdns") as f: + for line in f: + if line.strip() == domain or line.strip() == "usehiddenmasterdns": + correct_ns = "; ".join(sorted(secondary_ns)) + break + ip = query_dns(domain, "A") probably_external_dns = False From 45267465b2819c6b8358001daf2baf925aa6d164 Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Mon, 24 May 2021 23:22:50 +0200 Subject: [PATCH 11/12] update readme --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 36bbd09b..af0f8c07 100644 --- a/README.md +++ b/README.md @@ -15,15 +15,17 @@ Functionality changes and additions * Add fail2ban jails for both above mentioned geoipblocking filters * Add fail2ban filters for web scanners and badbots * Add xapian full text searching to dovecot (from https://github.com/grosjo/fts-xapian) -* Add rkhunter and chkrootkit -* Configure domain names for which only www will be hosted. Edit /etc/miabwwwdomains.conf to configure. DNS entries are not handled by this box! +* Add rkhunter and chkrootkit + chkrootkit support is a bit dodgy, creating false positives every now and then, notably on kernel update. +* Configure domain names for which only www will be hosted. + Edit /etc/miabwwwdomains.conf to configure. The box will handle incoming traffic asking for these domain names. The DNS entries are entered in an external DNS provider! If you want this box to handle the DNS entries, simply add a mail alias. (existing functionality of the vanilla Mail-in-a-Box) * Add some munin plugins * Update nextcloud to 20.0.8 * Update roundcube carddav plugin to 4.1.1 * Use shorter TTL values in the DNS server. To be used before moving e.g. DNS provider. Shortening TTL values will propagate changes faster. For reference, default TTL is 1 day, short TTL is 5 minutes. To use, edit file /etc/forceshortdnsttl and add a line for each domain for which shorter TTLs should be used. To use short TTLs for all known domains, add "forceshortdnsttl" * Use the box as a Hidden Master in the DNS system - Thus only the secondary DNS servers are used as public DNS servers. To use, edit file /etc/usehiddenmasterdns and add a line for each domain for which Hidden Master should be used. To use Hidden Master for all known domains, add "usehiddenmasterdns". At least two secondary servers should be set in the Custom DNS administration page. + Thus only the secondary DNS servers are used as public DNS servers. When using a hidden master, no glue records are necessary at your domain hoster. To use, edit file /etc/usehiddenmasterdns and add a line for each domain for which Hidden Master should be used. To use Hidden Master for all known domains, add "usehiddenmasterdns". At least two secondary servers should be set in the Custom DNS administration page. Bug fixes * Munin routes are ignored for Multi Factor Authentication [see github issue](https://github.com/mail-in-a-box/mailinabox/issues/1865) From 97ca4c7f4673e84b5a8927380f8e3b66b89a5daf Mon Sep 17 00:00:00 2001 From: "github@kiekerjan.isdronken.nl" Date: Wed, 26 May 2021 11:20:45 +0200 Subject: [PATCH 12/12] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index af0f8c07..6f84d350 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,9 @@ Functionality changes and additions * Update nextcloud to 20.0.8 * Update roundcube carddav plugin to 4.1.1 * Use shorter TTL values in the DNS server. - To be used before moving e.g. DNS provider. Shortening TTL values will propagate changes faster. For reference, default TTL is 1 day, short TTL is 5 minutes. To use, edit file /etc/forceshortdnsttl and add a line for each domain for which shorter TTLs should be used. To use short TTLs for all known domains, add "forceshortdnsttl" + To be used before for example when changing IP addresses. Shortening TTL values will propagate changes faster. For reference, default TTL is 1 day, short TTL is 5 minutes. To use, edit file /etc/forceshortdnsttl and add a line for each domain for which shorter TTLs should be used. To use short TTLs for all known domains, add "forceshortdnsttl" * Use the box as a Hidden Master in the DNS system - Thus only the secondary DNS servers are used as public DNS servers. When using a hidden master, no glue records are necessary at your domain hoster. To use, edit file /etc/usehiddenmasterdns and add a line for each domain for which Hidden Master should be used. To use Hidden Master for all known domains, add "usehiddenmasterdns". At least two secondary servers should be set in the Custom DNS administration page. + Thus only the secondary DNS servers are used as public DNS servers. When using a hidden master, no glue records are necessary at your domain hoster. To use, first setup secondary DNS servers via the Custom DNS administration page. At least two secondary servers should be set. When that functions, edit file /etc/usehiddenmasterdns and add a line for each domain for which Hidden Master should be used. To use Hidden Master for all known domains, add "usehiddenmasterdns". Bug fixes * Munin routes are ignored for Multi Factor Authentication [see github issue](https://github.com/mail-in-a-box/mailinabox/issues/1865)