continued writing
This commit is contained in:
parent
00185887bd
commit
df56646845
1 changed files with 78 additions and 80 deletions
|
|
@ -31,7 +31,7 @@ Put simply, a mail server will accept an email if…
|
|||
|
||||
I have created two illustrations to explain it.
|
||||
|
||||
### Outgoing email (without authentication)
|
||||
### Without authentication = denied
|
||||
|
||||
`john@example.org` is on the internet somewhere and wants to send an email to `lisa@example.com` (which is another
|
||||
domain). Your mail server is not responsible for the _example.com_ domain so it receives John’s email and would have to
|
||||
|
|
@ -62,7 +62,7 @@ Towards the end of the output you will find:
|
|||
<~* 554 5.7.1 <list@example.com>: Recipient address rejected: Access denied
|
||||
```
|
||||
|
||||
### Outgoing email (with authentication)
|
||||
### With authentication = accepted
|
||||
|
||||
So how does John prove his identity? He needs to use _authenticated_ SMTP. This is similar to the previous case but
|
||||
John’s email program will also send his username and password.
|
||||
|
|
@ -99,8 +99,7 @@ username and password. Postfix just needs some extra configuration. Run these co
|
|||
|
||||
```
|
||||
postconf smtpd_sasl_type=dovecot
|
||||
postconf smtpd_sasl_path=private/auth
|
||||
postconf smtpd_sasl_auth_enable=yes
|
||||
postconf smtpd_sasl_path=private/dovecot-auth
|
||||
```
|
||||
|
||||
This enables SMTP authentication and tells Postfix that it can talk to Dovecot through a socket file located at
|
||||
|
|
@ -113,45 +112,38 @@ TODO: collapsible on anti-spoofing
|
|||
|
||||
## Enable encryption
|
||||
|
||||
TODO: move this section to a separate page on TLS encryption
|
||||
|
||||
We certainly do not want our users to send their password over the wire wihtout encryption. So the following commands
|
||||
enable encryption, set the key and certificate paths for Postfix. Just run these commands:
|
||||
|
||||
```
|
||||
postconf smtp_tls_security_level=may
|
||||
postconf smtpd_tls_security_level=may
|
||||
postconf smtpd_tls_auth_only=yes
|
||||
postconf smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.org/fullchain.pem
|
||||
postconf smtpd_tls_key_file=/etc/letsencrypt/live/mail.example.org/privkey.pem
|
||||
postconf smtp_tls_security_level=may
|
||||
```
|
||||
|
||||
What it means:
|
||||
|
||||
- **smtp_tls_security_level**: \
|
||||
Allow encrypted _outgoing_ SMTP connections but do not enforce it.
|
||||
- **smtpd_tls_security_level**: \
|
||||
Allow encrypted _incoming_ SMTP connections but do not enforce it.
|
||||
- **smtpd_tls_cert_file** and **smtpd_tls_key_file**: \
|
||||
Where to find the private key and certificate for encryption.
|
||||
|
||||
Please note that configuration in `main.cf` applies to all Postfix services. So the above configuration enabled
|
||||
encryption for both server-to-server and human-to-server (`submission`) services. The `smtpd_sasl_auth_enable` will only
|
||||
be set for the `submission` service to enable authentication there.[^1]
|
||||
|
||||
<Aside type="tip" title="smtp or smtpd?">
|
||||
Look closely. Some settings start with “smtp\_” and others with “smtpd\_”. That is not a typo. “smtp\_” refers to the
|
||||
SMTP _client_. That is the component that sends out emails **from** Postfix **to** other servers. Whereas “smtpd\_”
|
||||
means the SMTP _server._ That in turn is the component that **receives** emails **from** other systems – either from a
|
||||
remote mail server or one of your users.
|
||||
</Aside>
|
||||
|
||||
The above settings allow encrypted incoming (smtpd\_) and outgoing (smtp\_) connections. But they do not enforce it. If
|
||||
a remote mail server does not have encryption enabled we will still accept their emails. You may be tempted to enforce
|
||||
encryption but that would reject email communication with servers who have been configured without encryption.
|
||||
|
||||
However the `smtpd_tls_auth_only=yes` setting makes sure that the user’s authentication information (email address and
|
||||
password) are always encrypted between the user and your mail server.
|
||||
|
||||
<Aside type="tip" title="Restrictions">
|
||||
In the past you may have configured your _smtpd\_recipient\_restrictions_ to restrict relaying to authenticated users.
|
||||
Postfix nowadays has setting called
|
||||
“[smtpd\_relay\_restrictions](http://www.postfix.org/postconf.5.html#smtpd_relay_restrictions)” that deals with
|
||||
relaying requests in the “RCPT TO” phase of the SMTP dialog. So essentially it works like the good old
|
||||
“smtpd\_recipient\_restrictions” but is checked first. _smtpd\_relay\_restrictions_ has a reasonable default so
|
||||
authenticated relaying works automatically: `smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated
|
||||
defer_unauth_destination`
|
||||
Look closely. Some settings start with `smtp_` and others start with with `smtpd_`. That is not a typo. `smtp_` refers
|
||||
to the SMTP _client_. That is the component that sends out emails **from** Postfix **to** other servers. Whereas
|
||||
`smtpd_` means the SMTP _server._ That in turn is the component that **receives** emails **from** other systems –
|
||||
either from a remote mail server or one of your users.
|
||||
</Aside>
|
||||
|
||||
<details class="collapsible">
|
||||
<summary>Click here to learn how SMTP authentication works…</summary>
|
||||
<summary>Click here if you want to learn how SMTP authentication works…</summary>
|
||||
|
||||
Are you curious how SMTP authentication looks on a low level? You probably are not. But let’s do it anyway. Just once,
|
||||
so that you get the idea.
|
||||
|
|
@ -203,7 +195,7 @@ Let me briefly explain what these lines mean:
|
|||
The remote server is allowed to send emails up to 10 MB large. This has long been a common maximum size for emails. However
|
||||
nowadays 40 MB or even more are more common sizes because emails have grown larger. Some mail servers even allow 100 MB.
|
||||
- VRFY
|
||||
Allows remote servers to verify a given name or email address. For example the remote server could send “VRFY john” and
|
||||
Allows remote servers to verify a given name or email address. For example the remote server could send "VRFY john" and
|
||||
your server might respond `250 John Doe <john@example.org>`. It can be used to verify that a certain recipient email address
|
||||
is deliverable
|
||||
- ETRN
|
||||
|
|
@ -212,15 +204,15 @@ Let me briefly explain what these lines mean:
|
|||
your server start sending outstanding emails for that domain. It is rarely used.
|
||||
- STARTTLS
|
||||
This tells the remote system that it might start switching from this unencrypted to an encrypted connection by sending
|
||||
the “STARTTLS” command. It will then start negotiating a TLS-encrypted connection. You could compare it to an HTTP connection
|
||||
the "STARTTLS" command. It will then start negotiating a TLS-encrypted connection. You could compare it to an HTTP connection
|
||||
that suddenly switches over to an encrypted HTTPS connection. The advantage is that you can start talking SMTP on TCP port
|
||||
25 and don’t have to open up a second TCP port like 465 which is the “SSMTP” (secure SMTP) port and only accepts encrypted
|
||||
25 and don’t have to open up a second TCP port like 465 which is the "SSMTP" (secure SMTP) port and only accepts encrypted
|
||||
connections.
|
||||
- ENHANCEDSTATUSCODES
|
||||
This enables more three-digit return codes for various conditions. See the [RFC2034](http://tools.ietf.org/html/rfc2034)
|
||||
if you are curious.
|
||||
- 8BITMIME
|
||||
In ancient times SMTP only processed 7-bit characters. You couldn’t transfer special characters like “Ä” or “ß” without
|
||||
In ancient times SMTP only processed 7-bit characters. You couldn’t transfer special characters like "Ä" or "ß" without
|
||||
special encoding. 8BITMIME allows a transmission of emails using 8-bit characters. Still many emails are specially encoded
|
||||
using ISO8859-1 or UTF-8.
|
||||
- DSN
|
||||
|
|
@ -254,7 +246,7 @@ And the server replies:
|
|||
```
|
||||
|
||||
However now it’s getting weird because you would have to speak TLS encryption which is not a language that humans speak.
|
||||
So let’s quit this using the “QUIT” command and do that differently:
|
||||
So let’s quit this using the "QUIT" command and do that differently:
|
||||
|
||||
```
|
||||
QUIT
|
||||
|
|
@ -293,7 +285,7 @@ string with a Base64-encoded password:
|
|||
AUTH PLAIN AGpvaG5AZXhhbXBsZS5vcmcAc3VtbWVyc3Vu
|
||||
```
|
||||
|
||||
Unless you have changed John’s password to something else than “summersun” the server should accept that authentication:
|
||||
Unless you have changed John’s password to something else than "summersun" the server should accept that authentication:
|
||||
|
||||
```
|
||||
235 2.7.0 Authentication successful
|
||||
|
|
@ -330,7 +322,7 @@ So for John’s case you can easily create the Base64 string using:
|
|||
printf '\0john@example.org\0summersun' | base64
|
||||
```
|
||||
|
||||
As a result you will get the exact same string you used above with “AUTH PLAIN”.
|
||||
As a result you will get the exact same string you used above with "AUTH PLAIN".
|
||||
|
||||
</details>
|
||||
|
||||
|
|
@ -338,50 +330,49 @@ As a result you will get the exact same string you used above with “AUTH PLAIN
|
|||
|
||||
Please note that there are two different TCP ports on a mail server that speak SMTP:
|
||||
|
||||
| Service name | SMTP | Submission |
|
||||
| -------------- | -------------------------- | --------------------- |
|
||||
| TCP Port | 25 | 587 |
|
||||
| Encryption | Optional | Mandatory |
|
||||
| Authentication | Optional | Mandatory |
|
||||
| Meant for | Servers | Humans |
|
||||
| Used by | Mail transport agent (MTA) | Mail user agent (MUA) |
|
||||
| Your home ISP | may block this port | will allows this port |
|
||||
| Service name | SMTP | Submission | Submission TLS |
|
||||
| -------------------- | ------------------------------------ | ------------------------------------------- | --------------------------- |
|
||||
| TCP Port | 25 | 587 | 465 |
|
||||
| Transport encryption | **Off** at first. STARTTLS optional. | **Off**. Then switch to TLS using STARTTLS. | **On** right from the start |
|
||||
| Authentication | Optional [^1] | Mandatory | Mandatory |
|
||||
| Meant for | Servers | Humans | Humans |
|
||||
| Used by | Mail transport agent (MTA) | Mail user agent (MUA) | Mail user agent (MUA) |
|
||||
| Your home ISP | may block this port | will allows this port | will allow this port |
|
||||
|
||||
I hope that makes the distinction a bit clearer. Our human users will have to use the _submission_ service.
|
||||
[^1]:
|
||||
In previous guides I recommended to set `smtpd_sasl_auth_enable=yes` globally in the `main.cf`. That would indeed
|
||||
enable authentication on port 25. For a clearer separation I now rather suggest to leave it out (default is `no`)
|
||||
and just enable authentication on the `submission` service in the `master.cf` file. A possible scenario that
|
||||
required this setting to be `on` would be if your server were a relay (_smarthost_) for other servers using
|
||||
authentication..
|
||||
|
||||
All Postfix services are declared in the `/etc/postfix/master.cf` file. Please edit the file and look for the
|
||||
_submission_ section that is commented out by default. Turn that section into the following. Basically I removed the ‘#’
|
||||
character on all lines of this section and removed the lines with the mua\_\* variables.
|
||||
I hope that makes the distinction a bit clearer. Our human users will have to use the _submission_ service either on 587
|
||||
or 465.
|
||||
|
||||
## Configure the submission service
|
||||
|
||||
All Postfix services are declared in the `/etc/postfix/master.cf` file. Most of them are used by Postfix internally,
|
||||
like `pickup`, `cleanup`, `rewrite` or `bounce`. But let's another section anywhere in there:
|
||||
|
||||
```
|
||||
submission inet n - y - - smtpd
|
||||
submission inet n - y - - smtpd
|
||||
-o syslog_name=postfix/submission
|
||||
-o smtpd_tls_security_level=encrypt
|
||||
-o smtpd_sasl_auth_enable=yes
|
||||
-o smtpd_tls_auth_only=yes
|
||||
-o smtpd_reject_unlisted_recipient=no
|
||||
-o smtpd_client_restrictions=
|
||||
-o smtpd_helo_restrictions=
|
||||
-o smtpd_sender_restrictions=
|
||||
-o smtpd_relay_restrictions=
|
||||
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
|
||||
-o milter_macro_daemon_name=ORIGINATING
|
||||
```
|
||||
|
||||
Make sure to start the first line in the first column and indent the following lines.
|
||||
Some notes on that:
|
||||
|
||||
This service uses the “smtpd” daemon (see the last word of the first line) which is the piece of software that responds
|
||||
if you open an SMTP connection on TCP port 25. But it gets a few extra options set…
|
||||
|
||||
- in the /var/log/mail.log log file you will see the connections to the submission port as “postfix/submission” (the
|
||||
_syslog_name_ setting above)
|
||||
- enforce encryption on this port (_smtpd_tls_security_level_)
|
||||
- enable authentication (_smtpd_sasl_auth_enable_)
|
||||
- enforce encryption during authentication (_smtpd_tls_auth_only_)
|
||||
- allow sending emails to recipients outside of this mail server (_smtpd_reject_unlisted_recipient_)
|
||||
- remove special restrictions (_smtpd\_\*\_restrictions_)
|
||||
- allow relaying if the sender was authenticated (_smtpd_recipient_restrictions_)
|
||||
- send the string _ORIGINATING_ to milter services (_milter_macro_daemon_name_) – you can just leave it like that
|
||||
- Lines with options (`-o`) need to be indented.
|
||||
- The word `submission` refers to the definition of the service in the `/etc/services` file. So it translates to TCP
|
||||
port 587.
|
||||
- The `smtpd` at the end tells Postfix that connections should be handled as incoming SMTP connections.
|
||||
- **syslog_name** is adding `postfix/submission` to log files so that you can distinguish it from other connections.
|
||||
- **smtpd_sasl_auth_enable** enables authentication on this port. SASL is short for _Simple Authentication and Security
|
||||
Layer_.
|
||||
- **smtpd_recipient_restrictions** define that only authenticated connections are permitted. Without a username and a
|
||||
password your connection will be rejected.
|
||||
|
||||
Restart the Postfix server:
|
||||
|
||||
|
|
@ -396,30 +387,37 @@ Feel free to send a test mail using the submission port and encryption. You will
|
|||
package first, so that SWAKS can speak TLS:
|
||||
|
||||
```
|
||||
apt install -y libnet-ssleay-perl
|
||||
swaks --server localhost --to john@example.org \
|
||||
swaks --server localhost:587 \
|
||||
--from john@example.org \
|
||||
--to lisa@example.com \
|
||||
--port 587 -tls \
|
||||
--auth-user john@example.org \
|
||||
--auth-password summersun
|
||||
```
|
||||
|
||||
<Aside type="tip" title="What is Port 465?">
|
||||
This TCP port belongs to the “submission over TLS” service. It is used for the submission service but expects an
|
||||
encrypted connection from the first byte. This port is hardly ever used so you don’t have to care about it. The
|
||||
submission service you just configured is also encrypted but uses the STARTTLS mechanism to switch to a TLS connection
|
||||
after the welcome message.
|
||||
<Aside type="caution">
|
||||
|
||||
At this point there is still a security flaw. We told Postfix to relay emails only if we authenticate with a valid
|
||||
username and password. But will it keep us from impersonating an arbitrary sender address?
|
||||
|
||||
No, it will not restrict that. We could be authenticating as `john@example.org` but send an email in the name of
|
||||
`brunhilde@example.org`.
|
||||
|
||||
If you want to allow users to send as one of their aliases you could create a new \*.cf file with a mapping query like
|
||||
this: `SELECT email FROM virtual_users WHERE email='%s' UNION SELECT destination FROM virtual_aliases WHERE source='%s'`
|
||||
|
||||
</Aside>
|
||||
|
||||
## Protecting against forged sender addresses
|
||||
|
||||
A “forged” sender address means that someone claims to be someone else. Let’s say that John has authenticated and the
|
||||
A "forged" sender address means that someone claims to be someone else. Let’s say that John has authenticated and the
|
||||
mail server trusts him. Nothing keeps John from impersonating someone else and sending email in his name? Most email
|
||||
service providers have restrictions that you can only send emails if the sender matches your actual email address. Let’s
|
||||
do that, too.
|
||||
|
||||
Postfix provides a setting called
|
||||
[smtpd_sender_login_maps](http://www.postfix.org/postconf.5.html#smtpd_sender_login_maps) for that purpose. From the
|
||||
“maps” part you can deduce that it expects a _mapping_ again. This time the two columns mean…
|
||||
"maps" part you can deduce that it expects a _mapping_ again. This time the two columns mean…
|
||||
|
||||
- Left column: who you claim to be (email’s sender address)
|
||||
- Right column: who you logged in as (user name after authentiation)
|
||||
|
|
@ -466,7 +464,7 @@ rejected. The server should tell you:
|
|||
```
|
||||
|
||||
Sorry if the mixture of example.org and example.com in my examples makes this guide less readable. But I can’t use any
|
||||
real world domains here. Please just note that sometimes it’s “.com” and sometimes “.org”.
|
||||
real world domains here. Please just note that sometimes it’s ".com" and sometimes ".org".
|
||||
|
||||
Of course you can test your new security feature in the Roundcube web mail interface as well. In Settings/Identities you
|
||||
can create another sender email address as in:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue