From e331c60377e62f158bdcdedfc7a0664104cd8e03 Mon Sep 17 00:00:00 2001 From: David Luevano Alvarado Date: Sat, 20 Mar 2021 02:46:53 -0700 Subject: Publish mail entry and reflect sbg fix --- blog/dst/a/mail_server_with_postfix.html | 576 +++++++++++++++++++++++++++++++ blog/dst/a/website_with_nginx.html | 34 +- 2 files changed, 593 insertions(+), 17 deletions(-) create mode 100644 blog/dst/a/mail_server_with_postfix.html (limited to 'blog/dst/a') diff --git a/blog/dst/a/mail_server_with_postfix.html b/blog/dst/a/mail_server_with_postfix.html new file mode 100644 index 0000000..eafb6bf --- /dev/null +++ b/blog/dst/a/mail_server_with_postfix.html @@ -0,0 +1,576 @@ + + + + + + + + + + + + + + + + Luévano's Blog + + + +
+ + + +
+ +
+ + +
+

Create a Mail server with Postfix, Dovecot, SpamAssassin and OpenDKIM

+ +

The entry is going to be long because it's a tedious process. This is also based on Luke Smith's script, but adapted to Arch Linux (his script works on debian-based distributions). This entry is mostly so I can record all the notes required while I'm in the process of installing/configuring the mail server on a new VPS of mine; also I'm going to be writing a script that does everything in one go (for Arch Linux), that will be hosted here.

+ +

This configuration works for local users (users that appear in /etc/passwd), and does not use any type of SQL. And note that most if not all commands executed here are run with root privileges.

+ +

More in depth configuration is detailed in the Arch Wiki for each package used here.

+ +

Prerequisites

+ +

Basically the same as with the website with Nginx and Certbot:

+ + + +

Postfix

+ +

Postfix is a “mail transfer agent” which is the component of the mail server that receives and sends emails via SMTP.

+ +

Install the postfix package:

+ +
pacman -S postfix
+
+ +

We have two main files to configure (inside /etc/postfix): master.cf (master(5)) and main.cf (postconf(5)). We're going to edit main.cf first either by using the command postconf -e 'setting' or by editing the file itself (I prefer to edit the file).

+ +

Note that the default file itself has a lot of comments with description on what each thing does (or you can look up the manual, linked above), I used what Luke's script did plus some other settings that worked for me.

+ +

Now, first locate where your website cert is, mine is at the default location /etc/letsencrypt/live/, so my certdir is /etc/letsencrypt/live/luevano.xyz. Given this information, change {yourcertdir} on the corresponding lines. The configuration described below has to be appended in the main.cf configuration file.

+ +

Certificates and ciphers to use for authentication and security:

+ +
smtpd_tls_key_file = {yourcertdir}/privkey.pem
+smtpd_tls_cert_file = {yourcertdir}/fullchain.pem
+smtpd_use_tls = yes
+smtpd_tls_auth_only = yes
+smtp_tls_security_level = may
+smtp_tls_loglevel = 1
+smtp_tls_CAfile = {yourcertdir}/cert.pem
+smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+tls_preempt_cipherlist = yes
+smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5,
+                DSS, ECDSA, CAMELLIA128, 3DES, CAMELLIA256,
+                RSA+AES, eNULL
+
+smtp_tls_CApath = /etc/ssl/certs
+smtpd_tls_CApath = /etc/ssl/certs
+
+smtpd_relay_restrictions = permit_sasl_authenticated, permit_mynetworks, defer_unauth_destination
+
+ +

Also, for the connection with dovecot, append the next few lines (telling postfix that dovecot will use user/password for authentication):

+ +
smtpd_sasl_auth_enable = yes
+smtpd_sasl_type = dovecot
+smtpd_sasl_path = private/auth
+smtpd_sasl_security_options = noanonymous, noplaintext
+smtpd_sasl_tls_security_options = noanonymous
+
+ +

