email: postfix: dovecot: Set strong security parameters

Other changes:
- Fix linter error
- Postfix port 25: do not trust localhost IP addresses
This commit is contained in:
fliu 2021-08-11 22:35:11 +00:00 committed by Sunil Mohan Adapa
parent b172b0b1cd
commit 9a98ddadd4
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
6 changed files with 123 additions and 3 deletions

View File

@ -1,6 +1,8 @@
"""FreedomBox email server app"""
# SPDX-License-Identifier: AGPL-3.0-or-later
import logging
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
@ -10,7 +12,9 @@ import plinth.frontpage
import plinth.menu
from plinth import actions
from plinth.modules.apache.components import Webserver
from plinth.modules.config import get_domainname
from plinth.modules.firewall.components import Firewall
from plinth.modules.letsencrypt.components import LetsEncrypt
from . import audit
from . import manifest
@ -36,6 +40,7 @@ managed_services = ['postfix', 'dovecot', 'rspamd']
managed_packages = packages + packages_bloat
app = None
logger = logging.getLogger(__name__)
class EmailServerApp(plinth.app.App):
@ -56,6 +61,18 @@ class EmailServerApp(plinth.app.App):
urls=['https://{host}/rspamd'])
self.add(webserver)
# Let's Encrypt event hook
default_domain = get_domainname()
domains = [default_domain] if default_domain else []
letsencrypt = LetsEncrypt(
'letsencrypt-email-server', domains=domains,
daemons=['postfix', 'dovecot'], should_copy_certificates=False,
managing_app='email_server')
self.add(letsencrypt)
if not domains:
logger.warning('Could not fetch the FreedomBox domain name!')
def _add_ui_components(self):
info = plinth.app.Info(
app_id=self.app_id,
@ -119,6 +136,7 @@ class EmailServerApp(plinth.app.App):
results.extend([r.summarize() for r in audit.domain.get()])
results.extend([r.summarize() for r in audit.ldap.get()])
results.extend([r.summarize() for r in audit.spam.get()])
results.extend([r.summarize() for r in audit.tls.get()])
return results
@ -128,6 +146,7 @@ def setup(helper, old_version=None):
helper.install(packages_bloat, skip_recommends=True)
helper.call('post', audit.ldap.repair)
helper.call('post', audit.spam.repair)
helper.call('post', audit.tls.repair)
for srvname in managed_services:
actions.superuser_run('service', ['reload', srvname])
# Final step: expose service daemons to public internet

View File

@ -126,7 +126,7 @@ def schedule_hash_update():
key = alias.email_name.encode('ascii') + b'\0'
if alias.enabled:
value = str(alias.uid_number).encode('ascii')
value += b'@localhost\0'
value += b'@localhost\0'
else:
value = b'/dev/null\0'
db[key] = value

View File

@ -7,5 +7,6 @@ from . import domain
from . import home
from . import ldap
from . import spam
from . import tls
__all__ = ['domain', 'home', 'ldap', 'spam']
__all__ = ['domain', 'home', 'ldap', 'spam', 'tls']

View File

@ -15,7 +15,11 @@ default_config = {
'smtpd_sasl_type': 'dovecot',
'smtpd_sasl_path': 'private/auth',
'mailbox_transport': 'lmtp:unix:private/dovecot-lmtp',
'virtual_transport': 'lmtp:unix:private/dovecot-lmtp'
'virtual_transport': 'lmtp:unix:private/dovecot-lmtp',
'smtpd_relay_restrictions': ','.join([
'permit_sasl_authenticated', 'defer_unauth_destination',
])
}
submission_flags = postconf.ServiceFlags(

View File

@ -0,0 +1,84 @@
"""TLS configuration"""
# SPDX-License-Identifier: AGPL-3.0-or-later
import logging
from plinth import actions
from . import models
from plinth.modules.email_server import postconf
# Mozilla Guideline v5.6, Postfix 1.17.7, OpenSSL 1.1.1d, intermediate
# Generated 2021-08
# https://ssl-config.mozilla.org/
tls_medium_cipherlist = [
'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES128-GCM-SHA256',
'ECDHE-ECDSA-AES256-GCM-SHA384', 'ECDHE-RSA-AES256-GCM-SHA384',
'ECDHE-ECDSA-CHACHA20-POLY1305', 'ECDHE-RSA-CHACHA20-POLY1305',
'DHE-RSA-AES128-GCM-SHA256', 'DHE-RSA-AES256-GCM-SHA384'
]
postfix_config = {
# Enable TLS
'smtpd_tls_security_level': 'may',
'smtpd_tls_auth_only': 'yes',
# Debugging information
'smtpd_tls_received_header': 'yes',
# Use a strong hashing algorithm
'smtp_tls_fingerprint_digest': 'sha256',
'smtpd_tls_fingerprint_digest': 'sha256',
# Mozilla Intermediate Configuration
'smtpd_tls_mandatory_protocols': '!SSLv2, !SSLv3, !TLSv1, !TLSv1.1',
'smtpd_tls_protocols': '!SSLv2, !SSLv3, !TLSv1, !TLSv1.1',
'smtpd_tls_mandatory_ciphers': 'medium',
'tls_medium_cipherlist': ':'.join(tls_medium_cipherlist),
'tls_preempt_cipherlist': 'no',
# Postfix SMTP client
'smtp_tls_mandatory_protocols': '!SSLv2, !SSLv3, !TLSv1, !TLSv1.1',
'smtp_tls_protocols': '!SSLv2, !SSLv3, !TLSv1, !TLSv1.1',
'smtp_tls_mandatory_ciphers': 'medium',
# Use DNSSEC to validate TLS certificates
'smtp_host_lookup': 'dns',
'smtp_dns_support_level': 'dnssec',
'smtp_tls_security_level': 'dane', # Opportunistic DANE TLS
# Maintain 1 cipherlist and keep it the most secure
'tls_low_cipherlist': '$tls_medium_cipherlist',
'tls_high_cipherlist': '$tls_medium_cipherlist',
}
logger = logging.getLogger(__name__)
def get():
results = []
with postconf.mutex.lock_all():
results.append(check_tls())
return results
def repair():
actions.superuser_run('email_server', ['-i', 'tls', 'set_up'])
def check_tls():
diagnosis = models.MainCfDiagnosis('Postfix TLS')
current = postconf.get_many_unsafe(list(postfix_config.keys()))
diagnosis.compare_and_advise(current=current, default=postfix_config)
return diagnosis
def repair_tls(diagnosis):
diagnosis.assert_resolved()
logger.info('Setting postconf: %r', diagnosis.advice)
postconf.set_many_unsafe(diagnosis.advice)
def action_set_up():
with postconf.mutex.lock_all():
repair_tls(check_tls())

View File

@ -0,0 +1,12 @@
# Direct edits to this file will be lost!
# Manage your settings on Plinth <https://localhost/plinth/apps/email_server>
# Mozilla Guideline v5.6, Dovecot 2.3.9, OpenSSL 1.1.1d, intermediate
# Generated 2021-08
# https://ssl-config.mozilla.org/
ssl = required
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = no
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384