diff --git a/CHANGELOG.md b/CHANGELOG.md index a07304b6..6688e676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,29 @@ CHANGELOG ========= +v0.43 (September 1, 2019) +------------------------- + +Security fixes: + +* A security issue was discovered in rsync backups. If you have enabled rsync backups, the file `id_rsa_miab` may have been copied to your backup destination. This file can be used to access your backup destination. If the file was copied to your backup destination, we recommend that you delete the file on your backup destination, delete `/root/.ssh/id_rsa_miab` on your Mail-in-a-Box, then re-run Mail-in-a-Box setup, and re-configure your SSH public key at your backup destination according to the instructions in the Mail-in-a-Box control panel. +* Brute force attack prevention was missing for the managesieve service. + +Setup: + +* Nextcloud was not upgraded properly after restoring Mail-in-a-Box from a backup from v0.40 or earlier. + +Mail: + +* Upgraded Roundcube to 1.3.10. +* Fetch an updated whitelist for greylisting on a monthly basis to reduce the number of delayed incoming emails. + +Control panel: + +* When using secondary DNS, it is now possible to specify a subnet range with the `xfr:` option. +* Fixed an issue when the secondary DNS option is used and the secondary DNS hostname resolves to multiple IP addresses. +* Fix a bug in how a backup configuration error is shown. + v0.42b (August 3, 2019) ----------------------- diff --git a/README.md b/README.md index 79e57083..4582f59c 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ by him: $ curl -s https://keybase.io/joshdata/key.asc | gpg --import gpg: key C10BDD81: public key "Joshua Tauberer " imported - $ git verify-tag v0.42b + $ git verify-tag v0.43 gpg: Signature made ..... using RSA key ID C10BDD81 gpg: Good signature from "Joshua Tauberer " gpg: WARNING: This key is not certified with a trusted signature! @@ -215,7 +215,7 @@ and on his [personal homepage](https://razor.occams.info/). (Of course, if this Checkout the tag corresponding to the most recent release: - $ git checkout v0.42b + $ git checkout v0.43 Begin the installation. diff --git a/conf/fail2ban/filter.d/dovecotimap.conf b/conf/fail2ban/filter.d/dovecotimap.conf index 64b8d944..40fa87a4 100644 --- a/conf/fail2ban/filter.d/dovecotimap.conf +++ b/conf/fail2ban/filter.d/dovecotimap.conf @@ -1,4 +1,4 @@ -# Fail2Ban filter Dovecot authentication and pop3/imap server +# Fail2Ban filter Dovecot authentication and pop3/imap/managesieve server # For Mail-in-a-Box [INCLUDES] @@ -9,7 +9,7 @@ before = common.conf _daemon = (auth|dovecot(-auth)?|auth-worker) -failregex = ^%(__prefix_line)s(pop3|imap)-login: (Info: )?(Aborted login|Disconnected)(: Inactivity)? \(((no auth attempts|auth failed, \d+ attempts)( in \d+ secs)?|tried to use (disabled|disallowed) \S+ auth)\):( user=<\S*>,)?( method=\S+,)? rip=, lip=(\d{1,3}\.){3}\d{1,3}(, TLS( handshaking)?(: Disconnected)?)?(, session=<\S+>)?\s*$ +failregex = ^%(__prefix_line)s(pop3|imap|managesieve)-login: (Info: )?(Aborted login|Disconnected)(: Inactivity)? \(((no auth attempts|auth failed, \d+ attempts)( in \d+ secs)?|tried to use (disabled|disallowed) \S+ auth)\):( user=<\S*>,)?( method=\S+,)? rip=, lip=(\d{1,3}\.){3}\d{1,3}(, TLS( handshaking)?(: Disconnected)?)?(, session=<\S+>)?\s*$ ignoreregex = diff --git a/management/backup.py b/management/backup.py index 93136bf5..11cdbb8a 100755 --- a/management/backup.py +++ b/management/backup.py @@ -15,8 +15,8 @@ from exclusiveprocess import Lock from utils import load_environment, shell, wait_for_service, fix_boto rsync_ssh_options = [ - "--ssh-options='-i /root/.ssh/id_rsa_miab'", - "--rsync-options=-e \"/usr/bin/ssh -oStrictHostKeyChecking=no -oBatchMode=yes -p 22 -i /root/.ssh/id_rsa_miab\"", + "--ssh-options= -i /root/.ssh/id_rsa_miab", + "--rsync-options= -e \"/usr/bin/ssh -oStrictHostKeyChecking=no -oBatchMode=yes -p 22 -i /root/.ssh/id_rsa_miab\"", ] def backup_status(env): @@ -406,7 +406,7 @@ def list_target_files(config): reason = "Provided path {} is invalid.".format(target_path) elif 'Network is unreachable' in listing: reason = "The IP address {} is unreachable.".format(target.hostname) - elif 'Could not resolve hostname': + elif 'Could not resolve hostname' in listing: reason = "The hostname {} cannot be resolved.".format(target.hostname) else: reason = "Unknown error." \ diff --git a/management/dns_update.py b/management/dns_update.py index 7e006d0b..dba6dbc1 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -903,10 +903,14 @@ def set_secondary_dns(hostnames, env): 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.") + if "/" in item[4:]: + v = ipaddress.ip_network(item[4:]) # raises a ValueError if there's a problem + if not isinstance(v, ipaddress.IPv4Network): raise ValueError("That's an IPv6 subnet.") + else: + 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:]) + raise ValueError("'%s' is not an IPv4 address or subnet." % item[4:]) # Set. set_custom_dns_record("_secondary_nameserver", "A", " ".join(hostnames), "set", env) diff --git a/management/status_checks.py b/management/status_checks.py index a172b256..0accebb5 100755 --- a/management/status_checks.py +++ b/management/status_checks.py @@ -486,10 +486,12 @@ def check_dns_zone(domain, env, output, dns_zonefiles): if custom_secondary_ns and not probably_external_dns: for ns in custom_secondary_ns: # We must first resolve the nameserver to an IP address so we can query it. - ns_ip = query_dns(ns, "A") - if not ns_ip: + ns_ips = query_dns(ns, "A") + if not ns_ips: output.print_error("Secondary nameserver %s is not valid (it doesn't resolve to an IP address)." % ns) continue + # Choose the first IP if nameserver returns multiple + ns_ip = ns_ips.split('; ')[0] # Now query it to see what it says about this domain. ip = query_dns(domain, "A", at=ns_ip, nxdomain=None) diff --git a/management/templates/custom-dns.html b/management/templates/custom-dns.html index c838d32a..56facdc9 100644 --- a/management/templates/custom-dns.html +++ b/management/templates/custom-dns.html @@ -90,7 +90,7 @@

Multiple secondary servers can be separated with commas or spaces (i.e., ns2.hostingcompany.com ns3.hostingcompany.com). - To enable zone transfers to additional servers without listing them as secondary nameservers, add xfr:IPADDRESS. + To enable zone transfers to additional servers without listing them as secondary nameservers, add an IP address or subnet using xfr:10.20.30.40 or xfr:10.20.30.40/24.