Merge branch 'master' into terminal

This commit is contained in:
revsuine 2024-11-20 03:00:47 +00:00
commit 792a1d3f56
Signed by: revsuine
GPG key ID: 3F257B68F5BC9339

View file

@ -39,8 +39,8 @@ server you yourself are using.[^server_trust]
Running your own mail server also allows you to implement things your way, with the features you want. For instance, Running your own mail server also allows you to implement things your way, with the features you want. For instance,
[you can run a sieve filter for encrypting all incoming mail with a user's public GPG [you can run a sieve filter for encrypting all incoming mail with a user's public GPG
key](https://www.grepular.com/Automatically_Encrypting_all_Incoming_Email); for obvious reasons, users of externally key](https://www.grepular.com/Automatically_Encrypting_all_Incoming_Email); for obvious reasons, public (as in, open to
managed mail servers that implement sieve do not allow users to create their own executables for sieve filters. public sign-up) mail servers that implement sieve do not allow users to create their own executables for sieve filters.
Hosting your own mail server is not something I would universally recommend to people. While I'm very much against Hosting your own mail server is not something I would universally recommend to people. While I'm very much against
"nothing to hide, nothing to fear", a combination of that factor alongside a low state threat model (i.e. there is "nothing to hide, nothing to fear", a combination of that factor alongside a low state threat model (i.e. there is
@ -108,7 +108,7 @@ in through a standard SMTP/IMAP/POP3 email client, read their emails, and send e
modular, i.e. you can opt to have e.g. Pigeonhole but not Amavis. modular, i.e. you can opt to have e.g. Pigeonhole but not Amavis.
We will end up with a small-scale mail server running on Alpine Linux with one domain, and we will use Unix user We will end up with a small-scale mail server running on Alpine Linux with one domain, and we will use Unix user
accounts as mail accounts. accounts as mail accounts. We will only set up IMAP, not POP3.
This tutorial was written for Alpine Linux 3.20.3, though will most likely work on other versions too. This tutorial was written for Alpine Linux 3.20.3, though will most likely work on other versions too.
@ -141,7 +141,7 @@ choice.
An MX record denotes that your domain is used to send and receive email, and tells other MTAs the domain name of your An MX record denotes that your domain is used to send and receive email, and tells other MTAs the domain name of your
mail server. We will use `mail.domain.com` for your MX record. For instance, my MX record looks like: mail server. We will use `mail.domain.com` for your MX record. For instance, my MX record looks like:
```bindzone ```dns
revsuine.xyz. 14400 IN MX 0 mail.revsuine.xyz revsuine.xyz. 14400 IN MX 0 mail.revsuine.xyz
``` ```
@ -153,19 +153,19 @@ same as the IP address of `domain.com`, or an A record if the IP address is not
I use a CNAME record because the IP addresses of `mail.revsuine.xyz` and `revsuine.xyz` are the same, so my record is: I use a CNAME record because the IP addresses of `mail.revsuine.xyz` and `revsuine.xyz` are the same, so my record is:
```bindzone ```dns
mail.revsuine.xyz. 14400 IN CNAME revsuine.xyz mail.revsuine.xyz. 14400 IN CNAME revsuine.xyz
``` ```
If you use an A record, your record may look something like If you use an A record, your record may look something like
```bindzone ```dns
mail.domain.com. 14400 IN A ip.address.here mail.domain.com. 14400 IN A ip.address.here
``` ```
If you use IPv6, you should also add an AAAA record, e.g.: If you use IPv6, you should also add an AAAA record, e.g.:
```bindzone ```dns
mail.domain.com. 14400 IN AAAA ip:address:here:: mail.domain.com. 14400 IN AAAA ip:address:here::
``` ```
@ -205,6 +205,57 @@ following TCP ports are open on your firewall:
| 587 | Email message submission | | 587 | Email message submission |
| 993 | IMAPS (IMAP over TLS) | | 993 | IMAPS (IMAP over TLS) |
## Obtain a TLS certificate
To enable TLS encryption, you need a certificate. [Let's Encrypt](https://letsencrypt.org/) provides free TLS
certificates. To get a certificate from them, you can use certbot:
# apk add certbot
We will need a web server to use certbot. I'm going to use nginx for this guide, because nginx is what I use on my
server, but [the certbot website](https://certbot.eff.org/) has instructions for a variety of setups. If you don't
already have an nginx server, install nginx and set it up now.
Install `certbot-nginx` with:
# apk add certbot-nginx
Add the following to your nginx config (for instance, inside `http {}` in `/etc/nginx/nginx.conf`, or in a dedicated
virtual host file `/etc/nginx/http.d/mail.domain.com.conf`):
```nginx
server {
listen 80;
listen [::]:80;
server_name mail.domain.com;
root /usr/share/nginx/html/;
location ~ /.well-known/acme-challenge {
allow all;
}
}
```
Replace `mail.domain.com` with the <abbr title="Fully-Qualified Domain Name">FQDN</abbr> of your mail server.
The `root` can be set to any extant directory on your system that you're happy to publish to the web. You can just make
an empty directory at `/usr/share/nginx/html`, or make this the directory of your website, etc.
Reload or restart nginx for the changes to take effect:
# rc-service nginx reload
Now run the following command to get your free TLS certificate:
# certbot certonly -a nginx --staple-ocsp --email your@email.here -d mail.domain.com
If you have several subdomains in your nginx config that you'd like covered by the same certificate, you can omit `-d
mail.domain.com` and get a certificate covering all the domains in your nginx config. On my server, I have one
certificate at `/etc/letsencrypt/live/revsuine.xyz/` covering my apex domain and all subdomains. If you go for a
certificate with only one domain name, e.g. for `mail.domain.com`, it will be at
`/etc/letsencrypt/live/mail.domain.com/`.
# Postfix # Postfix
Postfix is a [mail transport agent](https://en.wikipedia.org/wiki/Message_transfer_agent) (aka SMTP server). [In its Postfix is a [mail transport agent](https://en.wikipedia.org/wiki/Message_transfer_agent) (aka SMTP server). [In its
@ -257,6 +308,76 @@ one at `/etc/logrotate.d/postfix`:
} }
``` ```
Add the following TLS settings, replacing `your.domain.com` with your mail server's FQDN, [or otherwise where the TLS
certificate we generated would be](#obtain-a-tls-certificate):
```conf
# Enable TLS encryption when Postfix receives incoming emails
smtpd_tls_cert_file = /etc/letsencrypt/live/your.domain.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/your.domain.com/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = lmdb:${data_directory}/smtpd_scache
# Enable TLS encryption when Postfix sends outgoing emails
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = lmdb:${data_directory}/smtp_scache
# Enforce TLSv1.3 or TLSv1.2
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
# only offer authentication after STARTTLS
smtpd_tls_auth_only = yes
# disable SSL compression
tls_ssl_options = NO_COMPRESSION
# Configure the allowed cipher list
smtpd_tls_mandatory_ciphers = high
smtp_tls_mandatory_ciphers = high
smtpd_tls_ciphers = high
smtpd_tls_mandatory_ciphers = high
tls_high_cipherlist = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
tls_preempt_cipherlist = yes
```
The allowed cipher list is from [Mailcow](https://docs.mailcow.email/manual-guides/Postfix/u_e-postfix-harden_ciphers/).
If you're using this as a personal mail server, you may not want to have a mailbox size limit, so you can set:
```conf
mailbox_size_limit = 0
```
By default, `mailbox_size_limit` is `51200000`. This number is in bytes. You can similarly set a `message_size_limit`.
Finally, here are some various hardening settings you can add to your `/etc/postfix/main.conf`:
```conf
# connections rate limit: no of connections allowed per unit
# `postconf anvil_rate_time_unit` will give the time unit; by default it's
# 60 seconds, so 600/60=10 connections allowed per second
smtpd_client_connection_rate_limit = 600
# messages rate limit, again over same time limit
smtpd_client_message_rate_limit = 60
# VRFY command used to check if an email address exists
# not needed and can be used to find spam recipients
disable_vrfy_command = yes
# servers that don't use HELO or EHLO are either not properly configured
# or sending spam usually
smtpd_helo_required = yes
smtpd_delay_reject = yes
smtpd_helo_restrictions =
permit_mynetworks,
reject_invalid_helo_hostname,
reject_unknown_helo_hostname,
permit
```
## Send your first email ## Send your first email
Have the `postfix` service auto-start upon boot, and start it during this session: Have the `postfix` service auto-start upon boot, and start it during this session:
@ -268,7 +389,7 @@ You can now send an email with the following command:
$ echo "test email" | sendmail user@externaldomain.com $ echo "test email" | sendmail user@externaldomain.com
Send this email to your email account with an external server, e.g. a gmail account. Note that Protonmail has quite Send this email to your email account with an external server, e.g. a Gmail account. Note that Protonmail has quite
stringent spam filters and this likely would be rejected by Protonmail, i.e. not even reach your spam folder. stringent spam filters and this likely would be rejected by Protonmail, i.e. not even reach your spam folder.
## Configure email aliases ## Configure email aliases
@ -293,9 +414,119 @@ so ultimately `revsuine` will get `postmaster`'s mail.
You can continue to populate the aliases file with whatever aliases you want. You can continue to populate the aliases file with whatever aliases you want.
## Enable Postfix submission and smtps service
To send emails from email clients, you'll need to enable Postfix's submission service so that Postfix can receive
emails to send via SMTP. Edit `/etc/postfix/master.cf` and ensure that the following lines are present:
```conf
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o smtp_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
```
They may be commented out, or partially present without some options.
Restart Postfix.
# rc-service postfix restart
# Dovecot # Dovecot
[Dovecot](https://www.dovecot.org/) is a popular IMAP and POP3 server which we'll be using for our MDA. [Dovecot](https://www.dovecot.org/) is a popular IMAP and POP3 server which we'll be using for our MDA. Let's install
it:
# apk add dovecot
Check the Dovecot version with:
$ dovecot --version
Now let's enable IMAP by editing `/etc/dovecot/dovecot.conf`. Find a `protocols = ` line, or add one, and set it to:
```conf
protocols = imap
```
## Configure how to store emails
You probably want to use the Maildir format for storing emails, where each user's mail is stored at `~/Maildir` (this
can be set to another location if desired).
In `/etc/dovecot/conf.d/10-mail.conf`, set:
```conf
mail_location = maildir:~/Maildir
mail_privileged_group = mail
```
`mail_privileged_group` tells us which group of Unix users can send mail; in this case, it's anyone in the `mail`
group. You can create the group with:
# addgroup mail
# adduser postfix mail
# adduser dovecot mail
We want to ensure that `postfix` and `dovecot` users have the right to access mail.
To change the Maildir directory, e.g. to set it to `~/mail`, you would set the following:
`/etc/dovecot/conf.d/10-mail.conf`:
```conf
mail_location = maildir:~/mail
```
`/etc/postfix/main.cf`:
```conf
home_mailbox = mail/
```
## Get emails with LMTP
<abbr title="Local Mail Transfer Protocol">LMTP</abbr> is a protocol which can be used for Postfix to pass incoming
emails to Dovecot. To install it for Dovecot:
# apk add dovecot-lmtpd
Add `lmtp` to the supported protocols in `/etc/dovecot/dovecot.conf`:
```conf
protocols = imap lmtp
```
Now change the LMTP service (or add if it isn't already there) in `/etc/dovecot/conf.d/10-master.conf` to:
```conf
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
```
Postfix needs to be configured to use this socket. Edit `/etc/postfix/main.cf` with the following lines:
```conf
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtputf8_enable = no
```
<!-- FOOTNOTES: --> <!-- FOOTNOTES: -->
@ -312,7 +543,7 @@ You can continue to populate the aliases file with whatever aliases you want.
For a dedicated server you rent, there are at least no concerns about a compromised host, but an attacker with For a dedicated server you rent, there are at least no concerns about a compromised host, but an attacker with
physical access (in this case, the untrusted people you rent the dedicated server from) can attempt evil maid physical access (in this case, the untrusted people you rent the dedicated server from) can attempt evil maid
attacks. You are hopefully able to implement things to detect this, though. attacks. You are hopefully able to implement mechanisms to detect this, though.
There are reasons you may want to go with a rented server instead of one you own, though. For instance, if you live There are reasons you may want to go with a rented server instead of one you own, though. For instance, if you live
in a jurisdiction known for terrible privacy laws such as a [5/14 eyes in a jurisdiction known for terrible privacy laws such as a [5/14 eyes