Open polarathene opened 2 years ago
Nice! We could make people that want to start working on DMS guide to this issue as a nice "beginner-friendly" way of getting to know the project.
Potentially useful notes related to this topic when revisiting this issue.
smtpd_sasl_auth_enable
- Port 25 no longer supports SASL auth for submitting mail for Postfix to send. Potentially relevant to tracking history of SPOOF_PROTECTION=1
feature (which only applies to SASL).
Recently SPOOF_PROTECTION=1
being changed to default for the v12
release was proposed.
This issue was cited to discourage that for the time being due to variety of config changes already introduced into v12
and the concerns raised around the SPOOF_PROTECTION
feature support in this issue above.
This may be useful to migrate into technical documentation for maintainers in future.
The SPOOF_PROTECTION=1
feature is implemented in Postfix with smtpd_sender_restrictions
with any of the rejection policies listed below, presently the feature chooses reject_authenticated_sender_login_mismatch
.
smtpd_sender_login_maps
example config can be found here in Postfix docs in addition to usage with main.cf:smtpd_sender_restrictions
(_docs incorrectly assign to smtpd_recipient_restrictions
_). The Additional Notes section above provides more info on the smtpd_sender_login_maps
config format and our usage of regex
+ unionmap
config tables with it.
smtpd_sender_login_maps
- Config for SASL account lookups used by settings these settings when SASL is enabled:
reject_authenticated_sender_login_mismatch
reject_known_sender_login_mismatch
reject_authenticated_sender_login_mismatch
, only protecting spoofing of known accounts.reject_unauthenticated_sender_login_mismatch
reject_sender_login_mismatch
reject_authenticated_sender_login_mismatch
and reject_unauthenticated_sender_login_mismatch
.Mail received by Postfix goes through this sequence of restriction checks.
SPOOF_PROTECTION
feature code has since migrated to here (with upcoming changes in this PR):
When someone has time to, the conditionals there can be refactored, as described in the Task Overview at the start of this issue. LDAP perhaps can be updated later if easier.
Adding this here in case anyone else has time to tackle any of it.
I am not likely to have the time until at least December, but I expect I'll have to prioritize my time on other commitments before I can come back to addressing these tasks.
Task Overview
I've provided plenty of helpful details below, but a summary of tasks to complete is:
SPOOF_PROTECTION=1
feature:unionmap
and drop the conditional, as the file always exists, there is no known reason to need the alternative without unionmap or additional regex table.unionmap
, which is not a regex table. It will allow explicitly allowing additional senders for an account to send as.@gmail
related issue section below.unionmap
would also be relevant for theldap
equivalent value in that same linked method.noreply@external-domain
from referenced send-only related issue below. Likewise with the LDAP specific config ENV that was added to support the feature specifically there.Related alias support:
setup alias add
section below notes a bug to resolve, and CLI help message to update. It also has poor error handling feedback if somesetup
commands do not receive the expected number of inputs IIRC (may have beensetup alias del
)./etc/postfix/vhost
", it has been identified that we could improve how we determine what domains are managed.main.cf
settings more appropriately./etc/postfix/vhost
is presently sourced elsewhere, such as the DKIM generation support insetup
command.SPOOF_PROTECTION=1
handling forsmtpd_sender_login_maps
Jan 2021, @georglauterbach created and merged a PR to fix a user reported bug. The PR introduced a
unionmap: { ... }
table, which Postfix queries each listed table and merges the responses, rather than accepting the first matched response and exiting early with that outcome (as the result may fail, but have passed from another valid match rule later on).Nothing wrong there, but it was the PR that split the non-LDAP handling for
smtpd_sender_login_maps
(_used for ENVSPOOF_PROTECTION=1
_) into two values, only allowing theunionmap
when/etc/postfix/regexp
config was present. This does not seem necessary, and using theunionmap
regardless is probably fine?https://github.com/docker-mailserver/docker-mailserver/blob/ff969509f8b9c49e399327887c9a29f6fd664b80/target/scripts/helpers/aliases.sh#L29-L37
https://github.com/docker-mailserver/docker-mailserver/blob/ff969509f8b9c49e399327887c9a29f6fd664b80/target/scripts/start-mailserver.sh#L116-L123
/etc/postfix/regexp
is always created during startup, and it has always been before this logic is run, even before that PR which added the conditional check on it's existence. We would always getunionmap
AFAIK. It may even be useful for the LDAP configs.As a refresher for anyone reading
SPOOF_PROTECTION=1
(opt-in) prevents submitting any mail to send unless the logged in account is authorized to send from that envelope address (FROM
) insmtpd_sender_login_maps
lookup tables. The ENV does this by adding this restriction:smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch
(prefixed in front of other sender restrictions).Without this, our default config allows a logged in user to send mail "from" whatever address they'd like to, including other accounts for the same domain, or one that DMS doesn't manage. The related bug report that introduced the fix with
unionmap
, has a user explain a good use-case for wanting that, non-human service accounts being restricted to their account only for sending mail in-case the service is compromised, while using a regex to allow theirmail@example.com
account (admin) to be able to send as any address for that domain.When opting into
SPOOF_PROTECTION=1
, we permit local aliases (root
,amavis
, etc) (_that linked PR introduced thePOSTMASTER_ADDRESS
ENV and alias, along with settingmydestination
inmain.cf
_), account aliases, and a few other lookup tables in theunionmap
. One of these is a regexp filesender_login_maps.pcre
that will match whatever the owners sender address is, and allow it (There is similar advice elsewhere, that suggests this approach, seems fine). A more specific match would have higher priority I think, but it may just depend on whatever is matched first from top to bottom of a table.It should be noted that without the
/etc/postfix/virtual
table for account aliases included in theunionmap
, you cannot send from an alias (eg:marketing@example.com
), but you can authenticate over SASL as your aliased account by using that alias as the login account/username. That still logs the user in as the aliased account, not the alias, thus the actual account is still what is checked for allowed sender addresses that can be used regardless.The original PR that introduced this feature with
SPOOF_PROTECTION=1
also has discussion about enabling it by default in future breaking change. And some users sharing concerns about their workflows being broken, one from a previous maintainer who was using aliases to reply to mail keeping the sameFROM
address in the message, while only having a single mail account to manage.Additional Notes
The
/etc/postfix/regexp
table was added in this PR, when the user previously tried to use a catch-all alias@example.com
and noticed it did not work for them (received but could not send), possibly related to the later fix of using aunionmap
table.If we have any LDAP related issues with the feature, this may be helpful. That had a follow-up issue which also had a related PR merged for improving LDAP support with an optional filter config ENV - it demonstrates how to allow an additional sender address for
noreply@example.com
.The tables for
smtpd_sender_login_maps
are pretty simple, the left-side (1st column) is to match the desired sender address (explicit value or regex pattern depending on table type), and on the right-side (2nd column) is usually the owner address (login mail account, non-aliased), but it can be multiple addresses to allow too by using a,
delimiter just like the/etc/postfix/virtual
alias table allows to map an alias to multiple recipients.If using a regex pattern, keep in mind that whatever matches in a table first is the pass/fail for that table, regardless of the
unionmap
usage. As noted by this users comment that had two lines/.*/
to approve two separate domains, only the first would ever be matched. The response suggests moving the 2nd line to a separate table, but they should be able to fold the 2nd domain into a single line for that same regexp as mentioned above with,
delimiter.The ENV docs for
SPOOF_PROTECTION=1
notes that extension delimiters (eg:+
) are no longer usable as we don't have a table to authorize them out of the box. Technically it should be possible with regex as well? Would need some testing to ensure it's not abused.unionmap
withsmtpd_sender_login_maps
is covered well with the problem it solves in this blog article.The Postfix SASL docs briefly touch on related configuration discussed here, but seems to incorrectly reference using it with
smtpd_recipient_restrictions
rather thansmtpd_sender_restrictions
.SPOOF_PROTECTION=1
only restricts the envelopeFROM
sender address, spoofing still feasible?Despite
SPOOF_PROTECTION=1
applying these settings to restrict what a sender can use inFROM
(mail envelope), this doesn't prevent spoofing of thefrom:
(mail message) header apparently. This is mentioned here, in a link it references, that resource links to another that clarifies the difference between envelope and messageFROM
headers, and how SPF+DKIM+DMARC are leveraged to better handle this.Thus
SPOOF_PROTECTION
may not be the most appropriate ENV name, it's mostly to restrict your own authenticated accounts to what sender addresses can be used in the envelopeFROM
when they submit mail, which is still worthwhile to do. There is this project which is a Postfix milter designed to ensure the sender envelope and message are the same, which prevents OpenDKIM signing the message sender (From:
header) for a mismatch on the same domain, but different account.Related
Supporting send-only addresses without a regex table
A recent feature-request was raised for allowing accounts to opt-out from being considered managed by Postfix. They provide their solution to use another config for
scripts/helpers/postfix.sh:_vhost_collect_postfix_domains()
to exclude any account using a mentioned domain. I believe we have a similar opt-out config feature for when a relayhost is enabled (due to blanket adding all accounts to the relay..).That prompted me as likely a misconfiguration (confirmed, due to lack of our docs covering how to support the use-case). Their use-case was to send mail as
noreply@<external-domain>
, howeverSPOOF_PROTECTION=1
was restricting this without a matching account for that address - but as they wanted to send to a user at that same external domain (which was now considered managed by Postfix), it tries to deliver internally instead of outbound to the intended external mail-server. Thenoreply
sender address was only for sending to external accounts, not receiving any inbound mail, an account is therefore not necessary to resolve this use-case properly.I investigated and figured that they'd be better to use an opt-in config for what account should be allowed to send as an external account instead, which the
smtpd_sender_login_maps
can allow just fine. My link to that issue provides an example for how to setup a local testing environment that proves this approach works well. Normally it's not an issue whenSPOOF_PROTECTION=0
(default), as an authenticated user can use whatever sender address they like then.Only issue is that using regex probably isn't always appropriate - Users need to be careful with what expressions they use, often forgetting to escape regex tokens like
.
when providing a domain (I came across quite a few snippets where this was the case). However all the other tables aren't specifically for this feature which could cause issues, so another table should be made available within theunionmap
. I haven't looked over the earlier mentioned LDAP PR that added a related config ENV to extend support, but assume it provides similar flexibility when needed.If
SPOOF_PROTECTION=1
was to be enabled in future as a default, we should first support configuring with an alternative table (eg:texthash:/etc/postfix/senders-map.cf
or similar would be fine), along with supporting documentation and release notes (probably warrants a notice period before switching the default for the feature?).External accounts being handled as internal accidentally?
Related is another scenario / issue, again regarding a
noreply
sending account (but this one would belong to the internal domain). It's recipients are provided from LDAP accounts, and some users are remote / external addresses, such asuser@gmail.com
.I'm inclined to think this is more of an issue with their LDAP config, as DMS should not be treating
@gmail
as managed, unless your config is creating them as internal mail accounts for DMS (equivalent ofpostfix-accounts.cf
), or misconfigured as aliases (since we collect any alias domain into the Postfix/etc/postfix/vhost
to be treated as managed by DMS).Their desire was to try match the recipient mail is to be sent out to in hopes of convincing Postfix to deliver as outbound mail. Again, these accounts were not to receive mail to DMS, or forward / relay any inbound mail arriving to DMS to these external mail-servers (eg: Gmail). The only intention was having the
noreply@example.com
send out notifications from a service to these LDAP users associated mail accounts (where some of the LDAP users areexample.com
accounts, but not all).In this case rather than matching the
FROM
envelope, I believe we could workaround by using atransport_maps
table that matches theTO
(recipient). The prior send-only issue above did have a solution proposed to opt-out of managing entire domains (by excluding them from Postfix/etc/postfix/vhost
), I'm just not convinced that's something we should maintain.I lack LDAP knowledge, but cannot think of how this would be setup in a non-LDAP config where it'd make sense to create
@gmail
accounts - but I have seen users create aliases to remote addresses / accounts like Gmail? (which can introduce the same problem if the remote domain is incorrectly added as the alias, not the recipient that an alias should map to)We have the following described in our docs at the end of this example:
Directly after that
SPOOF_PROTECTION=0
example is one forSPOOF_PROTECTION=1
, where the advice is to create an intermediate alias, to workaround the sender map problem. That works because we include the alias table of aliases mapping to whatever recipients, and treating those as owners. A workaround that shouldn't be needed / used.The Postfix virtual docs on alias forwarding has a similar example (_excluding the
SPOOF_PROTECTION
issue_).setup alias add
The
setup alias add
command "usage" / help could better match ouraddalias
utility which is more clear on the inputs?:https://github.com/docker-mailserver/docker-mailserver/blob/ff969509f8b9c49e399327887c9a29f6fd664b80/target/bin/setup#L46-L47
The internal utility makes it more apparent the first input is an alias that is mapped to recipient(s) (internal
postfix-accounts.cf
, external addresses, or other aliases):https://github.com/docker-mailserver/docker-mailserver/blob/ff969509f8b9c49e399327887c9a29f6fd664b80/target/bin/addalias#L21-L22
setup alias add alias@example.com account@example.com
will create an aliasalias@example.com
that maps to internal accountaccount@example.com
.setup email list
will show that alias associated to the account as expected.setup alias add user@example.com user@gmail.com
will create an aliasuser@example.com
that will map to a remoteuser@gmail.com
account. Mail received / submitted touser@example.com
is forwarded to that remote address instead of stored in a local mailbox. Unless Postfix believes it manages that domain.setup email list
ifuser@example.com
exists as an account also, will list theuser@example.com
alias as an alias to the account itself.. but that's a side-effect bug from allowing such in the first place.Apart from the bug issue, our aliases docs communicate roughly the same two scenarios described above for
setup alias add
:+1:Alias domains being added to
/etc/postfix/vhost
We've had this support introduced way back in Oct 2015, which now lives in a dedicated vhost helper script that I created during a refactoring via this PR (June 2022).
I discussed further details regarding it and related Postfix
main.cf
config in the send-only linked issue above. As thepostfix-regexp.cf
for alias support came after that Oct 2015 PR, and our scripts can't realistically scrape domains from a regex, it could be better to have Postfix use the correct tables to lookup directly when it needs to, which would allow for the alias regex.Postfix provides separate config to check for accounts and aliases regarding if it should be considered the final destination for delivery of mail received/sent. We could better leverage that support directly. It would also allow for users to more easily opt-out domains I think, should they really need to.