diff --git a/content/en/docs/tutorials/email/dkim.md b/content/en/docs/tutorials/email/dkim.md new file mode 100644 index 0000000..722c9b2 --- /dev/null +++ b/content/en/docs/tutorials/email/dkim.md @@ -0,0 +1,191 @@ +--- +title: Setting up DKIM +description: Tutorial for setting up DKIM signing/verification on Postfix using OpenDKIM +date: 2017-01-04 +weight: 30 +--- + +Email headers contain a `FROM:` line that identifies the sender. This line is a part of the data sent, and is not used when the email is being routed to its destination. This means that an email can be successfully sent with an address in its `FROM:` line that does not match the actual sender; a flaw of SMTP used by malicious actors in order to send emails that appear to come from a legitimate source. This is called [email spoofing](https://www.cloudflare.com/learning/email-security/what-is-email-spoofing/). + +Modern mail servers contain several protections against email spoofing, with one of the more advanced being DomainKeys Identified Mail (DKIM). MTA servers configured with DKIM sign outgoing emails. The signature is then verified against a public [DNS TXT record](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/) that has a special format. + +It is highly recommended to set up DKIM on any self hosted mail server, as otherwise a lot of mail services such as Gmail will automatically assume that mail sent from your mail server is spam. + +We will configure DKIM for `postfix` using [OpenDKIM](http://www.opendkim.org), which is set up as a milter. I found [this tutorial](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy) helpful when setting this up. + +OpenDKIM can be installed using: +``` bash +sudo apt-get update +sudo apt-get install -y opendkim opendkim-tools +``` + +## Reloading configuration + +OpenDKIM is configured via a config file at `/etc/opendkim.conf`. After changes to this file, you must restart the service: +``` bash +sudo service opendkim restart +``` +for the changes to take effect. + +## Basic Configuration + +A basic configuration can be added using the following +``` bash +echo ' +# auto restart the DKIM filter on failures +AutoRestart Yes +# specifies the filter’s maximum restart rate, if restarts begin to happen faster than this rate, the filter will terminate; 10/1h - 10 restarts/hour are allowed at most +AutoRestartRate 10/1h + +# gives all access permissions to the user group defined by UserID and allows other users to read and execute files +UMask 002 +# the opendkim process runs under this user and group +UserID opendkim:opendkim + +# these parameters enable detailed logging via calls to syslog +Syslog Yes +SyslogSuccess Yes +LogWhy Yes + +# defines the canonicalization methods used at message signing +# - the simple method allows almost no modification while +# - the relaxed one tolerates minor changes such as whitespace replacement; +# - relaxed/simple: the message header will be processed with the relaxed algorithm and the body with the simple one +Canonicalization relaxed/simple + +# specifies the external hosts that can send mail through the server as one of the signing domains without credentials +ExternalIgnoreList refile:/etc/opendkim/TrustedHosts +# defines a list of internal hosts whose mail should not be verified but signed instead +InternalHosts refile:/etc/opendkim/TrustedHosts +# maps key names to signing keys +KeyTable refile:/etc/opendkim/KeyTable +# lists the signatures to apply to a message based on the address found in the From: header field +SigningTable refile:/etc/opendkim/SigningTable + +# declares operating modes; in this case the milter acts as a signer (s) and a verifier (v) +Mode sv + +# the path to the Pid file which contains the process identification number +PidFile /var/run/opendkim/opendkim.pid + +# selects the signing algorithm to use when creating signatures +SignatureAlgorithm rsa-sha256 + +# the milter will listen on the socket specified here, +# Postfix will send messages to opendkim for signing and verification through this socket; +# 12301@localhost defines a TCP socket that listens on localhost, port 12301 +Socket inet:12301@localhost' | sudo tee -a /etc/opendkim.conf +``` + +Make sure that port `12301` is free for OpenDKIM to use. + +Open `/etc/postfix/main.cf` and add the following lines if they are not already present: +``` text +# The mail filter protocol version and optional protocol extensions for communication with a Milter application +# 2 specifies that we want to use Sendmail 8 mail filter protocol version 2 +milter_protocol = 2 +# The default action when a Milter (mail filter) response is unavailable (for example, bad Postfix configuration or Milter failure). +# accept specifies that we should proceed as if the mail filter was not present. +milter_default_action = accept + +# A list of Milter (mail filter) applications for new mail that arrives via the Postfix smtpd server. +smtpd_milters = inet:localhost:12301 +# A list of Milter (mail filter) applications for new mail that does not arrive via the Postfix smtpd server. +non_smtpd_milters = inet:localhost:12301 +``` + +If `smtpd_milters` or `non_smtpd_milters` are already present and populated, add `, inet:localhost:12301` to the end of both of them. For example, if using [SpamAssassin](/docs/tutorials/email/spam) the current configuration will look like this: +``` text +smtpd_milters = unix:/spamass/spamass.sock +non_smtpd_milters = unix:/spamass/spamass.sock +``` +and must be changed to this +``` text +smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301 +non_smtpd_milters = unix:/spamass/spamass.sock, inet:localhost:12301 +``` + +## Setting trusted hosts + +Trusted hosts are hosts where mail originating from them does not require DKIM verification. They are defined in the `/etc/opendkim/TrustedHosts` file as per our configuration. We recommend limiting trusted hosts to local network hosts and public hosts with ``; this can be done using the following: +``` bash +# create dir to store TrustedHosts file. +sudo mkdir -p /etc/opendkim +sudo chown opendkim:opendkim /etc/opendkim + +# create and populate the TrustedHosts file +echo ' +127.0.0.1 +localhost +192.168.0.1/24 + +*.' | sudo tee /etc/opendkim/TrustedHosts + +# change ownership of newly created hosts file to opendkim +sudo chown opendkim:opendkim /etc/opendkim/TrustedHosts +``` + +## Creating the signing keys + +The [DKIM DNS record](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/) is a TXT record for `._domainkey.`, where `` is any alphanumeric string chosen during the setup of DKIM on the MTA. + +Key tables map a selector/domain pair to a private key; they consist of lines in the following format: +``` text +._domainkey. :: +``` + +In our case we will use `mail` as the `` and we will populate the key table (contained at `/etc/opendkim/KeyTable` as per our configuration) using: +``` bash +echo 'mail._domainkey. :mail:/etc/opendkim/keys//mail.private' | sudo tee /etc/opendkim/KeyTable + +# change ownership of key table file to opendkim +sudo chown opendkim:opendkim /etc/opendkim/KeyTable +``` + +OpenDKIM also requires a signing table with lines in the following format: +``` text +*@ ._domainkey. +``` + +This will identify the key to use when signing emails outgoing from the MTA with domain name ``. + +For our purposes we can populate the signing table (contained at `/etc/opendkim/SigningTable` as per our configuration) using: +``` bash +echo '*@ mail._domainkey.' | sudo tee /etc/opendkim/SigningTable + +# change ownership of signing table file to opendkim +sudo chown opendkim:opendkim /etc/opendkim/SigningTable +``` + +We can finally generate a private key for OpenDKIM to use when signing outgoing emails, this can be done using the following commands: +``` bash +sudo mkdir -p /etc/opendkim/keys/ +cd /etc/opendkim/keys/ + +# create the signing private key for OpenDKIM +# -s specifies the selector, in our case mail +# -d specifies the domain name to be used with emails. +# -b specifies the key size (in bytes), 2048 or greater does not work with Gmail in my experience. +sudo opendkim-genkey -s mail -d -b 1024 + +# change ownership of created key to opendkim +sudo chown -R opendkim:opendkim /etc/opendkim/keys/ +``` + +## Creating a DKIM DNS record + +As mentioned above, the [DKIM DNS record](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/) must contain the public key corresponding to the private key used by OpenDKIM to sign outgoing emails at the MTA. The public key and its information required for this DNS record can be accessed by running the following command: +``` bash +sudo cat /etc/opendkim/keys//mail.txt +``` + +To create the DKIM DNS record, create a TXT record for `._domainkey.` with content in the following format: +``` text +v=DKIM1; k=; p=; +``` +The `` is chosen during OpenDKIM configuration (see above), and the values to put for `k=` and `p=` can be obtained from the DKIM configuration as well (see above). + +In my case, for example, `` is `mail`, and the contents of the DKIM record are: +``` text +v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFMMPBxFVmYv+UqWG6YZUrpPq7P9NKovp6jw1m8rp/QQTFV5Ar8seCarbP7Rl7Q3UjIpO5JisKyfp9RjzkEZ8fnGpyZhOhzN9D4X5wf3ug37RbS4j8XF1zYx1m1POrtGHKiSa0BKBFSX15REs3RnkaiIRHNFmj+XIwTId5MyIOoQIDAQAB; +``` diff --git a/content/en/docs/tutorials/email/maa.md b/content/en/docs/tutorials/email/maa.md index 62e8d02..045a8b0 100644 --- a/content/en/docs/tutorials/email/maa.md +++ b/content/en/docs/tutorials/email/maa.md @@ -297,4 +297,12 @@ Port forwarding is managed via a table which can be edited through the router in Here are my port forwarding rules as an example of what a setup could look like: -![](/docs/tutorials/email/port-forwarding-rules.png) \ No newline at end of file +![](/docs/tutorials/email/port-forwarding-rules.png) + +## Debugging + +Logging for mail services (both MTA and MDA processes) is available at `/var/log/mail.log`. Use +``` bash +cat /var/log/mail.log | grep dovecot +``` +to filter for `dovecot` logging. \ No newline at end of file diff --git a/content/en/docs/tutorials/email/mta.md b/content/en/docs/tutorials/email/mta.md index 667c03b..d750bed 100644 --- a/content/en/docs/tutorials/email/mta.md +++ b/content/en/docs/tutorials/email/mta.md @@ -5,3 +5,161 @@ date: 2017-01-04 weight: 20 --- +An MTA server is responsible for actually sending and receiving emails. It does this via the Simple Mail Transfer Protocol (SMTP). User agent programs (such as Thunderbird) send mail by communicating with an MTA server via SMTP. Incoming email is received by the MTA server from other MTAs using SMTP, and then stored in the appropriate user mailbox where the MAA server can access it and make it available to MAA clients. + +For more information on the SMTP protocol, see [here](https://www.cloudflare.com/learning/email-security/what-is-smtp) or see [our reference material on email](/docs/reference/email). + +As an MTA, we will use [`postfix`](https://www.postfix.org). + +Milters (portmanteau for mail filters) are special programs which are used to filter received or sent emails. They can be used with the `postfix` and `sendmail` MTAs, and communicate with them over TCP. The MTA server informs and provides data about each stage of the email receipt/sending to milters, and milter programs can choose to terminate sending/receiving the email at any point. + +It is recommended to configure `postfix` with some milter programs (see [Setting up DKIM](/docs/tutorials/dkim) and [Spam filters](/docs/tutorials/email/spam)). + +## Installation + +``` bash +sudo apt-get update +sudo apt-get install -y postfix +``` + +When prompted with this screen: +``` text + ┌───────────────────────────┤ Postfix Configuration ├───────────────────────────┐ + │ Please select the mail server configuration type that best meets your needs. │ + │ │ + │ No configuration: │ + │ Should be chosen to leave the current configuration unchanged. │ + │ Internet site: │ + │ Mail is sent and received directly using SMTP. │ + │ Internet with smarthost: │ + │ Mail is received directly using SMTP or by running a utility such │ + │ as fetchmail. Outgoing mail is sent using a smarthost. │ + │ Satellite system: │ + │ All mail is sent to another machine, called a 'smarthost', for │ + │ delivery. │ + │ Local only: │ + │ The only delivered mail is the mail for local users. There is no │ + │ network. │ + │ │ + │ General mail configuration type: │ + │ │ + │ No configuration │ + │ Internet Site │ + │ Internet with smarthost │ + │ Satellite system │ + │ Local only │ + │ │ + │ │ + │ │ + │ │ + └───────────────────────────────────────────────────────────────────────────────┘ +``` +choose `Internet Site` as the configuration that should be installed. + +Then enter the domain name you want to use in your email addresses in the following screen: +``` text + ┌────────────────────────────┤ Postfix Configuration ├────────────────────────────┐ + │ The 'mail name' is the domain name used to 'qualify' _ALL_ mail addresses │ + │ without a domain name. This includes mail to and from : please do not │ + │ make your machine send out mail from root@example.org unless root@example.org │ + │ has told you to. │ + │ │ + │ This name will also be used by other programs. It should be the single, fully │ + │ qualified domain name (FQDN). │ + │ │ + │ Thus, if a mail address on the local host is foo@example.org, the correct │ + │ value for this option would be example.org. │ + │ │ + │ System mail name: │ + │ │ + │ _______________________________________________________________________________ │ + │ │ + │ │ + │ │ + └─────────────────────────────────────────────────────────────────────────────────┘ +``` + +To check that it is running correctly, use: +``` bash +sudo service postfix status +``` + +## Reloading configuration + +`postfix` is configured mainly through a single config file at `/etc/postfix/main.cf`. After configuration changes, `postfix` needs to be reloaded with: +``` bash +sudo service postfix reload +``` +in order for the changes to take effect. + +## Basic Configuration + +Ensure that `/etc/postfix/main.cf` contains the following: +``` text +# public DNS name of this MTA server +myhostname = mail. + +# The list of domains that are delivered via the $local_transport mail delivery transport. +# In other words this is the list of domains for which postfix will send/receive mail +mydestination = mail., , localhost, localhost.localdomain + +# The next-hop destination(s) for non-local mail +# In this case we do not want to use postfix as a relay, so we leave it empty +relayhost = + +# The list of "trusted" remote SMTP clients that have more privileges than "strangers". +# In particular, "trusted" SMTP clients are allowed to relay mail through Postfix. +# We limit these to local clients only. +# NOTE that I don't think this value matters for our setup. +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 + +# The maximal size of any local individual mailbox or maildir file, or zero (no limit). +mailbox_size_limit = 0 + +# The set of characters that can separate an email address localpart, user name, or a +# .forward file name from its extension. +# +# For example, with "recipient_delimiter = +", the software tries user+foo@example.com +# before trying user@example.com, user+foo before trying user, and .forward+foo before +# trying .forward. +recipient_delimiter = + + +# The local network interface addresses that this mail system receives mail on. +# Specify "all" to receive mail on all network interfaces (default) +inet_interfaces = all + +# specify that received mail should be stored using Maildir format, this matches our dovecot installation. +# Each mail user will have a mailbox at ~/Maildir. +home_mailbox = Maildir/ +``` + +### Receiving mail + +We need to specify recipients (the part before `@` in an email address) to `postfix` so that it knows how to route incoming mail to the right mail user's mailbox. Up until now we have treated mail users and recipients as interchangeable, but `postfix` allows for multiple recipients to map to the same mail user. This means that emails sent to `postmaster@markmizzi.dev` and `root@markmizzi.dev`, for e.g. may both be routed into the `root` user's mailbox. + +To specify recipients, we use the following configuration parameter: +``` text +local_recipient_maps = proxy:unix:passwd.byname $alias_maps +``` +- `proxy:unix:passwd.byname` ensures that each system user in `/etc/passwd` is also a recipient; this is important as our [`dovecot` setup](/docs/tutorial/email/maa) assumes that each system user is also a mail user. This option hence ensures that mail can be sent to each mail user defined in `dovecot`'s user database, using their username as the recipient. + +- `$alias_maps` are optional lookup tables that are searched in order to determine the mail user corresponding to a particular recipient. + +Because of the order in which we specified the options, the `/etc/passwd` file will be searched first. + +One file in `$alias_maps` by default is `/etc/aliases`, which we can modify to map recipients to mail users. These are some common mappings added: +``` text +mailer-daemon: postmaster +postmaster: root +nobody: root +hostmaster: root +usenet: root +news: root +webmaster: root +www: root +ftp: root +abuse: root +``` + +With this setup emails sent to `postmaster@`, `www@`, `abuse@`, and so on will all be routed to `root`'s mailbox. + diff --git a/content/en/docs/tutorials/email/spam.md b/content/en/docs/tutorials/email/spam.md new file mode 100644 index 0000000..08b6f41 --- /dev/null +++ b/content/en/docs/tutorials/email/spam.md @@ -0,0 +1,6 @@ +--- +title: Setting up a spam filter +description: Tutorial for setting up a spam filter on Postfix using SpamAssassin +date: 2017-01-04 +weight: 50 +--- \ No newline at end of file