Specify the mailbox home (this is going to be a directory inside your user's home):

+ +
home_mailbox = Mail/Inbox/
+
+ +

Pre-configuration to work seamlessly with dovecot and opendkim:

+ +
myhostname = {yourdomainname}
+mydomain = localdomain
+mydestination = $myhostname, localhost.$mydomain, localhost
+
+milter_default_action = accept
+milter_protocol = 6
+smtpd_milters = inet:127.0.0.1:8891
+non_smtpd_milters = inet:127.0.0.1:8891
+mailbox_command = /usr/lib/dovecot/deliver
+
+ +

Where {yourdomainname} is luevano.xyz in my case, or if you have localhost configured to your domain, then use localhost for myhostname (myhostname = localhost).

+ +

Lastly, if you don't want the sender's IP and user agent (application used to send the mail), add the following line:

+ +
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks
+
+ +

And create the /etc/postfix/smtp_header_checks file with the following content:

+ +
/^Received: .*/     IGNORE
+/^User-Agent: .*/   IGNORE
+
+ +

That's it for main.cf, now we have to configure master.cf. This one is a bit more tricky.

+ +

First look up lines (they're uncommented) smtp inet n - n - - smtpd, smtp unix - - n - - smtp and -o syslog_name=postfix/$service_name and either delete or uncomment them… or just run sed -i "/^\s*-o/d;/^\s*submission/d;/\s*smtp/d" /etc/postfix/master.cf as stated in Luke's script.

+ +

Lastly, append the following lines to complete postfix setup and pre-configure for spamassassin.

+ +
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=spamd argv=/usr/bin/vendor_perl/spamc -f -e /usr/sbin/sendmail -oi -f \${sender} \${recipient}
+
+ +

Now, I ran into some problems with postfix, one being smtps: Servname not supported for ai_socktype, to fix it, as Till posted in that site, edit /etc/services and add:

+ +
smtps 465/tcp
+smtps 465/udp
+
+ +

Before starting the postfix service, you need to run newaliases first (but you can do a bit of configuration beforehand). Edit the file /etc/postfix/aliases and edit accordingly. I only change the root: you line (where you is the account that will be receiving “root” mail). Check the Arch Wiki for more info and other alternatives/options. After you're done, run:

+ +
postalias /etc/postfix/aliases
+newaliases
+
+ +

At this point you're done configuring postfix and you can already start/enable the postfix service:

+ +
systemctl start postfix.service
+systemctl enable postfix.service
+
+ +

Dovecot

+ +

Dovecot is an IMAP and POP3 server, which is what lets an email application retrieve the mail.

+ +

Install the dovecot and pigeonhole (sieve for dovecot) packages:

+ +
pacman -S dovecot pigeonhole
+
+ +

On arch, by default, there is no /etc/dovecot directory with default configurations set in place, but the package does provide the example configuration files. Create the dovecot directory under /etc and, optionally, copy the dovecot.conf file and conf.d directory under the just created dovecot directory:

+ +
mkdir /etc/dovecot
+cp /usr/share/doc/dovecot/example-config/dovecot.conf /etc/dovecot/dovecot.conf
+cp -r /usr/share/doc/dovecot/example-config/conf.d /etc/dovecot
+
+ +

As Luke stated, dovecot comes with a lot of “modules” (under /etc/dovecot/conf.d/ if you copied that folder) for all sorts of configurations that you can include, but I do as he does and just edits/creates the whole dovecot.conf file; although, I would like to check each of the separate configuration files dovecot provides I think the options Luke provides are more than good enough.

+ +

I'm working with an empty dovecot.conf file. Add the following lines for SSL and login configuration (also replace {yourcertdir} with the same certificate directory described in the Postfix section above, note that the < is required):

+ +
ssl = required
+ssl_cert = <{yourcertdir}/fullchain.pem
+ssl_key = <{yourcertdir}/privkey.pem
+ssl_min_protocol = TLSv1.2
+ssl_cipher_list = ALL:!RSA:!CAMELLIA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SHA1:!SHA256:!SHA384:!LOW@STRENGTH
+ssl_prefer_server_ciphers = yes
+ssl_dh = </etc/dovecot/dh.pem
+
+auth_mechanisms = plain login
+auth_username_format = %n
+protocols = $protocols imap
+
+ +

You may notice we specify a file we don't have under /etc/dovecot: dh.pem. We need to create it with openssl (you should already have it installed if you've been following this entry and the one for nginx). Just run (might take a few minutes):

+ +
openssl dhparam -out /etc/dovecot/dh.pem 4096
+
+ +

After that, the next lines define what a “valid user is” (really just sets the database for users and passwords to be the local users with their password):

+ +
userdb {
+    driver = passwd
+}
+
+passdb {
+    driver = pam
+}
+
+ +

Next, comes the mail directory structure (has to match the one described in the Postfix section). Here, the LAYOUT option is important so the boxes are .Sent instead of Sent. Add the next lines (plus any you like):

+ +
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
+        }
+}
+
+ +

Also include this so Postfix can use Dovecot's authentication system:

+ +
service auth {
+    unix_listener /var/spool/postfix/private/auth {
+        mode = 0660
+        user = postfix
+        group = postfix
+        }
+}
+
+ +

