From 4535c42e70a2c5d62e97339dd3a05237de4a34e0 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 16:54:33 +0200 Subject: [PATCH 01/24] This isn't required --- core/postfix/conf/main.cf | 1 - 1 file changed, 1 deletion(-) diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index 9cd4010e..1a9c6bc9 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -31,7 +31,6 @@ mydestination = # Relayhost if any is configured relayhost = {{ RELAYHOST }} {% if RELAYUSER %} -smtp_sasl_auth_enable = yes smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous {% endif %} From de3620da4aeca8fb37ad5af2462bc8fc6e32a80e Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 16:55:23 +0200 Subject: [PATCH 02/24] Don't send credentials in clear ever --- core/postfix/conf/main.cf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index 1a9c6bc9..9b3e30ff 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -32,7 +32,8 @@ mydestination = relayhost = {{ RELAYHOST }} {% if RELAYUSER %} smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd -smtp_sasl_security_options = noanonymous +smtp_sasl_security_options = noanonymous, noplaintext +smtp_sasl_tls_security_options = noanonymous {% endif %} # Recipient delimiter for extended addresses From 7285c6bfd98fed56addf8d1b736f10feb6cb8048 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 17:28:16 +0200 Subject: [PATCH 03/24] admin won't understand LOGIN --- core/nginx/conf/nginx.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index 5158ca5c..718e90b9 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -302,7 +302,7 @@ mail { starttls only; {% endif %} protocol smtp; - smtp_auth plain login; + smtp_auth plain; } {% if TLS %} @@ -310,7 +310,7 @@ mail { listen 465 ssl; listen [::]:465 ssl; protocol smtp; - smtp_auth plain login; + smtp_auth plain; } server { From ecadf46ac620d2585e96d316910f607162905834 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 17:39:15 +0200 Subject: [PATCH 04/24] fix PFS --- core/postfix/conf/main.cf | 5 +++-- core/postfix/start.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index 9b3e30ff..dfa31514 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -50,7 +50,7 @@ smtpd_authorized_xclient_hosts={{ POD_ADDRESS_RANGE or SUBNET }} # General TLS configuration tls_high_cipherlist = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA tls_preempt_cipherlist = yes -tls_ssl_options = NO_COMPRESSION +tls_ssl_options = NO_COMPRESSION, NO_TICKET # By default, outgoing TLS is more flexible because # 1. not all receiving servers will support TLS, @@ -58,7 +58,8 @@ tls_ssl_options = NO_COMPRESSION smtp_tls_security_level = {{ OUTBOUND_TLS_LEVEL|default('may') }} smtp_tls_mandatory_protocols = !SSLv2, !SSLv3 smtp_tls_protocols =!SSLv2,!SSLv3 -smtp_tls_session_cache_database = lmdb:${data_directory}/smtp_scache +smtp_tls_session_cache_database = lmdb:/dev/shm/postfix/smtp_scache +smtpd_tls_session_cache_database = lmdb:/dev/shm/postfix/smtpd_scache ############### # Virtual diff --git a/core/postfix/start.py b/core/postfix/start.py index e0c781b7..df290a3a 100755 --- a/core/postfix/start.py +++ b/core/postfix/start.py @@ -15,6 +15,7 @@ log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING")) def start_podop(): os.setuid(getpwnam('postfix').pw_uid) + os.mkdir('/dev/shm/postfix',mode=0o700) url = "http://" + os.environ["ADMIN_ADDRESS"] + "/internal/postfix/" # TODO: Remove verbosity setting from Podop? run_server(0, "postfix", "/tmp/podop.socket", [ From 55cdb1a5349c8d35492efb5e2e69472f10f97827 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 17:42:33 +0200 Subject: [PATCH 05/24] be explicit about what we support --- core/postfix/conf/main.cf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index dfa31514..d83db600 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -43,6 +43,8 @@ recipient_delimiter = {{ RECIPIENT_DELIMITER }} # In kubernetes and Docker swarm, such address cannot be determined using the hostname. Allow for the whole Mailu subnet instead. smtpd_authorized_xclient_hosts={{ POD_ADDRESS_RANGE or SUBNET }} +auth_mechanisms = plain + ############### # TLS ############### From 5e7d5adf179d1a40c40c169d594995ff4de2f391 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 20:10:49 +0200 Subject: [PATCH 06/24] AUTH shouldn't happen on port 25 --- core/admin/mailu/internal/nginx.py | 7 +++++++ core/nginx/conf/nginx.conf | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py index 3f5582cc..0c03b866 100644 --- a/core/admin/mailu/internal/nginx.py +++ b/core/admin/mailu/internal/nginx.py @@ -81,6 +81,13 @@ def handle_authentication(headers): raw_password = urllib.parse.unquote(headers["Auth-Pass"]) password = raw_password.encode("iso8859-1").decode("utf8") ip = urllib.parse.unquote(headers["Client-Ip"]) + port = int(urllib.parse.unquote(headers["Auth-Port"])) + if port == 25: + return { + "Auth-Status": "AUTH not supported", + "Auth-Error-Code": "502 5.5.1", + "Auth-Wait": 0 + } user = models.User.query.get(user_email) if check_credentials(user, password, ip, protocol): return { diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index 718e90b9..82e7ca36 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -250,6 +250,7 @@ mail { listen 10025; protocol smtp; smtp_auth plain; + auth_http_header Auth-Port 10025; } # Default IMAP server for the webmail (no encryption, but authentication) @@ -257,6 +258,7 @@ mail { listen 10143; protocol imap; smtp_auth plain; + auth_http_header Auth-Port 10043; } # SMTP is always enabled, to avoid losing emails when TLS is failing @@ -271,6 +273,7 @@ mail { {% endif %} protocol smtp; smtp_auth none; + auth_http_header Auth-Port 25; } # All other protocols are disabled if TLS is failing @@ -283,6 +286,7 @@ mail { {% endif %} protocol imap; imap_auth plain; + auth_http_header Auth-Port 143; } server { @@ -293,6 +297,7 @@ mail { {% endif %} protocol pop3; pop3_auth plain; + auth_http_header Auth-Port 110; } server { @@ -303,6 +308,7 @@ mail { {% endif %} protocol smtp; smtp_auth plain; + auth_http_header Auth-Port 587; } {% if TLS %} @@ -311,6 +317,7 @@ mail { listen [::]:465 ssl; protocol smtp; smtp_auth plain; + auth_http_header Auth-Port 465; } server { @@ -318,6 +325,7 @@ mail { listen [::]:993 ssl; protocol imap; imap_auth plain; + auth_http_header Auth-Port 993; } server { @@ -325,6 +333,7 @@ mail { listen [::]:995 ssl; protocol pop3; pop3_auth plain; + auth_http_header Auth-Port 995; } {% endif %} {% endif %} From cb68cb312b781810f0ad57a8722bf2315f272458 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 20:40:56 +0200 Subject: [PATCH 07/24] Reduce the size of the RSA key to 3072bits This is already generous for certificates that have a 3month validity! We rekey every single time. --- core/nginx/letsencrypt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index 3fe8ea92..ed106fa1 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -14,7 +14,7 @@ command = [ "--cert-name", "mailu", "--preferred-challenges", "http", "--http-01-port", "8008", "--keep-until-expiring", - "--rsa-key-size", "4096", + "--rsa-key-size", "3072", "--config-dir", "/certs/letsencrypt", "--post-hook", "/config.py" ] From f05cc99dc0b25ad02f17d91e0aee9852b7558bf0 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 21:06:15 +0200 Subject: [PATCH 08/24] Add ECC certs for modern clients --- core/nginx/conf/tls.conf | 4 ++++ core/nginx/config.py | 4 ++-- core/nginx/letsencrypt.py | 15 ++++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/core/nginx/conf/tls.conf b/core/nginx/conf/tls.conf index 5d7ec031..9100243d 100644 --- a/core/nginx/conf/tls.conf +++ b/core/nginx/conf/tls.conf @@ -1,5 +1,9 @@ ssl_certificate {{ TLS[0] }}; ssl_certificate_key {{ TLS[1] }}; +{% if TLS_FLAVOR in ['letsencrypt','mail-letsencrypt] %} +ssl_certificate {{ TLS[2] }}; +ssl_certificate_key {{ TLS[3] }}; +{% endif %} ssl_session_timeout 1d; ssl_session_tickets off; ssl_dhparam /conf/dhparam.pem; diff --git a/core/nginx/config.py b/core/nginx/config.py index 6fc9c082..a9bce89b 100755 --- a/core/nginx/config.py +++ b/core/nginx/config.py @@ -27,10 +27,10 @@ keypair_name = os.getenv("TLS_KEYPAIR_FILENAME", default="key.pem") args["TLS"] = { "cert": ("/certs/%s" % cert_name, "/certs/%s" % keypair_name), "letsencrypt": ("/certs/letsencrypt/live/mailu/fullchain.pem", - "/certs/letsencrypt/live/mailu/privkey.pem"), + "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/fullchain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), "mail": ("/certs/%s" % cert_name, "/certs/%s" % keypair_name), "mail-letsencrypt": ("/certs/letsencrypt/live/mailu/fullchain.pem", - "/certs/letsencrypt/live/mailu/privkey.pem"), + "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/fullchain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), "notls": None }[args["TLS_FLAVOR"]] diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index ed106fa1..73659f7c 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -14,7 +14,19 @@ command = [ "--cert-name", "mailu", "--preferred-challenges", "http", "--http-01-port", "8008", "--keep-until-expiring", - "--rsa-key-size", "3072", + "--config-dir", "/certs/letsencrypt", + "--post-hook", "/config.py" +] +command2 = [ + "certbot", + "-n", "--agree-tos", # non-interactive + "-d", os.environ["HOSTNAMES"], + "-m", "{}@{}".format(os.environ["POSTMASTER"], os.environ["DOMAIN"]), + "certonly", "--standalone", + "--cert-name", "mailu-ecdsa", + "--preferred-challenges", "http", "--http-01-port", "8008", + "--keep-until-expiring", + "--key-type", "ecdsa", "--config-dir", "/certs/letsencrypt", "--post-hook", "/config.py" ] @@ -25,5 +37,6 @@ time.sleep(5) # Run certbot every hour while True: subprocess.call(command) + subprocess.call(command2) time.sleep(3600) From 92ec446c20f317c2c188c821fb561e020ec6d5d7 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 21:29:05 +0200 Subject: [PATCH 09/24] doh --- core/nginx/conf/tls.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nginx/conf/tls.conf b/core/nginx/conf/tls.conf index 9100243d..4372c5af 100644 --- a/core/nginx/conf/tls.conf +++ b/core/nginx/conf/tls.conf @@ -1,6 +1,6 @@ ssl_certificate {{ TLS[0] }}; ssl_certificate_key {{ TLS[1] }}; -{% if TLS_FLAVOR in ['letsencrypt','mail-letsencrypt] %} +{% if TLS_FLAVOR in ['letsencrypt','mail-letsencrypt'] %} ssl_certificate {{ TLS[2] }}; ssl_certificate_key {{ TLS[3] }}; {% endif %} From 98b903fe13c10ed99c9bae2167e046888114d3b8 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 21:38:03 +0200 Subject: [PATCH 10/24] don't send the rootcert --- core/nginx/config.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/nginx/config.py b/core/nginx/config.py index a9bce89b..1b0f7235 100755 --- a/core/nginx/config.py +++ b/core/nginx/config.py @@ -26,11 +26,11 @@ cert_name = os.getenv("TLS_CERT_FILENAME", default="cert.pem") keypair_name = os.getenv("TLS_KEYPAIR_FILENAME", default="key.pem") args["TLS"] = { "cert": ("/certs/%s" % cert_name, "/certs/%s" % keypair_name), - "letsencrypt": ("/certs/letsencrypt/live/mailu/fullchain.pem", - "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/fullchain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), + "letsencrypt": ("/certs/letsencrypt/live/mailu/chain.pem", + "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/chain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), "mail": ("/certs/%s" % cert_name, "/certs/%s" % keypair_name), - "mail-letsencrypt": ("/certs/letsencrypt/live/mailu/fullchain.pem", - "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/fullchain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), + "mail-letsencrypt": ("/certs/letsencrypt/live/mailu/chain.pem", + "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/chain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), "notls": None }[args["TLS_FLAVOR"]] From 24f9bf106440f98a757a368b01187e7ddc16d1f0 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 22:51:23 +0200 Subject: [PATCH 11/24] format certs for nginx --- core/nginx/conf/tls.conf | 1 + core/nginx/config.py | 8 ++++---- core/nginx/letsencrypt.py | 19 ++++++++++++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/core/nginx/conf/tls.conf b/core/nginx/conf/tls.conf index 4372c5af..f663bfd2 100644 --- a/core/nginx/conf/tls.conf +++ b/core/nginx/conf/tls.conf @@ -3,6 +3,7 @@ ssl_certificate_key {{ TLS[1] }}; {% if TLS_FLAVOR in ['letsencrypt','mail-letsencrypt'] %} ssl_certificate {{ TLS[2] }}; ssl_certificate_key {{ TLS[3] }}; +ssl_trusted_certificate /etc/ssl/certs/ca-cert-DST_Root_CA_X3.pem; {% endif %} ssl_session_timeout 1d; ssl_session_tickets off; diff --git a/core/nginx/config.py b/core/nginx/config.py index 1b0f7235..9fa75877 100755 --- a/core/nginx/config.py +++ b/core/nginx/config.py @@ -26,11 +26,11 @@ cert_name = os.getenv("TLS_CERT_FILENAME", default="cert.pem") keypair_name = os.getenv("TLS_KEYPAIR_FILENAME", default="key.pem") args["TLS"] = { "cert": ("/certs/%s" % cert_name, "/certs/%s" % keypair_name), - "letsencrypt": ("/certs/letsencrypt/live/mailu/chain.pem", - "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/chain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), + "letsencrypt": ("/certs/letsencrypt/live/mailu/nginx-chain.pem", + "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/nginx-chain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), "mail": ("/certs/%s" % cert_name, "/certs/%s" % keypair_name), - "mail-letsencrypt": ("/certs/letsencrypt/live/mailu/chain.pem", - "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/chain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), + "mail-letsencrypt": ("/certs/letsencrypt/live/mailu/nginx-chain.pem", + "/certs/letsencrypt/live/mailu/privkey.pem", "/certs/letsencrypt/live/mailu-ecdsa/nginx-chain.pem", "/certs/letsencrypt/live/mailu-ecdsa/privkey.pem"), "notls": None }[args["TLS_FLAVOR"]] diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index 73659f7c..9a5ba18a 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -4,7 +4,6 @@ import os import time import subprocess - command = [ "certbot", "-n", "--agree-tos", # non-interactive @@ -31,12 +30,30 @@ command2 = [ "--post-hook", "/config.py" ] +def format_for_nginx(fullchain, output): + """ nginx expects cert + intermediate + whereas letsencrypt provides ca + intermediate + cert + """ + certs = [] + with open(fullchain, 'r') as pem: + cert = '' + for line in pem: + cert += line + if '-----END CERTIFICATE-----' in line: + certs += [cert] + cert = '' + with open(output, 'w') as pem: + for cert in reversed(certs[1:]): + pem.write(cert) + # Wait for nginx to start time.sleep(5) # Run certbot every hour while True: subprocess.call(command) + format_for_nginx('/certs/letsencrypt/live/mailu/fullchain.pem', '/certs/letsencrypt/live/mailu/nginx-chain.pem') subprocess.call(command2) + format_for_nginx('/certs/letsencrypt/live/mailu-ecdsa/fullchain.pem', '/certs/letsencrypt/live/mailu-ecdsa/nginx-chain.pem') time.sleep(3600) From 12c842c4b99be47d1a7eb630780337a8995309d8 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 23:27:03 +0200 Subject: [PATCH 12/24] In fact in fullchain we want all but the last --- core/nginx/letsencrypt.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index 9a5ba18a..3f8f6067 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -31,8 +31,7 @@ command2 = [ ] def format_for_nginx(fullchain, output): - """ nginx expects cert + intermediate - whereas letsencrypt provides ca + intermediate + cert + """ nginx doesn't need the "compat" """ certs = [] with open(fullchain, 'r') as pem: @@ -43,7 +42,7 @@ def format_for_nginx(fullchain, output): certs += [cert] cert = '' with open(output, 'w') as pem: - for cert in reversed(certs[1:]): + for cert in certs[:-1]: pem.write(cert) # Wait for nginx to start From 4a871c090538e89d1aed1c148f036d1acec70e70 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 9 Aug 2021 23:29:17 +0200 Subject: [PATCH 13/24] this causes trouble with the test --- core/postfix/conf/main.cf | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index d83db600..dfa31514 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -43,8 +43,6 @@ recipient_delimiter = {{ RECIPIENT_DELIMITER }} # In kubernetes and Docker swarm, such address cannot be determined using the hostname. Allow for the whole Mailu subnet instead. smtpd_authorized_xclient_hosts={{ POD_ADDRESS_RANGE or SUBNET }} -auth_mechanisms = plain - ############### # TLS ############### From f971b47fb93190ee6d84961e4ea0e6ade510c0c8 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 10 Aug 2021 08:22:23 +0200 Subject: [PATCH 14/24] maybe fix the tests --- core/postfix/conf/main.cf | 1 + 1 file changed, 1 insertion(+) diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index dfa31514..a35ca16c 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -31,6 +31,7 @@ mydestination = # Relayhost if any is configured relayhost = {{ RELAYHOST }} {% if RELAYUSER %} +smtp_sasl_auth_enable = yes smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous, noplaintext smtp_sasl_tls_security_options = noanonymous From 2b05e72ce4027e3022a960d862bdbf0243583356 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 10 Aug 2021 08:51:55 +0200 Subject: [PATCH 15/24] Revert "maybe fix the tests" This reverts commit f971b47fb93190ee6d84961e4ea0e6ade510c0c8. --- core/postfix/conf/main.cf | 1 - 1 file changed, 1 deletion(-) diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index a35ca16c..dfa31514 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -31,7 +31,6 @@ mydestination = # Relayhost if any is configured relayhost = {{ RELAYHOST }} {% if RELAYUSER %} -smtp_sasl_auth_enable = yes smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous, noplaintext smtp_sasl_tls_security_options = noanonymous From 974bcba5ab8d8bf2d2f581f74e338fda491595f5 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 10 Aug 2021 09:05:02 +0200 Subject: [PATCH 16/24] Restore LOGIN as tests assume it's there --- core/nginx/conf/nginx.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index 82e7ca36..9ce12980 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -307,7 +307,7 @@ mail { starttls only; {% endif %} protocol smtp; - smtp_auth plain; + smtp_auth plain login; auth_http_header Auth-Port 587; } @@ -316,7 +316,7 @@ mail { listen 465 ssl; listen [::]:465 ssl; protocol smtp; - smtp_auth plain; + smtp_auth plain login; auth_http_header Auth-Port 465; } From dccd8afd5167eb2852567ad02062e802ba4834fb Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 10 Aug 2021 10:20:15 +0200 Subject: [PATCH 17/24] Thanks @Diman0! ENEEDSLEEP --- core/admin/mailu/internal/nginx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py index 0c03b866..5e60cd0c 100644 --- a/core/admin/mailu/internal/nginx.py +++ b/core/admin/mailu/internal/nginx.py @@ -81,8 +81,8 @@ def handle_authentication(headers): raw_password = urllib.parse.unquote(headers["Auth-Pass"]) password = raw_password.encode("iso8859-1").decode("utf8") ip = urllib.parse.unquote(headers["Client-Ip"]) - port = int(urllib.parse.unquote(headers["Auth-Port"])) - if port == 25: + service_port = int(urllib.parse.unquote(headers["Auth-Port"])) + if service_port == 25: return { "Auth-Status": "AUTH not supported", "Auth-Error-Code": "502 5.5.1", From 109a8aa000ec4556240fd56cb1deef1b36130d6f Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 10 Aug 2021 10:55:21 +0200 Subject: [PATCH 18/24] Ensure that we always have CERT+INTERMEDIARY CA Let's encrypt may change things up in the future... --- core/nginx/letsencrypt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index 3f8f6067..d6575c11 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -42,7 +42,7 @@ def format_for_nginx(fullchain, output): certs += [cert] cert = '' with open(output, 'w') as pem: - for cert in certs[:-1]: + for cert in certs[:-1] if len(certs)>2 else certs: pem.write(cert) # Wait for nginx to start From 5e1ba9d4ffbff68780c9f6e4ef4ba353744a7b4f Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 10 Aug 2021 12:09:11 +0200 Subject: [PATCH 19/24] towncrier --- towncrier/newsfragments/1922.enhancement | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 towncrier/newsfragments/1922.enhancement diff --git a/towncrier/newsfragments/1922.enhancement b/towncrier/newsfragments/1922.enhancement new file mode 100644 index 00000000..4b01fa88 --- /dev/null +++ b/towncrier/newsfragments/1922.enhancement @@ -0,0 +1,5 @@ +Add support for ECDSA certificates when letsencrypt is used. This means dropping compatibility for android < 4.1.1 +Add LETSENCRYPT_SHORTCHAIN to your configuration to avoid sending ISRG Root X1 (this will break compatibility with android < 7.1.1) +Disable AUTH command on port 25 +Disable TLS tickets, reconfigure the cache to improve Forward Secrecy +Prevent clear-text credentials from being sent to relays From c76a76c0b01890a07cc6b7490174334857e88bf9 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 10 Aug 2021 12:19:51 +0200 Subject: [PATCH 20/24] make it optional, add a knob --- core/nginx/letsencrypt.py | 4 ++-- docs/configuration.rst | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index d6575c11..1f7e20dc 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -31,7 +31,7 @@ command2 = [ ] def format_for_nginx(fullchain, output): - """ nginx doesn't need the "compat" + """ We may want to strip ISRG Root X1 out """ certs = [] with open(fullchain, 'r') as pem: @@ -42,7 +42,7 @@ def format_for_nginx(fullchain, output): certs += [cert] cert = '' with open(output, 'w') as pem: - for cert in certs[:-1] if len(certs)>2 else certs: + for cert in certs[:-1] if len(certs)>2 and os.getenv('LETSENCRYPT_SHORTCHAIN', default="False") else certs: pem.write(cert) # Wait for nginx to start diff --git a/docs/configuration.rst b/docs/configuration.rst index 21effc52..83bc9d90 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -163,6 +163,11 @@ See the `python docs`_ for more information. .. _`python docs`: https://docs.python.org/3.6/library/logging.html#logging-levels +The ``LETSENCRYPT_SHORTCHAIN`` (default: False) setting controls whether we send the ISRG Root X1 certificate in TLS handshakes. This is required for `android handsets older than 7.1.1` but slows down the performance of modern devices. + +.. _`android handsets older than 7.1.1`: https://community.letsencrypt.org/t/production-chain-changes/150739 + + Antivirus settings ------------------ From 925105075c163e908f0927c90cfbba03db14d5b7 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Fri, 13 Aug 2021 20:35:40 +0200 Subject: [PATCH 21/24] this is required in fact --- core/postfix/conf/main.cf | 1 + 1 file changed, 1 insertion(+) diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index dfa31514..a35ca16c 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -31,6 +31,7 @@ mydestination = # Relayhost if any is configured relayhost = {{ RELAYHOST }} {% if RELAYUSER %} +smtp_sasl_auth_enable = yes smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous, noplaintext smtp_sasl_tls_security_options = noanonymous From e304c352a13519afbd9e2b9bc04b069add8e7bf4 Mon Sep 17 00:00:00 2001 From: Jack Murray Date: Sat, 14 Aug 2021 14:04:02 +0100 Subject: [PATCH 22/24] Change letsencrypt timer from 1h --> 1 day There's no need to be calling certbot so frequently --- core/nginx/letsencrypt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index 1f7e20dc..cfd14e73 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -48,7 +48,7 @@ def format_for_nginx(fullchain, output): # Wait for nginx to start time.sleep(5) -# Run certbot every hour +# Run certbot every day while True: subprocess.call(command) format_for_nginx('/certs/letsencrypt/live/mailu/fullchain.pem', '/certs/letsencrypt/live/mailu/nginx-chain.pem') From 6704cb869aa6e724df9ebf8e9697f356ef07592a Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 18 Aug 2021 15:46:22 +0200 Subject: [PATCH 23/24] Switch to 3072bits dhparam (instead of 4096bits) We aim for 128bits of security here --- core/nginx/conf/dhparam.pem | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/core/nginx/conf/dhparam.pem b/core/nginx/conf/dhparam.pem index 3cf0fcbc..4f25f663 100644 --- a/core/nginx/conf/dhparam.pem +++ b/core/nginx/conf/dhparam.pem @@ -1,13 +1,11 @@ -----BEGIN DH PARAMETERS----- -MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz -+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a -87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 -YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi -7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD -ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 -7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 -nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e -8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx -iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K -zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI= +MIIBiAKCAYEAtQlUSOKGjpdXJ154qmMEa1pEs+9CdSxWiZFkiXBJb0lTafOh8cfF +2IkcWSwzxWwjW4Ad26UQQFh1poGf2QBzVk2vuKCekYzPAs/WqH8VwiXBiWR5R9lh +v/+CkEBYuQOzAhXLN6ZGdPPa2sjdI49rlaIqyLJE4D0TI/VHYmC/vEwqkJUgaGrS +19LhHZimnmouvrnyBPyf00czXlMow0RnmYeHVZ7W5hu7t9TH9o3QAN/GKiFfxFj+ +RkdLM7beQdS0He5YeTaElM5l1YT5d5gHFbOzEQyKHd10ux+bgVcgUeVbBnI1SAIC +w53yc1PkDAiRijSP5j5aWq1djtJPheS13o35HyIf0cHzkNYhKfX5JWPj/cbgdM+C +FL1bnRc8sL5oxmkDoGJhiNZIf4n2WtS8Zu28gUgat6S+vCm/4yavIc/T1g6UiNKE +X41HPbsma/QWUwOL6S+b2qr+7rKqjI5TzVek8vBMellEV4mBvfQU3NDSQ4WvxbTq +ZEOgLPA178nrAgEC -----END DH PARAMETERS----- From dd127f8f06520befbf52be325c4462cb6c7fbc2d Mon Sep 17 00:00:00 2001 From: Jack Murray Date: Sat, 14 Aug 2021 14:04:02 +0100 Subject: [PATCH 24/24] Change letsencrypt timer from 1h --> 1 day There's no need to be calling certbot so frequently --- core/nginx/letsencrypt.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/nginx/letsencrypt.py b/core/nginx/letsencrypt.py index cfd14e73..1dd2cba4 100755 --- a/core/nginx/letsencrypt.py +++ b/core/nginx/letsencrypt.py @@ -54,5 +54,4 @@ while True: format_for_nginx('/certs/letsencrypt/live/mailu/fullchain.pem', '/certs/letsencrypt/live/mailu/nginx-chain.pem') subprocess.call(command2) format_for_nginx('/certs/letsencrypt/live/mailu-ecdsa/fullchain.pem', '/certs/letsencrypt/live/mailu-ecdsa/nginx-chain.pem') - time.sleep(3600) - + time.sleep(86400)