From 3e51d15b03f84ce5e74ea9f869a4c9649b8f9205 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 18 Oct 2022 15:58:53 +0200 Subject: [PATCH 01/19] Remove the strict anti-spoofing rule. --- core/admin/mailu/internal/views/postfix.py | 15 --------------- core/postfix/conf/main.cf | 1 - towncrier/newsfragments/2475.feature | 1 + 3 files changed, 1 insertion(+), 16 deletions(-) create mode 100644 towncrier/newsfragments/2475.feature diff --git a/core/admin/mailu/internal/views/postfix.py b/core/admin/mailu/internal/views/postfix.py index f8346bb1..8188270c 100644 --- a/core/admin/mailu/internal/views/postfix.py +++ b/core/admin/mailu/internal/views/postfix.py @@ -158,21 +158,6 @@ def postfix_sender_rate(sender): user = models.User.get(sender) or flask.abort(404) return flask.abort(404) if user.sender_limiter.hit() else flask.jsonify("450 4.2.1 You are sending too many emails too fast.") -@internal.route("/postfix/sender/access/") -def postfix_sender_access(sender): - """ Simply reject any sender that pretends to be from a local domain - """ - if '@' in sender: - if sender.startswith('<') and sender.endswith('>'): - sender = sender[1:-1] - try: - localpart, domain_name = models.Email.resolve_domain(sender) - if models.Domain.query.get(domain_name): - return flask.jsonify("REJECT") - except sqlalchemy.exc.StatementError: - pass - return flask.abort(404) - # idna encode domain part of each address in list of addresses def idna_encode(addresses): return [ diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index a892430c..f3b789f9 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -110,7 +110,6 @@ check_ratelimit = check_sasl_access ${podop}senderrate smtpd_client_restrictions = permit_mynetworks, - check_sender_access ${podop}senderaccess, reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unknown_recipient_domain, diff --git a/towncrier/newsfragments/2475.feature b/towncrier/newsfragments/2475.feature new file mode 100644 index 00000000..e84bc68a --- /dev/null +++ b/towncrier/newsfragments/2475.feature @@ -0,0 +1 @@ +Remove the strict anti-spoofing rule. In 2022 we should have other controls (SPF/DKIM) for dealing with authorization and shouldn't assume that Mailu is the only MTA allowed to send emails on behalf of the domains it hosts. From 5ebcecf4dd6676637a5585d24d5a5853c7d23996 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 18 Oct 2022 16:05:57 +0200 Subject: [PATCH 02/19] Don't need that anymore either --- core/postfix/start.py | 1 - 1 file changed, 1 deletion(-) diff --git a/core/postfix/start.py b/core/postfix/start.py index 4faf2e2d..323ff1f6 100755 --- a/core/postfix/start.py +++ b/core/postfix/start.py @@ -27,7 +27,6 @@ def start_podop(): ("mailbox", "url", url + "mailbox/§"), ("recipientmap", "url", url + "recipient/map/§"), ("sendermap", "url", url + "sender/map/§"), - ("senderaccess", "url", url + "sender/access/§"), ("senderlogin", "url", url + "sender/login/§"), ("senderrate", "url", url + "sender/rate/§") ]) From 8775a2bf04cc7e730de02dc36a18e78b9d71cfbe Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 19 Oct 2022 15:28:20 +0200 Subject: [PATCH 03/19] untested code that may just work --- core/admin/mailu/internal/views/rspamd.py | 5 +++++ core/rspamd/conf/whitelist.conf | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 core/rspamd/conf/whitelist.conf diff --git a/core/admin/mailu/internal/views/rspamd.py b/core/admin/mailu/internal/views/rspamd.py index 458dbb81..3d3f8719 100644 --- a/core/admin/mailu/internal/views/rspamd.py +++ b/core/admin/mailu/internal/views/rspamd.py @@ -25,3 +25,8 @@ def rspamd_dkim_key(domain_name): } ) return flask.jsonify({'data': {'selectors': selectors}}) + +@internal.route("/rspamd/local_domains", methods=['GET']) +def rspamd_local_domains(): + domains = set(models.Domain.query.all() + models.Alternative.query.all()) + return '\n'.join(domains) diff --git a/core/rspamd/conf/whitelist.conf b/core/rspamd/conf/whitelist.conf new file mode 100644 index 00000000..fcde167a --- /dev/null +++ b/core/rspamd/conf/whitelist.conf @@ -0,0 +1,8 @@ +rules { + BLACKLIST_ANTISPOOF = { + valid_dmarc = true; + blacklist = true; + domains = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; + score = 15.0; + } +} From cc2c308d1d2fb1674627e6a035ee483166d4a122 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 19 Oct 2022 15:33:37 +0200 Subject: [PATCH 04/19] update the towncrier entry --- towncrier/newsfragments/2475.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/towncrier/newsfragments/2475.feature b/towncrier/newsfragments/2475.feature index e84bc68a..d5340380 100644 --- a/towncrier/newsfragments/2475.feature +++ b/towncrier/newsfragments/2475.feature @@ -1 +1 @@ -Remove the strict anti-spoofing rule. In 2022 we should have other controls (SPF/DKIM) for dealing with authorization and shouldn't assume that Mailu is the only MTA allowed to send emails on behalf of the domains it hosts. +Upgrade the anti-spoofing rule. We shouldn't assume that Mailu is the only MTA allowed to send emails on behalf of the domains it hosts... but we should also ensure that both the envelope from and header from are checked. From 0204c9e59d5202090d44d6747b635201f399c99e Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 19 Oct 2022 16:08:29 +0200 Subject: [PATCH 05/19] doh --- core/admin/mailu/internal/views/rspamd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/internal/views/rspamd.py b/core/admin/mailu/internal/views/rspamd.py index 3d3f8719..e2e453ad 100644 --- a/core/admin/mailu/internal/views/rspamd.py +++ b/core/admin/mailu/internal/views/rspamd.py @@ -29,4 +29,4 @@ def rspamd_dkim_key(domain_name): @internal.route("/rspamd/local_domains", methods=['GET']) def rspamd_local_domains(): domains = set(models.Domain.query.all() + models.Alternative.query.all()) - return '\n'.join(domains) + return '\n'.join(map(str,domains)) From f7b3aad8316abe8fb5ac987c09656d888c847558 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 19 Oct 2022 17:53:32 +0200 Subject: [PATCH 06/19] Ensure we REJECT when we don't have a DMARC policy This restores the old behaviour --- core/rspamd/conf/force_actions.conf | 7 +++++++ core/rspamd/conf/multimap.conf | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 core/rspamd/conf/force_actions.conf create mode 100644 core/rspamd/conf/multimap.conf diff --git a/core/rspamd/conf/force_actions.conf b/core/rspamd/conf/force_actions.conf new file mode 100644 index 00000000..64c992c4 --- /dev/null +++ b/core/rspamd/conf/force_actions.conf @@ -0,0 +1,7 @@ +rules { + WHITELIST_EXCEPTION { + action = "reject"; + expression = "(AUTH_NA|BLACKLIST_ANTISPOOF) & IS_LOCAL_DOMAIN"; + message = "Rejected (anti-spoofing)"; + } +} diff --git a/core/rspamd/conf/multimap.conf b/core/rspamd/conf/multimap.conf new file mode 100644 index 00000000..dd2ffa61 --- /dev/null +++ b/core/rspamd/conf/multimap.conf @@ -0,0 +1,5 @@ +IS_LOCAL_DOMAIN { + type = "from"; + filter = "email:domain"; + map = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; +} From be4dd6d84a747f6b80acb83cf89c8db1426ceea7 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 19 Oct 2022 18:22:33 +0200 Subject: [PATCH 07/19] Spell it out --- core/rspamd/conf/force_actions.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/rspamd/conf/force_actions.conf b/core/rspamd/conf/force_actions.conf index 64c992c4..20bf9245 100644 --- a/core/rspamd/conf/force_actions.conf +++ b/core/rspamd/conf/force_actions.conf @@ -1,7 +1,7 @@ rules { - WHITELIST_EXCEPTION { + ANTISPOOF { action = "reject"; - expression = "(AUTH_NA|BLACKLIST_ANTISPOOF) & IS_LOCAL_DOMAIN"; + expression = "((R_DKIM_NA & R_SPF_NA & DMARC_NA & ARC_NA)|BLACKLIST_ANTISPOOF) & IS_LOCAL_DOMAIN"; message = "Rejected (anti-spoofing)"; } } From af87456faf65ffbe133e451fa7f002983d7e282a Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 20 Oct 2022 10:24:10 +0200 Subject: [PATCH 08/19] this works for me --- core/rspamd/conf/force_actions.conf | 16 +++++++++++++--- core/rspamd/conf/multimap.conf | 12 +++++++++--- core/rspamd/conf/whitelist.conf | 2 +- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/core/rspamd/conf/force_actions.conf b/core/rspamd/conf/force_actions.conf index 20bf9245..0d1d1a2b 100644 --- a/core/rspamd/conf/force_actions.conf +++ b/core/rspamd/conf/force_actions.conf @@ -1,7 +1,17 @@ rules { - ANTISPOOF { + ANTISPOOF_NOAUTH { action = "reject"; - expression = "((R_DKIM_NA & R_SPF_NA & DMARC_NA & ARC_NA)|BLACKLIST_ANTISPOOF) & IS_LOCAL_DOMAIN"; - message = "Rejected (anti-spoofing)"; + expression = "(IS_LOCAL_DOMAIN_E & MISSING_FROM) | (IS_LOCAL_DOMAIN_H & (R_DKIM_NA & R_SPF_NA & DMARC_NA & ARC_NA))"; + message = "Rejected (anti-spoofing noauth)"; + } + ANTISPOOF_DMARC_ENFORCE_LOCAL { + action = "reject"; + expression = "((IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE)"; + message = "Rejected (anti-spoofing DMARC-enforce for local domains)"; + } + ANTISPOOF_AUTH_FAILED { + action = "reject"; + expression = "BLACKLIST_ANTISPOOF"; + message = "Rejected (anti-spoofing auth-failed)"; } } diff --git a/core/rspamd/conf/multimap.conf b/core/rspamd/conf/multimap.conf index dd2ffa61..dd25c08e 100644 --- a/core/rspamd/conf/multimap.conf +++ b/core/rspamd/conf/multimap.conf @@ -1,5 +1,11 @@ -IS_LOCAL_DOMAIN { - type = "from"; - filter = "email:domain"; +IS_LOCAL_DOMAIN_H { + type = "selector" + selector = "from('mime'):domain"; + map = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; +} + +IS_LOCAL_DOMAIN_E { + type = "selector" + selector = "from('smtp'):domain"; map = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; } diff --git a/core/rspamd/conf/whitelist.conf b/core/rspamd/conf/whitelist.conf index fcde167a..208ca203 100644 --- a/core/rspamd/conf/whitelist.conf +++ b/core/rspamd/conf/whitelist.conf @@ -3,6 +3,6 @@ rules { valid_dmarc = true; blacklist = true; domains = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; - score = 15.0; + score = 99.0; } } From 8da6117bb92aac66f0ab422ead887e9314d079c4 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 20 Oct 2022 10:35:43 +0200 Subject: [PATCH 09/19] clarify --- core/rspamd/conf/force_actions.conf | 6 +++--- core/rspamd/conf/whitelist.conf | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/rspamd/conf/force_actions.conf b/core/rspamd/conf/force_actions.conf index 0d1d1a2b..54e893a9 100644 --- a/core/rspamd/conf/force_actions.conf +++ b/core/rspamd/conf/force_actions.conf @@ -2,16 +2,16 @@ rules { ANTISPOOF_NOAUTH { action = "reject"; expression = "(IS_LOCAL_DOMAIN_E & MISSING_FROM) | (IS_LOCAL_DOMAIN_H & (R_DKIM_NA & R_SPF_NA & DMARC_NA & ARC_NA))"; - message = "Rejected (anti-spoofing noauth)"; + message = "Rejected (anti-spoofing: noauth). Please setup DMARC with DKIM or SPF if you want to send emails from your domain from other servers."; } ANTISPOOF_DMARC_ENFORCE_LOCAL { action = "reject"; expression = "((IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE)"; - message = "Rejected (anti-spoofing DMARC-enforce for local domains)"; + message = "Rejected (anti-spoofing: DMARC is enforced for local domains)"; } ANTISPOOF_AUTH_FAILED { action = "reject"; expression = "BLACKLIST_ANTISPOOF"; - message = "Rejected (anti-spoofing auth-failed)"; + message = "Rejected (anti-spoofing: auth-failed)"; } } diff --git a/core/rspamd/conf/whitelist.conf b/core/rspamd/conf/whitelist.conf index 208ca203..56f8a83d 100644 --- a/core/rspamd/conf/whitelist.conf +++ b/core/rspamd/conf/whitelist.conf @@ -3,6 +3,6 @@ rules { valid_dmarc = true; blacklist = true; domains = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; - score = 99.0; + score = 0.0; } } From 8929f54de5ff960c316d2c76292cb32e2c716b5c Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 20 Oct 2022 11:32:58 +0200 Subject: [PATCH 10/19] clarify Also cover the case where the DKIM sig is for another domain and there is no explicit DMARC policy --- core/rspamd/conf/force_actions.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/rspamd/conf/force_actions.conf b/core/rspamd/conf/force_actions.conf index 54e893a9..5c4e8eea 100644 --- a/core/rspamd/conf/force_actions.conf +++ b/core/rspamd/conf/force_actions.conf @@ -6,8 +6,8 @@ rules { } ANTISPOOF_DMARC_ENFORCE_LOCAL { action = "reject"; - expression = "((IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE)"; - message = "Rejected (anti-spoofing: DMARC is enforced for local domains)"; + expression = "((IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE | DMARC_NA)"; + message = "Rejected (anti-spoofing: DMARC compliance is enforced for local domains, regardless of the policy setting)"; } ANTISPOOF_AUTH_FAILED { action = "reject"; From c4fcaed7d42c68f8ff13ad37a96d9434cd8bf500 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 20 Oct 2022 16:01:18 +0200 Subject: [PATCH 11/19] doh --- core/rspamd/conf/force_actions.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rspamd/conf/force_actions.conf b/core/rspamd/conf/force_actions.conf index 5c4e8eea..c0ffe728 100644 --- a/core/rspamd/conf/force_actions.conf +++ b/core/rspamd/conf/force_actions.conf @@ -6,7 +6,7 @@ rules { } ANTISPOOF_DMARC_ENFORCE_LOCAL { action = "reject"; - expression = "((IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE | DMARC_NA)"; + expression = "(IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE | DMARC_NA)"; message = "Rejected (anti-spoofing: DMARC compliance is enforced for local domains, regardless of the policy setting)"; } ANTISPOOF_AUTH_FAILED { From bd1b73032c8e439c7d1be640505853170f311951 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 24 Oct 2022 09:48:51 +0200 Subject: [PATCH 12/19] Poke a hole for mailing lists --- core/rspamd/conf/force_actions.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/rspamd/conf/force_actions.conf b/core/rspamd/conf/force_actions.conf index c0ffe728..a5c342b8 100644 --- a/core/rspamd/conf/force_actions.conf +++ b/core/rspamd/conf/force_actions.conf @@ -1,17 +1,17 @@ rules { ANTISPOOF_NOAUTH { action = "reject"; - expression = "(IS_LOCAL_DOMAIN_E & MISSING_FROM) | (IS_LOCAL_DOMAIN_H & (R_DKIM_NA & R_SPF_NA & DMARC_NA & ARC_NA))"; + expression = "-MAILLIST & ((IS_LOCAL_DOMAIN_E & MISSING_FROM) | (IS_LOCAL_DOMAIN_H & (R_DKIM_NA & R_SPF_NA & DMARC_NA & ARC_NA)))"; message = "Rejected (anti-spoofing: noauth). Please setup DMARC with DKIM or SPF if you want to send emails from your domain from other servers."; } ANTISPOOF_DMARC_ENFORCE_LOCAL { action = "reject"; - expression = "(IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE | DMARC_NA)"; + expression = "-MAILLIST & (IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE | DMARC_NA)"; message = "Rejected (anti-spoofing: DMARC compliance is enforced for local domains, regardless of the policy setting)"; } ANTISPOOF_AUTH_FAILED { action = "reject"; - expression = "BLACKLIST_ANTISPOOF"; + expression = "-MAILLIST & BLACKLIST_ANTISPOOF"; message = "Rejected (anti-spoofing: auth-failed)"; } } From 07bf8ce6df23d588ecb5312caf3defba0f7af1ae Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 24 Oct 2022 09:49:58 +0200 Subject: [PATCH 13/19] Add anti-spoofing to the feature list --- README.md | 2 +- docs/index.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0d8402f5..0fd737b6 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Main features include: - **User features**, aliases, auto-reply, auto-forward, fetched accounts - **Admin features**, global admins, announcements, per-domain delegation, quotas - **Security**, enforced TLS, DANE, MTA-STS, Letsencrypt!, outgoing DKIM, anti-virus scanner -- **Antispam**, auto-learn, greylisting, DMARC and SPF +- **Antispam**, auto-learn, greylisting, DMARC and SPF, anti-spoofing - **Freedom**, all FOSS components, no tracker included ![Domains](docs/assets/screenshots/domains.png) diff --git a/docs/index.rst b/docs/index.rst index 4e4bb416..5c004dc1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,8 +28,8 @@ Main features include: - **Web access**, multiple Webmails and administration interface - **User features**, aliases, auto-reply, auto-forward, fetched accounts - **Admin features**, global admins, announcements, per-domain delegation, quotas -- **Security**, enforced TLS, Letsencrypt!, outgoing DKIM, anti-virus scanner -- **Antispam**, auto-learn, greylisting, DMARC and SPF +- **Security**, enforced TLS, DANE, MTA-STS, Letsencrypt!, outgoing DKIM, anti-virus scanner +- **Antispam**, auto-learn, greylisting, DMARC and SPF, anti-spoofing - **Freedom**, all FOSS components, no tracker included .. image:: assets/screenshots/create.png From 84a722eabcad706616f1de893a587ee032d86281 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 24 Oct 2022 19:31:53 +0200 Subject: [PATCH 14/19] Optimize the query --- core/admin/mailu/internal/views/rspamd.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/admin/mailu/internal/views/rspamd.py b/core/admin/mailu/internal/views/rspamd.py index e2e453ad..b6ead86b 100644 --- a/core/admin/mailu/internal/views/rspamd.py +++ b/core/admin/mailu/internal/views/rspamd.py @@ -28,5 +28,4 @@ def rspamd_dkim_key(domain_name): @internal.route("/rspamd/local_domains", methods=['GET']) def rspamd_local_domains(): - domains = set(models.Domain.query.all() + models.Alternative.query.all()) - return '\n'.join(map(str,domains)) + return '\n'.join(domain[0] for domain in models.Domain.query.with_entities(models.Domain.name).all() + models.Alternative.query.with_entities(models.Alternative.name).all()) From 95a3a3d3423163267d2d1207b6e87a8b2ce7da27 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 25 Oct 2022 12:05:25 +0200 Subject: [PATCH 15/19] doh --- core/rspamd/conf/force_actions.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/rspamd/conf/force_actions.conf b/core/rspamd/conf/force_actions.conf index a5c342b8..9f803405 100644 --- a/core/rspamd/conf/force_actions.conf +++ b/core/rspamd/conf/force_actions.conf @@ -1,17 +1,17 @@ rules { ANTISPOOF_NOAUTH { action = "reject"; - expression = "-MAILLIST & ((IS_LOCAL_DOMAIN_E & MISSING_FROM) | (IS_LOCAL_DOMAIN_H & (R_DKIM_NA & R_SPF_NA & DMARC_NA & ARC_NA)))"; + expression = "!MAILLIST & ((IS_LOCAL_DOMAIN_E & MISSING_FROM) | (IS_LOCAL_DOMAIN_H & (R_DKIM_NA & R_SPF_NA & DMARC_NA & ARC_NA)))"; message = "Rejected (anti-spoofing: noauth). Please setup DMARC with DKIM or SPF if you want to send emails from your domain from other servers."; } ANTISPOOF_DMARC_ENFORCE_LOCAL { action = "reject"; - expression = "-MAILLIST & (IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE | DMARC_NA)"; + expression = "!MAILLIST & (IS_LOCAL_DOMAIN_H | IS_LOCAL_DOMAIN_E) & (DMARC_POLICY_SOFTFAIL | DMARC_POLICY_REJECT | DMARC_POLICY_QUARANTINE | DMARC_NA)"; message = "Rejected (anti-spoofing: DMARC compliance is enforced for local domains, regardless of the policy setting)"; } ANTISPOOF_AUTH_FAILED { action = "reject"; - expression = "-MAILLIST & BLACKLIST_ANTISPOOF"; + expression = "!MAILLIST & BLACKLIST_ANTISPOOF"; message = "Rejected (anti-spoofing: auth-failed)"; } } From 0f17299b4e6c6deba13a7755fb547409aa235bd2 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 25 Oct 2022 14:43:47 +0200 Subject: [PATCH 16/19] Admin may not have started up when this loads --- core/rspamd/conf/multimap.conf | 8 ++++++-- core/rspamd/conf/whitelist.conf | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/core/rspamd/conf/multimap.conf b/core/rspamd/conf/multimap.conf index dd25c08e..7592fee0 100644 --- a/core/rspamd/conf/multimap.conf +++ b/core/rspamd/conf/multimap.conf @@ -1,11 +1,15 @@ IS_LOCAL_DOMAIN_H { type = "selector" selector = "from('mime'):domain"; - map = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; + map = [ +"http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains", +"fallback+file:///dev/null"]; } IS_LOCAL_DOMAIN_E { type = "selector" selector = "from('smtp'):domain"; - map = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; + map = [ +"http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains", +"fallback+file:///dev/null"]; } diff --git a/core/rspamd/conf/whitelist.conf b/core/rspamd/conf/whitelist.conf index 56f8a83d..01efd80d 100644 --- a/core/rspamd/conf/whitelist.conf +++ b/core/rspamd/conf/whitelist.conf @@ -2,7 +2,7 @@ rules { BLACKLIST_ANTISPOOF = { valid_dmarc = true; blacklist = true; - domains = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; + domains = ["http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains", "fallback+file:///dev/null"]; score = 0.0; } } From d8cf0c3848475221288f46a8264e9252c93e0156 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 27 Oct 2022 10:21:19 +0200 Subject: [PATCH 17/19] Revert "Admin may not have started up when this loads" This reverts commit 0f17299b4e6c6deba13a7755fb547409aa235bd2. --- core/rspamd/conf/multimap.conf | 8 ++------ core/rspamd/conf/whitelist.conf | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/core/rspamd/conf/multimap.conf b/core/rspamd/conf/multimap.conf index 7592fee0..dd25c08e 100644 --- a/core/rspamd/conf/multimap.conf +++ b/core/rspamd/conf/multimap.conf @@ -1,15 +1,11 @@ IS_LOCAL_DOMAIN_H { type = "selector" selector = "from('mime'):domain"; - map = [ -"http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains", -"fallback+file:///dev/null"]; + map = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; } IS_LOCAL_DOMAIN_E { type = "selector" selector = "from('smtp'):domain"; - map = [ -"http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains", -"fallback+file:///dev/null"]; + map = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; } diff --git a/core/rspamd/conf/whitelist.conf b/core/rspamd/conf/whitelist.conf index 01efd80d..56f8a83d 100644 --- a/core/rspamd/conf/whitelist.conf +++ b/core/rspamd/conf/whitelist.conf @@ -2,7 +2,7 @@ rules { BLACKLIST_ANTISPOOF = { valid_dmarc = true; blacklist = true; - domains = ["http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains", "fallback+file:///dev/null"]; + domains = "http://{{ ADMIN_ADDRESS }}/internal/rspamd/local_domains"; score = 0.0; } } From 89f7d983b41a41f17dcd4d1f8a2adf5696682ed2 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 27 Oct 2022 10:51:45 +0200 Subject: [PATCH 18/19] Don't start rspamd until admin is up and working --- core/rspamd/start.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/rspamd/start.py b/core/rspamd/start.py index fcb33a97..b03a602f 100755 --- a/core/rspamd/start.py +++ b/core/rspamd/start.py @@ -3,7 +3,9 @@ import os import glob import logging as log +import requests import sys +import time from socrate import system, conf log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING")) @@ -19,5 +21,16 @@ if os.environ.get("ANTIVIRUS") == 'clamav': for rspamd_file in glob.glob("/conf/*"): conf.jinja(rspamd_file, os.environ, os.path.join("/etc/rspamd/local.d", os.path.basename(rspamd_file))) +# Admin may not be up just yet +healthcheck = f'http://{os.environ["ADMIN_ADDRESS"]}/internal/rspamd/local_domains' +while True: + time.sleep(1) + try: + if requests.get(healthcheck,timeout=2).ok: + break + except: + pass + print("Admin is not up just yet, retrying in 1 second") + # Run rspamd os.execv("/usr/sbin/rspamd", ["rspamd", "-i", "-f"]) From ec4224123baaabcaac12eae8f65a3b268165bead Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Fri, 28 Oct 2022 18:28:31 +0200 Subject: [PATCH 19/19] Use the logger --- core/rspamd/start.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/rspamd/start.py b/core/rspamd/start.py index b03a602f..031aaf88 100755 --- a/core/rspamd/start.py +++ b/core/rspamd/start.py @@ -30,7 +30,7 @@ while True: break except: pass - print("Admin is not up just yet, retrying in 1 second") + log.warning("Admin is not up just yet, retrying in 1 second") # Run rspamd os.execv("/usr/sbin/rspamd", ["rspamd", "-i", "-f"])