Lastly (for dovecot at least), the plugin configuration for sieve (pigeonhole):

+ +
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/
+
+ +

Where /var/lib/dovecot/sieve/default.sieve doesn't exist yet. Create the folders:

+ +
mkdir -p /var/lib/dovecot/sieve
+
+ +

And create the file default.sieve inside that just created folder with the content:

+ +
require ["fileinto", "mailbox"];
+if header :contains "X-Spam-Flag" "YES" {
+    fileinto "Junk";
+}
+
+ +

Now, if you don't have a vmail (virtual mail) user, create one and change the ownership of the /var/lib/dovecot directory to this user:

+ +
grep -q "^vmail:" /etc/passwd || useradd -m vmail -s /usr/bin/nologin
+chown -R vmail:vmail /var/lib/dovecot
+
+ +

Note that I also changed the shell for vmail to be /usr/bin/nologin. After that, run:

+ +
sievec /var/lib/dovecot/sieve/default.sieve
+
+ +

To compile the configuration file (a default.svbin file will be created next to default.sieve).

+ +

Next, add the following lines to /etc/pam.d/dovecot if not already present (shouldn't be there if you've been following these notes):

+ +
auth required pam_unix.so nullok
+account required pam_unix.so
+
+ +

That's it for dovecot, at this point you can start/enable the dovecot service:

+ +
systemctl start dovecot.service
+systemctl enable dovecot.service
+
+ +

OpenDKIM

+ +

