diff options
Diffstat (limited to 'content/mail')
| -rw-r--r-- | content/mail/inbox.md | 214 | ||||
| -rw-r--r-- | content/mail/rdns.md | 36 | ||||
| -rw-r--r-- | content/mail/security.md | 72 | ||||
| -rw-r--r-- | content/mail/smtp.md | 74 | ||||
| -rw-r--r-- | content/mail/validate.md | 230 |
5 files changed, 626 insertions, 0 deletions
diff --git a/content/mail/inbox.md b/content/mail/inbox.md new file mode 100644 index 0000000..3f70b9c --- /dev/null +++ b/content/mail/inbox.md @@ -0,0 +1,214 @@ +--- +title: "Setting up an E-mail Inbox" +tags: ['mail'] +date: 2022-12-04 +--- +In the article on [SMTP and Postfix](/mail/smtp), we set up a simple +Postfix server that we could use to programatically send mail with the +`mail` command. In order to have a true and fully-functional mail +server, users should be able to login to a mail client where they +can read their inbox and send mail remotely. In order to achieve this we need Dovecot, +which can store mails received by the server, +authenticate user accounts and interact with mail. + +If we're setting up an inbox we will also want spam detection software, such +as spam assassin. + +## Dovecot and Spamassassin + + apt install dovecot-imapd dovecot-sieve spamassassin spamc + +Unblock the imap port: + + ufw allow 993 + +## Certificate + +We will want a SSL certificate for the `mail.` subdomain. We can get +this with [Certbot](/basic/certbot/). Assuming we are using Nginx for our +server otherwise, run: + + certbot --nginx certonly -d mail.example.org + +## DNS + +We also need two little DNS records set on your domain registrar's site/DNS server: + +1. An MX record. Just put your domain, **example.org**, in the "Points to" field. +2. A CNAME record. Host field: **mail.example.org**. "Points to" field: **example.org.** + +## Configuring Dovecot + +Dovecot\'s configuration file is in `/etc/dovecot/dovecot.conf`. If you +open that file, you will see this line: `!include conf.d/*.conf` which adds +all the `.conf` files in `/etc/dovecot/conf.d/` to the Dovecot +configuration. + +One can edit each of these files individually to get the needed +configuration, but to make things easy here, delete or backup the main +configuration file and we will replace it with one single config file +with all important settings in it. Make sure you change `ssl_cert` +and `ssl_key` accordingly. + +``` wide +# Note that in the dovecot conf, you can use: +# %u for username +# %n for the name in name@domain.tld +# %d for the domain +# %h the user's home directory + +# Connections between the mail client and Dovecot needs to be encrypted +ssl = required +ssl_cert = </etc/letsencrypt/live/mail.example.org/fullchain.pem +ssl_key = </etc/letsencrypt/live/mail.example.org/privkey.pem +ssl_min_protocol = TLSv1.2 +ssl_cipher_list = EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED +ssl_prefer_server_ciphers = yes +ssl_dh = </usr/share/dovecot/dh.pem +auth_mechanisms = plain login +auth_username_format = %n + +protocols = $protocols imap + +# Search for valid users in /etc/passwd +userdb { + driver = passwd +} +#Fallback: Use plain old PAM to find user passwords +passdb { + driver = pam +} + +# Our mail for each user will be in ~/Mail, and the inbox will be ~/Mail/Inbox +mail_location = maildir:~/Mail:INBOX=~/Mail/Inbox:LAYOUT=fs +namespace inbox { + inbox = yes + mailbox Drafts { + special_use = \Drafts + auto = subscribe +} + mailbox Junk { + special_use = \Junk + auto = subscribe + autoexpunge = 30d +} + mailbox Sent { + special_use = \Sent + auto = subscribe +} + mailbox Trash { + special_use = \Trash +} + mailbox Archive { + special_use = \Archive +} +} + +# Here we let Postfix use Dovecot's authetication system. +service auth { + unix_listener /var/spool/postfix/private/auth { + mode = 0660 + user = postfix + group = postfix +} +} + +protocol lda { + mail_plugins = $mail_plugins sieve +} +protocol lmtp { + mail_plugins = $mail_plugins sieve +} +plugin { + sieve = ~/.dovecot.sieve + sieve_default = /var/lib/dovecot/sieve/default.sieve + sieve_dir = ~/.sieve + sieve_global_dir = /var/lib/dovecot/sieve/ +} +``` + +### Settings Explained + +Take a good look at the above settings to understand what\'s going on. Some of +the settings include: + +1. SSL settings to allow encrypted connections. +2. The mail server will authenticate users against PAM/passwd, which + means users you create on the server (so long as they are part of + the `mail` group) will be able to receive and send mail. +3. Default directories for a mail account: Inbox, Sent, Drafts, Junk, + Trash and Archive. +4. Create a `unix_listener` that will allow Postfix to authenticate + users via Dovecot. +5. Setup the Dovecot sieve plugin, which provides mail filtering facilities + at time of final message delivery. Sieve scripts can be used to + customize how messages are delivered, whether they're forwarded + or stored in special folders. + +Next, we can tell sieve to automatically move mail flagged as spam to +the junk folder: + + echo "require [\"fileinto\", \"mailbox\"]; + if header :contains \"X-Spam-Flag\" \"YES\" + { + fileinto \"Junk\"; + }" > /var/lib/dovecot/sieve/default.sieve + +After that, we should create the `vmail` user and group, which will +access the mails, and then update the sieve configuration: + + grep -q '^vmail:' /etc/passwd || useradd vmail + chown -R vmail:vmail /var/lib/dovecot + sievec /var/lib/dovecot/sieve/default.sieve + +Then, enable pam authentication for Dovecot: + + echo "auth required pam_unix.so nullok + account required pam_unix.so" >> /etc/pam.d/dovecot + +## Connecting Postfix and Dovecot + +We need to tell Postfix to look to Dovecot for authenticating users/passwords. +Dovecot will be putting an authentication socket in `/var/spool/postfix/private/auth`. + + postconf -e 'smtpd_sasl_auth_enable = yes' + postconf -e 'smtpd_sasl_type = dovecot' + postconf -e 'smtpd_sasl_path = private/auth' + postconf -e 'mailbox_command = /usr/lib/dovecot/deliver' + +## Connecting Postfix and Spamassassin + +We will change `/etc/postifx/master.cf` so postfix can route mail through spamassassin. First +we can cleanup the default configuration. Feel free to make a backup. + + sed -i '/^\s*-o/d;/^\s*submission/d;/^\s*smtp/d' /etc/postfix/master.cf + +Finally, run this command to finish the configuration for spamassassin. + + echo "smtp unix - - n - - smtp + smtp inet n - y - - smtpd + -o content_filter=spamassassin + 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 + smtps inet n - y - - smtpd + -o syslog_name=postfix/smtps + -o smtpd_tls_wrappermode=yes + -o smtpd_sasl_auth_enable=yes + spamassassin unix - n n - - pipe + user=debian-spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f \${sender} \${recipient}" >> /etc/postfix/master.cf + +## Make new mail accounts + +This is the easy part. Let's say we want to add a user Billy and let him +receive mail, run this: + + useradd -m -G mail billy + passwd billy + +Any user added to the `mail` group will be able to receive mail. Suppose a user +Cassie already exists and we want to let her receive mail too. Just run: + + usermod -a -G mail cassie diff --git a/content/mail/rdns.md b/content/mail/rdns.md new file mode 100644 index 0000000..85cce0f --- /dev/null +++ b/content/mail/rdns.md @@ -0,0 +1,36 @@ +--- +title: "Setup rDNS" +tags: ['mail'] +date: 2022-12-02 +--- + +While [DNS records](/basic/dns) refer a domain name to the IP address +where the the website is hosted, there is also rDNS (reverse DNS) and +specifically PTR (pointer) records which do the reverse: link a +server\'s IP to a domain name. + +This is important for many things, but especially email. Many email +servers require that other servers that send them mail have PTR records +to prevent spam. + +## Setting your PTR Record + +DNS settings are set with your registrar, while rDNS settings are set +with your server or VPS provider. **Remember to set records for both +IPv4 and IPv6!** + +In [Vultr](https://www.vultr.com/?ref=8384069-6G) we want to set the +IPv4 record, click on the server, then \"Settings,\" and make sure the +\"IPv4\" tab is selected. We can then edit the \"Reverse DNS\" blank +shown below. + +{{< img alt="IPv4 rDNS PTR record set in Vultr" src="/pix/rdns-01.png" >}} + +The setting for IPv6 is obviosuly under the IPv6 tab. Note here that we +copy the full IPv6 address from above and create a new rDNS entry by +pasting that and the domain name in the blanks below. Then just select +\"Add.\" + +{{< img alt="IPv6 rDNS PTR record set in Vultr" src="/pix/rdns-02.png" >}} + +That\'s it! diff --git a/content/mail/security.md b/content/mail/security.md new file mode 100644 index 0000000..4527b34 --- /dev/null +++ b/content/mail/security.md @@ -0,0 +1,72 @@ +--- +title: "Harden your E-mail Server" +tags: ["mail"] +date: 2022-12-05 +--- + +## Hardening Postfix + +Put restrictions on servers sending mail to you. + + postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unknown_recipient_domain' + +## Anonymize Headers + +Use some regular expressions to prevent some meta data like a client's ip address +from being leaked. + + echo "/^Received:.*/ IGNORE + /^X-Originating-IP:/ IGNORE + /^User-Agent:/ IGNORE + /^X-Mailer:/ IGNORE" >> /etc/postfix/header_checks + +Add this file to the postfix configuration: + + postconf -e "header_checks = regexp:/etc/postfix/header_checks" + +## Fail2Ban + +If you're not familiar with fail2Ban, it's essentially a program which +blocks bot's and hacker's login requests after a few invalid attempts. + + apt-get install fail2ban + +Make a local copy of the configuration file: + + cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local + +Go down to the `# Mail servers` line and paste this: + + [postfix] + + enabled = true + port = smtp,ssmtp,submission + filter = postfix + logpath = %(postfix_log)s + backend = systemd + + + [sasl] + + enabled = true + port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s + filter = postfix[mode=auth] + # You might consider monitoring /var/log/mail.warn instead if you are + # running postfix since it would provide the same log lines at the + # "warn" level but overall at the smaller filesize. + logpath = %(postfix_log)sAdd commentMore actions + backend = systemd + maxretry = 1 + bantime = 21600 + + [dovecot] + + enabled = true + port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s + filter = dovecot + logpath = %(dovecot_log)sAdd commentMore actions + backend = systemd + +This will only grant 2 login attempts and then block the requester for 6 hours. Now restart `fail2ban`: + + systemctl restart fail2ban diff --git a/content/mail/smtp.md b/content/mail/smtp.md new file mode 100644 index 0000000..d5c1f48 --- /dev/null +++ b/content/mail/smtp.md @@ -0,0 +1,74 @@ +--- +title: "Sending and Receiving Email" +tags: ["mail"] +date: 2022-12-01 +--- + +The first step to setting up an email server is having an SMTP server. +SMTP sends and receives email. Whether we want a full email server or +just the ability to send automated email by script, we will need SMTP, +and Postfix is the standard SMTP server. + +Here let\'s set a server up. Note that our goal is to be able to send +emails from our server. If you want a full email server, this is the +first step, and we will address the rest later. + +## Before beginning! + +Whatever VPS ([Vultr](https://www.vultr.com/?ref=8384069-6G) or +[Frantech](https://my.frantech.ca/aff.php?aff=3886)) or IPS you are +using, it is a very common policy to **automatically block all email +ports by default**. VPS providers do this to prevent spammers from using +their services. + +If you want to start an email server, therefore, go to your VPS\'s site +and open a ticket or make a request to open up email ports, notably port `25`. This is a +simple process that requires nothing too special. One of the wagies at +your VPS will kindly do the needful and open your ports for you. Note +that this is not the same as unblocking a port with [ufw](/../ufw), +which still needs to be done for SMTP to work. + + ufw allow 25,587 proto tcp + +## Installation + +First, we install Postfix and also `mailutils`, which comes with some +mail programs we will use. + + apt install -y mailutils postfix + +Installing Postfix for the first time will give us some graphical +options. + +{{< img alt="SMTP Postfix internet site choice" src="/pix/smtp-01.png" link="/pix/smtp-01.png" >}} + +When asked for a \"mail name\", give your full domain name from which +you would like mail to come and go, e.g. **example.org** or +**chad.thesiah.xyz** + +{{< img alt="SMTP Postfix fully qualified domain name" src="/pix/smtp-02.png" link="/pix/smtp-02.png" >}} + +## Test the email + +That is actually all you need to have set up to have a barebones, +send-only email server. We can test our server by running a `mail` +command like that below. + + echo "Hi there. + + This is the text." | mail -s "Email from the server" your@emailaddress.com + +This type of command is sufficient enough for your server to send mail. +Note that we use the `-s` option to specify the email\'s subject while +we pipe the email content into the `mail` command via standard input. In +this example I use a quoted multiline email as an example. + +## Do you see your message? + +If you sent the above test message to an account on Gmail or another +major email provider, there is **very high** chance of the message you +sent above being marked as spam or not appearing at all! + +Don\'t worry, we\'ll take care of that in the next two articles where we +set up rDNS with your VPS provider and various other DNS +records to validate the emails you send. diff --git a/content/mail/validate.md b/content/mail/validate.md new file mode 100644 index 0000000..8447409 --- /dev/null +++ b/content/mail/validate.md @@ -0,0 +1,230 @@ +--- +title: "Validate Email with DNS Records" +tags: ['mail'] +date: 2022-12-03 +--- +Email is a lot like real-life mail. You can send email to anyone, but +you can also write whatever return address you\'d like. That is, it\'s +pretty easy to pretend to be someone else via mail, and that was +originally the case with email as well: email is just text, and you +could just change your `From:` address to any email address you wanted! +DKIM (Domain Keys Identified Mail) helps solve this issue. + +OpenDKIM will generate a public/private cryptographic key pair for your +server. The public key will be made available publicly in your server\'s +DNS records and the private key will be used to sign every single email +that leaves the server. This means that people receiving mail from your +server can now be absolutely sure that it originated from your server +because their servers can check the cryptographic signature on the email +with the public key! + +OpenDKIM ensures that email originated from the server it claims it did, +but it does not ensure that it originated from the user account it +claims it did. This easier problem is solved by server-side +authorization settings. + +## Installation + +```sh +apt install opendkim opendkim-tools +``` + +## The Keys and Files + +We have to generate the DKIM keys and create some secondary files that +will be required for our configuration. + +### Generate the DKIM key + +<!-- +TODO: Make a unique directory for each domain to later allow multiple domain +DKIM validation for servers serving more than one domain name. +--> + +Here we create directories for the OpenDKIM keys, generate them, and +ensure they have the right file permissions. + +```sh +mkdir -p /etc/postfix/dkim +opendkim-genkey -D /etc/postfix/dkim/ -d example.org -s mail +chgrp opendkim /etc/postfix/dkim/* +chmod g+r /etc/postfix/dkim/* +``` + +### Create the key table + +Now we\'ll tell OpenDKIM where the newly generated keys are on the file +system. + +```sh +echo "mail._domainkey.example.org example.org:mail:/etc/postfix/dkim/mail.private" > /etc/postfix/dkim/keytable +``` + +### Create the signing table + +```sh +echo "*@example.org mail._domainkey.example.org" > /etc/postfix/dkim/signingtable +``` + +### Adding trusted hosts + +```sh +echo "127.0.0.1 +10.1.0.0/16 +1.2.3.4/24" > /etc/postfix/dkim/trustedhosts +``` + +## Configuring opendkim.conf + +Now we have all the raw material, so open up `/etc/opendkim.conf` and we +can finalize our server settings. First, add these lines that will +source the files we just created. + +```yaml +KeyTable file:/etc/postfix/dkim/keytable +SigningTable refile:/etc/postfix/dkim/signingtable +InternalHosts refile:/etc/postfix/dkim/trustedhosts + +Canonicalization relaxed/simple +Socket inet:12301@localhost +``` + +There will already be an uncommented `Socket` directive, so delete, +comment out or replace it with the above. + +## Interfacing with Postfix + +There are a couple things we must add to the Postfix SMTP server +settings to interface it with OpenDKIM. Specifically, we have to set our +OpenDKIM server, which will be running on port `12301`, as a milter +(mail filter). This is easy to do with the four commands below: + +```sh +postconf -e "myhostname = $(cat /etc/mailname)" +postconf -e "milter_default_action = accept" +postconf -e "milter_protocol = 6" +postconf -e "smtpd_milters = inet:localhost:12301" +postconf -e "non_smtpd_milters = inet:localhost:12301" +``` + +## Restart and reload Postfix and DKIM + +Now that we have all our settings in place: + +```sh +systemctl restart opendkim +systemctl enable opendkim +systemctl reload postfix +``` + +## Adding the DNS record! + +We are only one step away from having functioning OpenDKIM. We must add the +DKIM public key to our server\'s DNS settings, so go ahead and open up your +registrar\'s site or wherever your site\'s DNS settings are. + +The public key is found in the file `/etc/postfix/dkim/mail.txt`, but it +will display as multiple lines and multiple quoted strings, which is +annoying and hard to copy-and-paste into your registrar. To make things +easier, run the following command to format the key in the way we need +it for the DNS TXT entry: + +```sh +echo -e " + +v=DKIM1; k=rsa; $(tr -d " +" </etc/postfix/dkim/mail.txt | sed "s/k=rsa.* \"p=/k=rsa; p=/;s/\"\s*\"//;s/\"\s*).*//" | grep -o "p=.*") + +" +``` + +Take the very long output of that command, which will start with +`v=DKIM1` and add it as a TXT entry in your DNS settings as below. The +host we put it for is `mail._domainkey`. + +{{< img alt="Adding the OpenDKIM TXT entry in DNS settings" src="/pix/dkim-01.png" link="/pix/dkim-01.png" >}} + +On my registrar, this is how it is input, but on some registrars, it may be +required to include your domain name as well as `mail._domainkey.example.org`. + +If you have your own DNS server, add a TXT entry as follows: + +```txt +mail._domainkey.example.org TXT v=DKIM1; k=rsa; p=ThatLongRandomSequenceOfLettersAndNumbersOfYours +``` + +## Testing it out! + +Now we want to send an email to make sure that your emails will now be +signed with OpenDKIM. + +### Hostname + +If you\'ve followed these instructions, all emails from the domain +**example.org** will now have a DKIM signature on them. If we send mail +via the `mail` command, however, their domain of origin will be whatever +your server\'s hostname is, which you may have set to something +different than your domain. + +You can permanently change your hostname by changing it in +`/etc/hostname` and rebooting, or you can just run +`hostname example.org` to change it temporarily for testing. Either way, +this will allow us to run the `mail` command as in [the SMTP +article](../smtp). + +```sh +echo "Hi there. + +This is the text." | mail -s "Email from the server" your@emailaddress.com +``` + +### More helpful troubleshooting. + +You can also go to [this site](https://appmaildev.com/en/dkim), which +will help you troubleshoot any other DKIM problems if you mistyped +something. + +## DMARC + +DMARC (Domain-based Message Authentication Protocol) is a protocol designed +to give email domain owners the ability to protect their domain from +unauthorized use. + +Add the dmarc user: + + useradd -m -G mail dmarc + +Open up your registrar or DNS settings again, and make a new TXT record like +we did with DKIM, except now use the output from the following command: + + echo "_dmarc.$(cat /etc/mailname)" + echo "v=DMARC1; p=reject; rua=mailto:dmarc@$(cat /etc/mailname); fo=1" + +The first line is the Host field. The latter is the TXT value. + +### Sender Policy Framework + +Saving the easiest for last, we should add a TXT record for SPF, +an email-authentication standard used to prevent spammers from sending messages +that appear to come from a spoofed domain. + + cat /etc/mailname + IP4=<your VPS's IPv4 address> + IP6=<your VPS's IPv6 address> + echo "v=spf1 mx a:mail.$(cat /etc/mailname) ip4:$IP4 ip6:$IP6 -all" + +**Note**: previous versions of this guide didn't ask you to specify the `ip4` +and `ip6` mechanisms. If you don't include them, some email hosts (most +notoriously gmail) will not accept mail from your server. + +The `IP4` and `IP6` values should be the same as what you set your [PTR +records](../rdns) to. + +The output of `cat /etc/mailname` is the Host field. The output of the second command is the TXT value. + +Again, you can check [that site](https://appmaildev.com/en/spf) +to make sure your DKIM, DMARC, and SPF entries are valid. That's it! + +## Contribution + +- SPF mechanisms updated by Martin Chrzanowski \-- [website](https://m-chrzan.xyz), [donate](https://m-chrzan.xyz/donate.html) |