OpenDKIM is needed so services like G**gle (we don't mention that name here [[[this is a meme]]]) don't throw the mail to the trash. DKIM stands for “DomainKeys Identified Mail”.

+ +

Install the opendkim package:

+ +
pacman -S opendkim
+
+ +

Generate the keys for your domain:

+ +
opendkim-genkey -D /etc/opendkim -d {yourdomain} -s {yoursubdomain} -r -b 2048
+
+ +

Where you need to change {yourdomain} and {yoursubdomain} (doesn't really need to be the sub-domain, could be anything that describes your key) accordingly, for me it's luevano.xyz and mail, respectively. After that, we need to create some files inside the /etc/opendkim directory. First, create the file KeyTable with the content:

+ +
{yoursubdomain}._domainkey.{yourdomain} {yourdomain}:{yoursubdomain}:/etc/opendkim/{yoursubdomain}.private
+
+ +

So, for me it would be:

+ +
mail._domainkey.luevano.xyz luevano.xyz:mail:/etc/opendkim/mail.private
+
+ +

Next, create the file SigningTable with the content:

+ +
*@{yourdomain} {yoursubdomain}._domainkey.{yourdomain}
+
+ +

Again, for me it would be:

+ +
*@luevano.xyz mail._domainkey.luevano.xyz
+
+ +

And, lastly create the file TrustedHosts with the content:

+ +
127.0.0.1
+::1
+10.1.0.0/16
+1.2.3.4/24
+localhost
+{yourserverip}
+...
+
+ +

And more, make sure to include your server IP and something like subdomain.domainname.

+ +

Next, edit /etc/opendkim/opendkim.conf to reflect the changes (or rather, additions) of these files, as well as some other configuration. You can look up the example configuration file located at /usr/share/doc/opendkim/opendkim.conf.sample, but I'm creating a blank one with the contents:

+ +
Domain {yourdomain}
+Selector {yoursubdomain}
+
+Syslog Yes
+UserID opendkim
+
+KeyFile /etc/opendkim/{yoursubdomain}.private
+Socket inet:8891@localhost
+
+ +

Now, change the permissions for all the files inside /etc/opendkim:

+ +
chown -R root:opendkim /etc/opendkim
+chmod g+r /etc/postfix/dkim/*
+
+ +

I'm using root:opendkim so opendkim doesn't complain about the {yoursubdomani}.private being insecure (you can change that by using the option RequireSafeKeys False in the opendkim.conf file, as stated here).

+ +

That's it for the general configuration, but you could go more in depth and be more secure with some extra configuration as described in the Arch Wiki entry for OpenDKIM.

+ +

Now, just start/enable the opendkim service:

+ +
systemctl start opendkim.service
+systemctl enable opendkim.service
+
+ +

And don't forget to add the following TXT records on your domain registrar (these examples are for Epik):

+ +
    +
  1. DKIM entry: look up your {yoursubdomain}.txt file, it should look something like:
  2. +
+ +
{yoursubdomain}._domainkey IN TXT ( "v=DKIM1; k=rsa; s=email; "
+    "p=..."
+    "..." )  ; ----- DKIM key mail for {yourdomain}
+
+ +

In the TXT record you will place {yoursubdomain}._domainkey as the “Host” and "v=DKIM1; k=rsa; s=email; " "p=..." "..." in the “TXT Value” (replace the dots with the actual value you see in your file).

+ +
    +
  1. DMARC entry: just _dmarc.{yourdomain} as the “Host” and "v=DMARC1; p=reject; rua=mailto:dmarc@{yourdomain}; fo=1" as the “TXT Value”.

  2. +
  3. SPF entry: just @ as the “Host” and "v=spf1 mx a:{yoursubdomain}.{yourdomain} - all" as the “TXT Value”.

  4. +
+ +

And at this point you could test your mail for spoofing and more, but you don't know -yet- how to login (it's really easy, but I'm gonna state that at the end of this entry).

+ +

SpamAssassin

+ +

SpamAssassin is just a mail filter to identify spam.

+ +

Install the spamassassin package (which will install a bunch of ugly perl packages…):

+ +
pacman -S spamassassin
+
+ +

For some reason, the permissions on all spamassassin stuff are all over the place. First, change owner of the executables, and directories:

+ +
chown spamd:spamd /usr/bin/vendor_perl/sa-*
+chown spamd:spamd /usr/bin/vendor_perl/spam*
+chwown -R spamd:spamd /etc/mail/spamassassin
+
+ +

Then, you can edit local.cf (located in /etc/mail/spamassassin) to fit your needs (I only uncommented the rewrite_header Subject ... line). And then you can run the following command to update the patterns and compile them:

+ +
sudo -u spamd sa-update
+sudo -u spamd sa-compile
+
+ +

And since this should be run periodically, create the service spamassassin-update.service under /etc/systemd/system with the following content:

+ +
[Unit]
+Description=SpamAssassin housekeeping
+After=network.target
+
+[Service]
+User=spamd
+Group=spamd
+Type=oneshot
+
+ExecStart=/usr/bin/vendor_perl/sa-update --allowplugins
+SuccessExitStatus=1
+ExecStart=/usr/bin/vendor_perl/sa-compile
+ExecStart=/usr/bin/systemctl -q --no-block try-restart spamassassin.service
+
+ +

And you could also execute sa-learn to train spamassassin's bayes filter, but this works for me. Then create the timer spamassassin-update.timer under the same directory, with the content:

+ +
[Unit]
+Description=SpamAssassin housekeeping
+
+[Timer]
+OnCalendar=daily
+Persistent=true
+
+[Install]
+WantedBy=timers.target
+
+ +

You can now start/enable the spamassassin-update timer:

+ +
systemctl start spamassassin-update.timer
+systemctl enable spamassassin-update.timer
+
+ +

Next, you may want to edit the spamassassin service before starting and enabling it, because by default, it could spawn a lot of “childs” eating a lot of resources and you really only need one child. Append --max-children=1 to the line ExecStart=... in /usr/bin/systemd/system/spamassassin.service:

+ +
...
+ExecStart=/usr/bin/vendor_perl/spamd -x -u spamd -g spamd --listen=/run/spamd/spamd.sock --listen=localhost --max-children=1
+...
+
+ +

Finally, start and enable the spamassassin service:

+ +
systemctl start spamassassin.service
+systemctl enable spamassassin.service
+
+ +

Wrapping up

+ +

We should have a working mail server by now. Before continuing check your journal logs (journalctl -xe --unit={unit}, where {unit} could be spamassassin.servicefor example) to see if there was any error whatsoever and try to debug it, it should be a typo somewhere (the logs are generally really descriptive) because all the settings and steps detailed here just (literally just finished doing everything on a new server as of the writing of this text) worked (((it just werks on my machine))).

+ +

Now, to actually use the mail service: first of all, you need a normal account (don't use root) that belongs to the mail group (gpasswd -a user group to add a user user to group group) and that has a password.

+ +

Next, to actually login into a mail app/program/whateveryouwanttocallit, you will use the following settings, at least for thunderdbird(I tested in windows default mail app and you don't need a lot of settings):

+ + + +

All that's left to do is test your mail server for spoofing, and to see if everything is setup correctly. Go to DKIM Test and follow the instructions (basically click next, and send an email with whatever content to the email that they provide). After you send the email, you should see something like:

+ +

DKIM Test successful

+ +

(Yes, I blurred a lot in the picture just to be sure, either way what's important is the list on the bottom part of the image)

+ +

Finally, that's actually it for this entry, if you have any problem whatsoever you have my info down below.

+ +
+
+

Created: Sat, Mar 20, 2021 @ 02:23 MST

+
+ + + diff --git a/blog/dst/a/website_with_nginx.html b/blog/dst/a/website_with_nginx.html index 45366e4..69b371b 100644 --- a/blog/dst/a/website_with_nginx.html +++ b/blog/dst/a/website_with_nginx.html @@ -65,7 +65,7 @@

These are general notes on how to setup a Nginx web server plus Certbot for SSL certificates, initially learned from Luke's video and after some use and research I added more stuff to the mix. And, actually at the time of writing this entry, I'm configuring the web server again on a new VPS instance, so this is going to be fresh.

-

As a side note, (((i use arch btw))) so everything here es aimed at an Arch Linux distro, and I'm doing everything on a VPS.

+

As a side note, (((i use arch btw))) so everything here es aimed at an Arch Linux distro, and I'm doing everything on a VPS. Also note that most if not all commands here are executed with root privileges.

Prerequisites

@@ -81,7 +81,7 @@ @@ -90,9 +90,9 @@

You have two options: nginx and nginx-mainline. I prefer nginx-mainline because it's the “up to date” package even though nginx is labeled to be the “stable” version. Install the package and enable/start the service:

-
# pacman -S nginx-mainline
-# systemctl enable nginx.service
-# systemctl start nginx.service
+
pacman -S nginx-mainline
+systemctl enable nginx.service
+systemctl start nginx.service
 

And that's it, at this point you can already look at the default initial page of nginx if you enter the ip of your server in a web browser. You should see something like this:

@@ -101,7 +101,7 @@

As stated in the welcome page, configuration is needed, head to the directory of nginx:

-
# cd /etc/nginx
+
cd /etc/nginx
 

Here you have several files, the important one is nginx.conf, which as its name implies, contains general configuration of the web server. If you peek into the file, you will see that it contains around 120 lines, most of which are commented out and contains the welcome page server block. While you can configure a website in this file, it's common practice to do it on a separate file (so you can scale really easily if needed for mor websites or sub-domains).

@@ -129,9 +129,9 @@ http {

Next, inside the directory /etc/nginx/ create the sites-available and sites-enabled, and go into the sites-available one:

-
# mkdir sites-available
-# mkdir sites-enabled
-# cd sites-available
+
mkdir sites-available
+mkdir sites-enabled
+cd sites-available
 

Here, create a new .conf file for your website and add the following lines (this is just the sample content more or less):

@@ -166,15 +166,15 @@ http {

Then, make a symbolic from this config file to the sites-enabled directory:

-
# ln -s /etc/nginx/sites-available/your_config_file.conf /etc/nginx/sites-enabled
+
ln -s /etc/nginx/sites-available/your_config_file.conf /etc/nginx/sites-enabled
 

This is so the nginx.conf file can look up the newly created server config. With this method of having each server configuration file separate you can easily “deactivate” any website by just deleting the symbolic link in sites-enabled and you're good, or just add new configuration files and keep everything nice and tidy.

All you have to do now is restart (or enable and start if you haven't already) the nginx service (and optionally test the configuration):

-
# nginx -t
-# systemctl restart nginx
+
nginx -t
+systemctl restart nginx
 

If everything goes correctly, you can now go to your website by typing “domain.name” on a web browser. But you will see a “404 Not Found” page like the following (maybe with different nginx version):

@@ -200,19 +200,19 @@ http {

The only “bad” (bloated) thing about certbot, is that it uses python, but for me it doesn't matter too much. You may want to look up another alternative if you prefer. Install the packages certbot and certbot-nginx:

-
# pacman -S certbot certbot-nginx
+
pacman -S certbot certbot-nginx
 

After that, all you have to do now is run certbot and follow the instructions given by the tool:

-
# certbot --nginx
+
certbot --nginx
 

It will ask you for some information, for you to accept some agreements and the names to activate https for. Also, you will want to “say yes” to the redirection from http to https. And that's it, you can now go to your website and see that you have https active.

-

Now, the certificate given by certbot expires every 3 months or something like that, so you want to renew this certificate every once in a while. Using cron, you can do this by running:

+

Now, the certificate given by certbot expires every 3 months or something like that, so you want to renew this certificate every once in a while. Using cron, you can do this by running:

-
# crontab -e
+
crontab -e
 

And a file will be opened where you need to add a new rule for certbot, just append the line: 1 1 1 * * certbot renew (renew on the first day of every month) and you're good. Alternatively use systemd timers as stated in the Arch Linux Wiki.

@@ -223,7 +223,7 @@ http {

-

Created: Sat, Mar 13, 2021 @ 23:08 MST

+

Created: Thu, Mar 18, 2021 @ 19:58 MST