Mercredi 12 février 2020 (Modifié le Mercredi 4 mars 2020)

OVH vps785909 (1 vCore/2GoRam/20GoSSD) Debian Buster

cinay.eu - Serveur de Messagerie

Texte alternatif

Système de base : Debian Buster
Hébergeur : OVH
Composants du serveur de messagerie :

  • Postfix (SMTP)Dovecot (IMAP)
  • Rspamd (Antispam)
  • Rainloop (Webmail)
  • Dkim SPF Dmarc
  • Filtres Sieve

Prérequis

Serveur Debian Buster fonctionnel

  • nginx version: nginx/1.16.1
  • OpenSSL 1.1.1d 10 Sep 2019
  • mysql Ver 15.1 Distrib 10.3.18-MariaDB (Mot de passe MySql/MariaDB : /etc/mysql/mdp)
  • PHP 7.3.14-5+0~20200202.52+debian10~1.gbpa71879 (cli) (built: Feb 2 2020 07:53:51)
  • Certificats Let’s Encrypt
  • Parefeu iptables

Passez en root et mise à jour distribution

sudo -s
apt-get update && apt-get upgrade

Créer un groupe et un user vmail :

groupadd -g 5000 vmail
useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /var/mail/vmail -m vmail

Installation appli utiles + nginx, php, mysql (Mariadb)

Dans le cas ou nginx + PHP7.3 et mariadb sont installés , paragraphe B

A - Installation complète

apt install curl git unzip ntp ntpdate openssl php7.3-fpm php7.3 php7.3-common php7.3-gd php7.3-mysql php7.3-imap php7.3-cli php7.3-cgi php-pear mcrypt imagemagick libruby php7.3-curl php7.3-intl php7.3-pspell php7.3-recode php7.3-sqlite3 php7.3-tidy php7.3-xmlrpc php7.3-xsl memcached php-memcache php-imagick php-gettext php7.3-zip php7.3-mbstring

Outils

apt install mc screen htop vim-nox nginx mariadb-server 

On sécurise Mysql en ajoutant un mot de passe root

mysql_secure_installation
  • Enter current password for root (enter for none): ENTREE
  • Set root password? [Y/n] Tapez Y
  • New password: Entrez le mot de passe pour le user root
  • Re-enter new password: mot de passe de nouveau…
  • Remove anonymous users? [Y/n] Tapez Y
  • Disallow root login remotely? [Y/n] Tapez Y
  • Remove test database and access to it? [Y/n] Tapez Y
  • Reload privilege tables now? [Y/n] Tapez Y

B - Installation complémentaire (suite compilation Nginx + PHP7.3 + MariaDB)

apt install php7.3-imap php7.3-xmlrpc php7.3-xsl php7.3-pspell php7.3-recode php-memcache memcached php-gettext php-pear mcrypt libruby

PostfixAdmin

On va utiliser PHP5.6

sudo apt install php5.6 php5.6-fpm php5.6-mysql

Télécharger Postfixadmin (la dernière version au 09/10/19 est la 3.2)

wget https://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-3.2/postfixadmin-3.2.tar.gz
tar xzf postfixadmin-3.2.tar.gz

Déplacer postfixadmin → /var/www/postfixadmin et créer le répertoire templates_c :

mv postfixadmin-3.2/ /var/www/postfixadmin
rm -f postfixadmin-3.2.tar.gz
mkdir /var/www/postfixadmin/templates_c

Créer un utilisateur système (-s) sans home (-M) id défini (990) pfa

sudo useradd -M -u 991  -r -s /bin/false -c "User pfa" pfa
sudo chown pfa:pfa /var/www/postfixadmin -R

Configuration php pfa.conf

sudo nano /etc/php/5.6/fpm/pool.d/pfa.conf
[pfa]
user = pfa
group = pfa
listen = /run/php/php5.6-fpm-pfa.sock
listen.owner = www-data
listen.group = www-data
pm = ondemand
pm.max_children = 4

Générer un mot de passe

echo $(head -c 12 /dev/urandom | openssl enc -base64) > /etc/mysql/pfa

Créer la base mysql pour postfixadmin

mysql -u root -p$(cat /etc/mysql/mdp) -e "CREATE DATABASE postfixadmin; GRANT ALL ON postfixadmin.* TO 'postfixadmin'@'localhost' IDENTIFIED BY '$(cat /etc/mysql/pfa)'; FLUSH PRIVILEGES;"

Configuration /var/www/postfixadmin/config.local.php

<?php
$CONF['configured'] = true;

$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'js556h';
$CONF['database_name'] = 'postfixadmin';

$CONF['default_aliases'] = array (
  'abuse'      => 'abuse@cinay.eu',
  'hostmaster' => 'hostmaster@cinay.eu',
  'postmaster' => 'postmaster@cinay.eu',
  'webmaster'  => 'webmaster@cinay.eu'
);

$CONF['fetchmail'] = 'NO';
$CONF['show_footer_text'] = 'NO';

$CONF['quota'] = 'YES';
$CONF['domain_quota'] = 'YES';
$CONF['quota_multiplier'] = '1024000';
$CONF['used_quotas'] = 'YES';
$CONF['new_quota_table'] = 'YES';

$CONF['aliases'] = '0';
$CONF['mailboxes'] = '0';
$CONF['maxquota'] = '0';
$CONF['domain_quota_default'] = '0';
?>

Installer le schéma de la base en lançant le script suivant

sudo -u pfa /usr/bin/php5.6 /var/www/postfixadmin/public/upgrade.php

Modifier pour exécution en php5.6

nano /var/www/postfixadmin/scripts/postfixadmin-cli
#!/bin/bash
# LIB is expected to be relative to this script (inside the PostfixAdmin sources)
# This breaks if you symlink postfixadmin-cli to /usr/bin or alike. Therefore we
# have to follow the symlink to get the correct path.
self="$0"
test -L "$self" && self="`readlink -f \"$self\"`"

LIB="${self/%postfixadmin-cli/}"

exec /usr/bin/php5.6 -q "${LIB}postfixadmin-cli.php" "$@"

exit;

Créer le superadmin Postfixadmin

sudo bash /var/www/postfixadmin/scripts/postfixadmin-cli admin add
Welcome to Postfixadmin-CLI v0.2
---------------------------------------------------------------
Admin:  
> hostmaster@cinay.eu
Password:  
> vWLq5cuSbEBfD6fn
Password (again):  
> vWLq5cuSbEBfD6fn
Super admin:
(Super admins have access to all domains, can manage domains and admin accounts.) (y/n)
> y
Domain:  
> cinay.eu
Active: (y/n)
> y
The admin postmaster@cinay.eu has been added!

Certificats letsencrypt installés par acme

Créer le fichier Nginx dans /etc/nginx/conf.d/pfa.cinay.eu.conf

	##
	# Virtual Host pfa.cinay.eu
	##

	server {
	    listen 80;
	    listen [::]:80;
	
	    ## redirect http to https ##
	    server_name pfa.cinay.eu;
	    return  301 https://$server_name$request_uri;
	}
	
	server {
	    listen 443 ssl http2;
	    listen [::]:443 ssl http2;
	    server_name pfa.cinay.eu;

	    include ssl_dh_headers_ocsp;

	    root /var/www/postfixadmin/public;
	    index index.php;
	
        location ~ \.php$ {
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass unix:/run/php/php5.6-fpm-pfa.sock;   # PHP5.6
          fastcgi_index index.php;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_intercept_errors off;
          fastcgi_buffer_size 16k;
          fastcgi_buffers 4 16k;
          fastcgi_connect_timeout 600;
          fastcgi_send_timeout 600;
          fastcgi_read_timeout 600;
        }


   location / {
       try_files $uri $uri/ =404;
   }

}

Problème sur PHP7 et +
Pour éviter la page “blanche” , nous devons stocker l’en-tête dans un tampon et envoyer le tampon à la fin du script. Pour stocker l’en-tête dans le tampon, nous utiliserons donc la fonction php ob_start() et pour nettoyer le tampon, nous utiliserons la fonction ob_end_flush().Il faut modifier le fichier index.php qui redirige vers login.php si config “true”.Voir article How to Solve PHP header() Function Problem

sudo nano /var/www/postfixadmin/public/index.php
<?php
/**
 * Postfix Admin
 *
 * LICENSE
 * This source file is subject to the GPL license that is bundled with
 * this package in the file LICENSE.TXT.
 *
 * Further details on the project are available at http://postfixadmin.sf.net or https://github.com/postfixadmin/postfixadmin
 *
 * @version $Id$
 * @license GNU GPL v2 or later.
 *
 * File: index.php
 * Shows a sort-of welcome page.
 * Template File: -none-
 *
 * Template Variables: -none-
 *
 * Form POST \ GET Variables: -none-
 */
ob_start();
$CONF = array('configured' => false);

if (file_exists(dirname(__FILE__) . '/../config.inc.php')) {
    require_once(dirname(__FILE__) . '/../config.inc.php');
}

if ($CONF['configured'] === true) {
    header("Location: login.php");
    ob_end_flush();
    echo " Config true";
    exit;
}
// si config false,
ob_end_flush();
?>
[...]

Vérification et on redémarre Nginx :

nginx -t
systemctl restart php5.6-fpm
systemctl restart nginx

https://pfa.cinay.eu

Postfix & Dovecot

Les paquets Dovecot Debian Buster sont à jour.

debconf-set-selections <<< "postfix postfix/mailname string $(hostname -f)"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"
apt install postfix postfix-mysql dovecot-imapd dovecot-lmtpd dovecot-pop3d dovecot-mysql

Configuration de Postfix

Postfix

mkdir -p /etc/postfix/sql
cat > /etc/postfix/sql/mysql_virtual_domains_maps.cf << EOF
user = postfixadmin
password = $(cat /etc/mysql/pfa)
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
EOF
 
cat > /etc/postfix/sql/mysql_virtual_alias_maps.cf << EOF
user = postfixadmin
password = $(cat /etc/mysql/pfa)
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
EOF
 
cat > /etc/postfix/sql/mysql_virtual_alias_domain_maps.cf << EOF
user = postfixadmin
password = $(cat /etc/mysql/pfa)
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
EOF
 
cat > /etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf << EOF
user = postfixadmin
password = $(cat /etc/mysql/pfa)
hosts = 127.0.0.1
dbname = postfixadmin
query  = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
EOF
 
cat > /etc/postfix/sql/mysql_virtual_mailbox_maps.cf << EOF
user = postfixadmin
password = $(cat /etc/mysql/pfa)
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
EOF
 
cat > /etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf << EOF
user = postfixadmin
password = $(cat /etc/mysql/pfa)
hosts = 127.0.0.1
dbname = postfixadmin
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
EOF

Puis on complète la configuration du fichier /etc/postfix/main.cf de Postfix

postconf -e "myhostname = cinay.eu"
postconf -e "mydestination = localhost"
postconf -e "virtual_mailbox_domains = mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf"
postconf -e "virtual_alias_maps = mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf"
postconf -e "virtual_mailbox_maps = mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf"

postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e 'smtp_tls_security_level = may'
postconf -e 'smtpd_tls_security_level = may'
postconf -e 'smtp_tls_note_starttls_offer = yes'
postconf -e 'smtpd_tls_loglevel = 1'
postconf -e 'smtpd_tls_received_header = yes'
 
postconf -e 'smtpd_tls_cert_file = /etc/ssl/private/cinay.eu-fullchain.pem'
postconf -e 'smtpd_tls_key_file = /etc/ssl/private/cinay.eu-key.pem'
 
postconf -e 'smtpd_sasl_type = dovecot'
postconf -e 'smtpd_sasl_path = private/auth'
postconf -e 'smtpd_sasl_local_domain ='
postconf -e 'smtpd_sasl_security_options = noanonymous'
postconf -e 'broken_sasl_auth_clients = yes'
postconf -e 'smtpd_sasl_auth_enable = yes'
postconf -e 'smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination'

On configure le fichier /etc/postfix/master.cf de Postfix

submission inet n       -       y       -       -       smtpd 
  -o syslog_name=postfix/submission 
  -o smtpd_tls_security_level=encrypt 
  -o smtpd_sasl_auth_enable=yes
  #  -o smtpd_reject_unlisted_recipient=no 
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  #  -o smtpd_helo_restrictions=$mua_helo_restrictions
  #  -o smtpd_sender_restrictions=$mua_sender_restrictions
  #  -o smtpd_recipient_restrictions=
  #  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject 
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       y       -       -       smtpd 
  -o syslog_name=postfix/smtps 
  -o smtpd_tls_wrappermode=yes 
  -o smtpd_sasl_auth_enable=yes
  #  -o smtpd_reject_unlisted_recipient=no 
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  #  -o smtpd_helo_restrictions=$mua_helo_restrictions
  #  -o smtpd_sender_restrictions=$mua_sender_restrictions
  #  -o smtpd_recipient_restrictions=
  #  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject 
  -o milter_macro_daemon_name=ORIGINATING

… et on redémarre Postfix :

service postfix restart

Configuration Dovecot

Dovecot

On va configurer Dovecot :

nano /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=127.0.0.1 dbname=postfixadmin user=postfixadmin password=jsA8b7KJWwjcENXh
default_pass_scheme = MD5-CRYPT
iterate_query = SELECT username AS user FROM mailbox
user_query = SELECT CONCAT('/var/mail/vmail/',maildir) AS home,   CONCAT('maildir:/var/mail/vmail/',maildir) AS mail,   5000 AS uid, 5000 AS gid, CONCAT('*:bytes=',quota) AS quota_rule   FROM mailbox WHERE username = '%u' AND active = 1
password_query = SELECT username AS user,password FROM mailbox   WHERE username = '%u' AND active='1'
nano /etc/dovecot/conf.d/10-mail.conf
...
mail_location = maildir:/var/mail/vmail/%d/%n
...
mail_uid = vmail
mail_gid = vmail
...
first_valid_uid = 5000
last_valid_uid = 5000
...
mail_privileged_group = mail
...
mail_plugins = quota
...
nano /etc/dovecot/conf.d/10-auth.conf
...
disable_plaintext_auth = yes
...
auth_mechanisms = plain login
...
#!include auth-system.conf.ext
!include auth-sql.conf.ext
...
rm /etc/dovecot/conf.d/10-master.conf
nano /etc/dovecot/conf.d/10-master.conf
#default_process_limit = 100
#default_client_limit = 1000

# Default VSZ (virtual memory size) limit for service processes. This is mainly
# intended to catch and kill processes that leak memory before they eat up
# everything.
#default_vsz_limit = 256M

# Login user is internally used by login processes. This is the most untrusted
# user in Dovecot system. It shouldn't have access to anything at all.
#default_login_user = dovenull

# Internal user is used by unprivileged processes. It should be separate from
# login user, so that login processes can't disturb other processes.
#default_internal_user = dovecot

service imap-login {
  inet_listener imap {
    #port = 143
  }
  inet_listener imaps {
    #port = 993
    #ssl = yes
  }

  # Number of connections to handle before starting a new process. Typically
  # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0
  # is faster. <doc/wiki/LoginProcess.txt>
  #service_count = 1

  # Number of processes to always keep waiting for more connections.
  #process_min_avail = 0

  # If you set service_count=0, you probably need to grow this.
  #vsz_limit = $default_vsz_limit
}

service pop3-login {
  inet_listener pop3 {
    #port = 110
  }
  inet_listener pop3s {
    #port = 995
    #ssl = yes
  }
}

service submission-login {
  inet_listener submission {
    #port = 587
  }
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    #mode = 0666
   mode = 0600
   user = postfix 
   group = postfix 
  }

  # Create inet listener only if you can't use the above UNIX socket
  #inet_listener lmtp {
    # Avoid making LMTP visible for the entire internet
    #address =
    #port = 
  #}
}

service imap {
  # Most of the memory goes to mmap()ing files. You may need to increase this
  # limit if you have huge mailboxes.
  #vsz_limit = $default_vsz_limit

  # Max. number of IMAP processes (connections)
  #process_limit = 1024
}

service pop3 {
  # Max. number of POP3 processes (connections)
  #process_limit = 1024
}

service submission {
  # Max. number of SMTP Submission processes (connections)
  #process_limit = 1024
}

service auth {
  # auth_socket_path points to this userdb socket by default. It's typically
  # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
  # full permissions to this socket are able to get a list of all usernames and
  # get the results of everyone's userdb lookups.
  #
  # The default 0666 mode allows anyone to connect to the socket, but the
  # userdb lookups will succeed only if the userdb returns an "uid" field that
  # matches the caller process's UID. Also if caller's uid or gid matches the
  # socket's uid or gid the lookup succeeds. Anything else causes a failure.
  #
  # To give the caller full permissions to lookup all users, set the mode to
  # something else than 0666 and Dovecot lets the kernel enforce the
  # permissions (e.g. 0777 allows everyone full permissions).
  unix_listener auth-userdb {
   mode = 0600
   user = vmail
   group = vmail
  }

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = vmail
    group = vmail
  }

  # Auth process is run as this user.
  #user = $default_internal_user
}

service auth-worker {
  # Auth worker process is run as root by default, so that it can access
  # /etc/shadow. If this isn't necessary, the user should be changed to
  # $default_internal_user.
  user = vmail
}

service dict {
  # If dict proxy is used, mail processes should have access to its socket.
  # For example: mode=0660, group=vmail and global mail_access_groups=vmail
  unix_listener dict {
    mode = 0600
    user = vmail
    group = vmail
  }
}
nano /etc/dovecot/conf.d/10-ssl.conf
...
ssl = yes
...
ssl_cert = </etc/ssl/private/cinay.eu-fullchain.pem
ssl_key = </etc/ssl/private/cinay.eu-key.pem
...
ssl_dh = </etc/ssl/private/dh2048.pem
...
ssl_min_protocol = TLSv1.2
...
ssl_cipher_list = EECDH+AES:EDH+AES+aRSA
...
ssl_prefer_server_ciphers = yes
...
nano /etc/dovecot/conf.d/20-imap.conf
...
protocol imap { 
...
  mail_plugins = $mail_plugins imap_quota
  ...
}
...
nano /etc/dovecot/conf.d/20-lmtp.conf
##
## LMTP specific settings
##

protocol lmtp {
  postmaster_address = postmaster@cinay.eu
  mail_plugins = $mail_plugins
}
rm /etc/dovecot/conf.d/15-mailboxes.conf
nano /etc/dovecot/conf.d/15-mailboxes.conf
##
## Mailbox definitions
##

# Each mailbox is specified in a separate mailbox section. The section name
# specifies the mailbox name. If it has spaces, you can put the name
# "in quotes". These sections can contain the following mailbox settings:
#
# auto:
#   Indicates whether the mailbox with this name is automatically created
#   implicitly when it is first accessed. The user can also be automatically
#   subscribed to the mailbox after creation. The following values are
#   defined for this setting:
# 
#     no        - Never created automatically.
#     create    - Automatically created, but no automatic subscription.
#     subscribe - Automatically created and subscribed.
#  
# special_use:
#   A space-separated list of SPECIAL-USE flags (RFC 6154) to use for the
#   mailbox. There are no validity checks, so you could specify anything
#   you want in here, but it's not a good idea to use flags other than the
#   standard ones specified in the RFC:
#
#     \All       - This (virtual) mailbox presents all messages in the
#                  user's message store.
#     \Archive   - This mailbox is used to archive messages.
#     \Drafts    - This mailbox is used to hold draft messages.
#     \Flagged   - This (virtual) mailbox presents all messages in the
#                  user's message store marked with the IMAP \Flagged flag.
#     \Important - This (virtual) mailbox presents all messages in the
#                  user's message store deemed important to user.
#     \Junk      - This mailbox is where messages deemed to be junk mail
#                  are held.
#     \Sent      - This mailbox is used to hold copies of messages that
#                  have been sent.
#     \Trash     - This mailbox is used to hold messages that have been
#                  deleted.
#
# comment:
#   Defines a default comment or note associated with the mailbox. This
#   value is accessible through the IMAP METADATA mailbox entries
#   "/shared/comment" and "/private/comment". Users with sufficient
#   privileges can override the default value for entries with a custom
#   value.

# NOTE: Assumes "namespace inbox" has been defined in 10-mail.conf.
namespace inbox {
  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    special_use = \Drafts
  }
  mailbox Junk {
    special_use = \Junk
  }
  mailbox Trash {
    special_use = \Trash
  }
  mailbox Spam {
    special_use = \Junk
    auto = subscribe
  }

  # For \Sent mailboxes there are two widely used names. We'll mark both of
  # them as \Sent. User typically deletes one of them if duplicates are created.
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }

  # If you have a virtual "All messages" mailbox:
  #mailbox virtual/All {
  #  special_use = \All
  #  comment = All my messages
  #}

  # If you have a virtual "Flagged" mailbox:
  #mailbox virtual/Flagged {
  #  special_use = \Flagged
  #  comment = All my flagged messages
  #}

  # If you have a virtual "Important" mailbox:
  #mailbox virtual/Important {
  #  special_use = \Important
  #  comment = All my important messages
  #}
}
nano /etc/dovecot/conf.d/90-quota.conf
plugin {
 quota = dict:User quota::proxy::sqlquota
 quota_rule = *:storage=5GB
 quota_rule2 = Trash:storage=+100M
 quota_grace = 10%%
 quota_exceeded_message = Quota exceeded, please contact your system administrator.
}

plugin {
 quota_warning = storage=100%% quota-warning 100 %u
 quota_warning2 = storage=95%% quota-warning 95 %u
 quota_warning3 = storage=90%% quota-warning 90 %u
 quota_warning4 = storage=85%% quota-warning 85 %u
}

service quota-warning {
 executable = script /usr/local/bin/quota-warning.sh
 user = vmail

 unix_listener quota-warning {
  group = vmail
  mode = 0660
  user = vmail
 }
}

dict {
 sqlquota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
}
nano /etc/dovecot/dovecot-dict-sql.conf.ext
...
connect = host=127.0.0.1 dbname=postfixadmin user=postfixadmin password=jsA8b7KJWwjcENXh
...
map {
  pattern = priv/quota/storage
  table = quota2
  username_field = username
  value_field = bytes
}
map {
  pattern = priv/quota/messages
  table = quota2
  username_field = username
  value_field = messages
}
...
# map {
#   pattern = shared/expire/$user/$mailbox
#   table = expires
#   value_field = expire_stamp
#
#   fields {
#     username = $user
#     mailbox = $mailbox
#   }
# }
...
nano /usr/local/bin/quota-warning.sh
#!/bin/sh
PERCENT=$1
USER=$2
cat << EOF | /usr/lib/dovecot/dovecot-lda -d $USER -o "plugin/quota=dict:User quota::noenforcing:proxy::sqlquota"
From: postmaster@cinay.eu
Subject: Quota warning
Your mailbox is $PERCENT% full. Don't forget to make a backup of old messages to remain able to receive mails.
EOF
chmod +x /usr/local/bin/quota-warning.sh

et on redémarre Dovecot :

service dovecot restart

RSPAMD

On commence par installer redis-server :

apt install redis-server

Puis on installe Rspamd

apt install software-properties-common lsb-release -y
wget -O- https://rspamd.com/apt-stable/gpg.key | apt-key add -
echo "deb http://rspamd.com/apt-stable/ $(lsb_release -cs) main" > /etc/apt/sources.list.d/rspamd.list
apt update
apt install rspamd

Configurer Rspamd

echo 'bind_socket = "127.0.0.1:11333";' > /etc/rspamd/local.d/worker-normal.inc
cat > /etc/rspamd/local.d/worker-proxy.inc << EOF
bind_socket = "127.0.0.1:11332";
milter = yes;
timeout = 120s;
upstream "local" {
  default = yes;
  self_scan = yes;
}
EOF

Il faut créer un mot de passe ‘admin’ pour l’interface web de Rspamd :

rspamadm pw --encrypt -p 6VhhmngTF5ix

Notez bien la clé qui va s’afficher. Elle ressemblera à ça :

$2$t6psjojndbjp1wtnb3rha3ohdiwxzye3$gxpbrjf7uyqbhdxqs33iz8rxytgm449x6zw1pnasruqq8qn3p98y
echo 'password = "$2$t6psjojndbjp1wtnb3rha3ohdiwxzye3$gxpbrjf7uyqbhdxqs33iz8rxytgm449x6zw1pnasruqq8qn3p98y"' > /etc/rspamd/local.d/worker-controller.inc

Puis on continue la configuration :

cat > /etc/rspamd/local.d/classifier-bayes.conf << EOF
servers = "127.0.0.1";
backend = "redis";
EOF

cat > /etc/rspamd/local.d/milter_headers.conf << EOF
use = ["x-spamd-bar", "x-spam-level", "authentication-results"];
EOF

On rédémarre Rspamd :

systemctl restart rspamd

Configurer Nginx pour l’interface web de Rspamd

nano /etc/nginx/conf.d/rspamd.cinay.eu.conf
	##
	# Virtual Host rspamd.cinay.eu (Rspamd)
	##

	server {
	    listen 80;
	    listen [::]:80;
	
	    ## redirect http to https ##
	    server_name rspamd.cinay.eu;
	    return  301 https://$server_name$request_uri;
	}
	
	server {
	    listen 443 ssl http2;
	    listen [::]:443 ssl http2;
	    server_name rspamd.cinay.eu;
	
	    include ssl_dh_headers_ocsp;
	
	    location / {
              proxy_pass http://127.0.0.1:11334/;
              proxy_set_header Host $host;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	    }
	
	}

On va terminer la configuration de Postfix on intégrant les paramètres pour Rspamd

postconf -e "milter_protocol = 6"
postconf -e "milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}"
postconf -e "milter_default_action = accept"
postconf -e "smtpd_milters = inet:127.0.0.1:11332"
postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"

… et on redémarre Postfix :

systemctl restart postfix

Dovecot ,terminer la configuration

On termine la config de Dovecot en intégrant le module Sieve pour filtrer les mails

apt install dovecot-sieve dovecot-managesieved
nano /etc/dovecot/conf.d/20-lmtp.conf # ajout  sieve
protocol lmtp {
  # Space separated list of plugins to load (default is global mail_plugins).
  postmaster_address = postmaster@cinay.eu
  mail_plugins = $mail_plugins sieve
}
nano /etc/dovecot/conf.d/20-imap.conf # ajout imap_sieve
...
protocol imap {
...
  mail_plugins = $mail_plugins imap_quota imap_sieve
...
}
...
nano /etc/dovecot/conf.d/20-managesieve.conf
...
service managesieve-login {
  inet_listener sieve {
    port = 4190
  }
}
..
service managesieve {
  # Max. number of ManageSieve processes (connections)
  process_limit = 1024
}
...
nano /etc/dovecot/conf.d/90-sieve.conf
plugin {
...  
# sieve = file:~/sieve;active=~/.dovecot.sieve  
  sieve_plugins = sieve_imapsieve sieve_extprograms
  sieve_before = /var/mail/vmail/sieve/global/spam-global.sieve
  sieve = file:/var/mail/vmail/sieve/%d/%n/scripts;active=/var/mail/vmail/sieve/%d/%n/active-script.sieve
  imapsieve_mailbox1_name = Spam
  imapsieve_mailbox1_causes = COPY
  imapsieve_mailbox1_before = file:/var/mail/vmail/sieve/global/report-spam.sieve
  imapsieve_mailbox2_name = *
  imapsieve_mailbox2_from = Spam
  imapsieve_mailbox2_causes = COPY
  imapsieve_mailbox2_before = file:/var/mail/vmail/sieve/global/report-ham.sieve
  sieve_pipe_bin_dir = /usr/bin
  sieve_global_extensions = +vnd.dovecot.pipe
....  
}

Créer un répertoire qui va accueillir les scripts Sieve:

mkdir -p /var/mail/vmail/sieve/global
cat > /var/mail/vmail/sieve/global/spam-global.sieve << EOF
require ["fileinto","mailbox"];

if anyof(
 header :contains ["X-Spam-Flag"] "YES",  
 header :contains ["X-Spam"] "Yes",  
 header :contains ["Subject"] "*** SPAM ***"  
)  
{
fileinto :create "Spam";  
stop;  
}
EOF

cat > /var/mail/vmail/sieve/global/report-spam.sieve << EOF
require ["vnd.dovecot.pipe", "copy", "imapsieve"];
pipe :copy "rspamc" ["learn_spam"];
EOF

cat > /var/mail/vmail/sieve/global/report-ham.sieve << EOF
require ["vnd.dovecot.pipe", "copy", "imapsieve"];
pipe :copy "rspamc" ["learn_ham"];
EOF

… et on redémarre Dovecot :

systemctl restart dovecot

Il faut maintenant compiler les scripts Sieve et appliquer les bons droits :

sievec /var/mail/vmail/sieve/global/spam-global.sieve
sievec /var/mail/vmail/sieve/global/report-spam.sieve
sievec /var/mail/vmail/sieve/global/report-ham.sieve
chown -R vmail: /var/mail/vmail/sieve/

DKIM

OpenDkim

Dkim
DomainKeys Identified Mail (DKIM) est une méthode d’authentification par courrier électronique qui ajoute une signature cryptographique aux en-têtes des messages sortants. Il permet au destinataire de vérifier qu’un courrier électronique prétendant provenir d’un domaine spécifique a bien été autorisé par le propriétaire de ce domaine. Le but principal de cette opération est d’empêcher les messages électroniques falsifiés.

On peut avoir différentes clés DKIM pour tous les domaines et même plusieurs clés pour un seul domaine, mais pour simplifier cet article, nous allons utiliser une seule clé DKIM qui pourra ultérieurement être utilisée pour tous les nouveaux domaines.

Créer un répertoire afin d’accueillir les clés Dkim

mkdir /var/lib/rspamd/dkim/

Et on va créer la clé Dkim :

rspamadm dkim_keygen -b 2048 -s mail -k /var/lib/rspamd/dkim/mail.key > /var/lib/rspamd/dkim/mail.pub

La clé publique est dans le fichier /var/lib/rspamd/dkim/mail.pub

Dans cet exemple, on utilise “mail” comme sélecteur Dkim.
On applique les bonnes permissions :

chown -R _rspamd: /var/lib/rspamd/dkim
chmod 440 /var/lib/rspamd/dkim/*

On va ensuite “dire” à Rspamd de regarder au bon endroit pour les clés Dkim :

nano /etc/rspamd/local.d/dkim_signing.conf
selector = "mail";
path = "/var/lib/rspamd/dkim/$selector.key";
allow_username_mismatch = true;

Rspamd prend également en charge la signature ARC (Authenticated Received Chain). Rspamd utilise le module dkim pour traiter les signatures ARC afin que nous puissions simplement copier la configuration précédente :

cp /etc/rspamd/local.d/dkim_signing.conf /etc/rspamd/local.d/arc.conf

… et on redémarre Rspamd :

systemctl restart rspamd

DNS OVH

Vous devez aussi configurer vos DNS.

$TTL 3600
@	IN SOA dns100.ovh.net. tech.ovh.net. (2020020719 86400 3600 3600000 300)
                       IN NS     dns100.ovh.net.
                       IN NS     ns100.ovh.net.
                       IN MX     10 cinay.eu.
                       IN A      54.37.13.57
                       IN AAAA   2001:41d0:401:3200:0:0:0:d48
                   600 IN TXT    "v=spf1 a mx ip4:54.37.13.57 ip6:2001:41d0:401:3200:0:0:0:d48 ~all"
*                      IN CNAME  cinay.eu.
_dmarc                 IN TXT    "v=DMARC1;p=quarantine;sp=quarantine;rua=mailto:postmaster@cinay.eu;ruf=mailto:postmaster@cinay.eu;pct=100;adkim=r;aspf=r;fo=1;ri=86400;rf=afrf"
mail._domainkey        IN TXT    ( "k=rsa;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQR5AH6/lmEJusr3v8ja7kBFp/+z0dBKu7e01z/H0RppeQpxy1nW7AaE9cXqmY0srhyFJgOJ4VgcZG3EFr0jqMJLiMvmRTzFP9fjH6z2iswFGJlyD1M8J8KiVge5V4wCxDCPI3E6wZOH4CvMMcttfhFGhPwTm8bvKdagKmk7lGMr42cIR1GLkDQOYaoETkDfcYlc0r" "rZJzwwmJsCUfEaq8ONMmdwgDEYRAaCsS/4cLwNdm61epGOKO+hWMR+kYChtxeT/1fzySUY1y9xi0kRuF2ES+j+clZMybVy53fBr2Bu11VGxPB+DKjyAIQvmyz8mx73WICb1wmvnOn/WDsFxwIDAQAB;" )

Suite aux erreurs d’authentifications (hors domaine)

$TTL 3600
@	IN SOA dns100.ovh.net. tech.ovh.net. (2020020719 86400 3600 3600000 300)
                       IN NS     dns100.ovh.net.
                       IN NS     ns100.ovh.net.
                       IN MX     10 cinay.eu.
                       IN A      54.37.13.57
                       IN AAAA   2001:41d0:401:3200:0:0:0:d48
                   600 IN TXT    "v=spf1 mx ip4:54.37.13.57 ip6:2001:41d0:401:3200:0:0:0:d48 -all"
*                      IN CNAME  cinay.eu.
_dmarc                 IN TXT    "v=DMARC1;p=none;"
mail._domainkey        IN TXT    ("v=DKIM1;h=sha256;k=rsa;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQR5AH6/lmEJusr3v8ja7kBFp/+z0dBKu7e01z/H0RppeQpxy1nW7AaE9cXqmY0srhyFJgOJ4VgcZG3EFr0jqMJLiMvmRTzFP9fjH6z2iswFGJlyD1M8J8KiVge5V4wCxDCPI3E6wZOH4CvMMcttfhFGhPwTm8bvKdagKmk7lGMr42cIR1GLkDQOYaoETkDfcYlc0r" "rZJzwwmJsCUfEaq8ONMmdwgDEYRAaCsS/4cLwNdm61epGOKO+hWMR+kYChtxeT/1fzySUY1y9xi0kRuF2ES+j+clZMybVy53fBr2Bu11VGxPB+DKjyAIQvmyz8mx73WICb1wmvnOn/WDsFxwIDAQAB;" )

Modifier le parefeu

Ajouter au fichier le script /sbin/iptables-firewall.sh

sudo nano /sbin/iptables-firewall.sh
# Postfix SMTP, SMTPS, SUBMISSION
iptables -t filter -A INPUT -p tcp --dport 25 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 25 -j ACCEPT
iptables -t filter -A INPUT -p tcp --dport 465 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 465 -j ACCEPT
iptables -t filter -A INPUT -p tcp --dport 587 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 587 -j ACCEPT
# ImapS
iptables -t filter -A INPUT -p tcp --dport 993 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 993 -j ACCEPT

Relancer le service iptables

sudo systemctl restart iptables-firewall

Reste à configurer les noms de domaines et les boites mail dans Postfixadmin : https://pfa.cinay.eu

RAINLOOP WEBMAIL

webmail rainloop

On télécharge Rainloop :

mkdir rainloop
cd rainloop
curl -s http://repository.rainloop.net/installer.php | php
cd ..
sudo mv rainloop /var/www/

Créer un utilisateur système (-s) sans home (-M) id défini (990) rainloop

sudo useradd -M -u 990  -r -s /bin/false -c "User rainloop" rainloop
sudo chown rainloop:rainloop /var/www/rainloop/ -R

Configuration php rainloop.conf

sudo nano /etc/php/7.3/fpm/pool.d/rainloop.conf
[rainloop]
user = rainloop
group = rainloop
listen = /run/php/php7.3-fpm-rainloop.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
request_terminate_timeout = 1d
chdir = /var/www/rainloop

php_value[upload_max_filesize] = 10G
php_value[post_max_size] = 10G
php_value[mail.add_x_header] = Off

On crée le fichier Nginx pour Rainloop webmail :

sudo nano /etc/nginx/conf.d/webmail.cinay.eu.conf

	##
	# Virtual Host pfa.cinay.eu
	##

	server {
	    listen 80;
	    listen [::]:80;
	
	    ## redirect http to https ##
	    server_name webmail.cinay.eu;
	    return  301 https://$server_name$request_uri;
	}
	
	server {
	    listen 443 ssl http2;
	    listen [::]:443 ssl http2;
	    server_name webmail.cinay.eu;

	    include ssl_dh_headers_ocsp;

	    root /var/www/rainloop;
	    client_max_body_size 100M;
	    index index.php;
	
	   location / {      
	     try_files $uri $uri/ /index.php?$query_string;   
 	  }   
	        location ~ \.php$ {
	           fastcgi_split_path_info ^(.+\.php)(/.+)$;
		   if (!-f $document_root$fastcgi_script_name) {return 404;}
	           fastcgi_pass unix:/run/php/php7.3-fpm-rainloop.sock;   # PHP7.3
	           fastcgi_index index.php;
	           include fastcgi_params;
	    	   #fastcgi_param SCRIPT_FILENAME $request_filename;
		   fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	        }
	  location ^~ /data {   
   		deny all;       
	  }    
	

	    access_log /var/log/nginx/webmail.cinay.eu-access.log;
	    error_log /var/log/nginx/webmail.cinay.eu-error.log;
	}

Vérifier et relancer php et nginx

nginx -t
systemctl status php7.3-fpm
systemctl restart nginx

Une fois tous les domaines et les boites mail configurées dans Postfixadmin, on va pouvoir se connecter sur l’interface d’admin de Rainloop à cette adresse http://webmail.cinay.eu/?admin pour la configuration.(login par défaut “admin” et mot de passe “12345”)

Une fois connecté à l’admin – Onglet Domaine, Ajouter un domaine>

Domaine et IMAP/SMTP
cinay.eu
IMAP
Serveur : cinay.eu
Sécurité : SSL/TLS
Port : 993

SMTP
Serveur : cinay.eu
Sécurité : STARTTLS
Port : 587

Cliquez sur TEST, en bas à gauche de la fenêtre. Si TEST devient vert, la config est OK.

SIEVE
Cliquez sur configuration sieve (beta)
Cochez : Autoriser les scripts Sieve ET Autoriser les scripts personnels

SIEVE
Serveur : cinay.eu
Sécurité : STARTTLS
Port : 4190

SMTP
Serveur : cinay.eu
Sécurité : STARTTLS
Port : 587


Cliquez enfin sur Ajouter.

Effectuer cette configuration sur chaque domaine utilisé !

Pour activer l’auto learn (apprentissage) de Rspamd

sudo nano /etc/rspamd/override.d/classifier-bayes.conf
autolearn = true;

Redémarrer Rspamd

systemctl restart rspamd

Fail2ban

Fail2ban

Fail2ban lit des fichiers de log et bannit les adresses IP qui ont obtenu un trop grand nombre d’échecs lors de l’authentification. Il met à jour les règles du pare-feu pour rejeter cette adresse IP. Ces règles peuvent êtres défines par l’utilisateur.

Les commandes sont exécutées en mode su sudo

Installation

apt install fail2ban

fail2ban.conf : Rien à faire dans ce fichier, vous pouvez laisser les options par défaut

Copier la configuration par défaut afin qu’elle ne soit pas supprimée en cas de mise à jour.

cp /etc/fail2ban/jail.conf  /etc/fail2ban/jail.local

Ce fichier est beaucoup plus intéressant, il contient tous les services à monitorer, et vous allez le découvrir, fail2ban ne se limite pas à SSH…

nano /etc/fail2ban/jail.local

Tous les commentaires ont été supprimés pour allèger le fichier.
Les commentaires sont visibles dans le fichier original jail.conf

[INCLUDES]

before = paths-debian.conf

[DEFAULT]
# "bantime" is the number of seconds that a host is banned.
bantime  = 10m

# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime  = 10m

# "maxretry" is the number of failures before a host get banned.
maxretry = 5

# "backend" specifies the backend used to get files modification.
# auto:      will try to use the following backends, in order:
#              pyinotify, gamin, polling.
backend = auto

# "usedns" specifies if jails should trust hostnames in logs,
#   warn when DNS lookups are performed, or ignore all hostnames in logs
usedns = warn

# "logencoding" specifies the encoding of the log files handled by the jail
#   auto:   will use the system locale setting
logencoding = auto

# "enabled" enables the jails.
#  By default all jails are disabled, and it should stay this way.
#  Enable only relevant to your setup jails in your .local or jail.d/*.conf
#
# true:  jail will be enabled and log files will get monitored for changes
# false: jail is not enabled
enabled = false


# "mode" defines the mode of the filter (see corresponding filter implementation for more info).
mode = normal

# "filter" defines the filter to use by the jail.
#  By default jails have names matching their filter name
#
filter = %(__name__)s[mode=%(mode)s]


#
# ACTIONS
#

# Some options used for actions

# Destination email address used solely for the interpolations in
# jail.{conf,local,d/*} configuration files.
destemail = root@localhost

# Sender email address used solely for some actions
sender = root@<fq-hostname>

# E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the
# mailing. Change mta configuration parameter to mail if you want to
# revert to conventional 'mail'.
mta = mail

# Default protocol
protocol = tcp


# Ports to be banned
# Usually should be overridden in a particular jail
port = 0:65535

# Format of user-agent https://tools.ietf.org/html/rfc7231#section-5.5.3
fail2ban_agent = Fail2Ban/%(fail2ban_version)s

#
# Action shortcuts. To be used to define action parameter

# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
banaction_allports = iptables-allports

# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]

# ban & send an e-mail with whois report to the destemail.
action_mw = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
            %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
             %(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]

# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
#
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
# to the destemail.
action_xarf = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
             xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath=%(logpath)s, port="%(port)s"]

# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
# to the destemail.
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
                %(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s"]

# Report block via blocklist.de fail2ban reporting service API
# 
# See the IMPORTANT note in action.d/blocklist_de.conf for when to use this action.
# Specify expected parameters in file action.d/blocklist_de.local or if the interpolation
# `action_blocklist_de` used for the action, set value of `blocklist_de_apikey`
# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in 
# corresponding jail.d/my-jail.local file).
#
action_blocklist_de  = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]

# Report ban via badips.com, and use as blacklist
#
# See BadIPsAction docstring in config/action.d/badips.py for
# documentation for this action.
#
# NOTE: This action relies on banaction being present on start and therefore
# should be last action defined for a jail.
#
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
#
# Report ban via badips.com (uses action.d/badips.conf for reporting only)
#
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]

# Report ban via abuseipdb.com.
#
# See action.d/abuseipdb.conf for usage example and details.
#
action_abuseipdb = abuseipdb

# Choose default action.  To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g.  action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s


#
# JAILS
#

#
# SSH servers
#

[sshd]

# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode   = normal
enabled = true
port    = 55034
logpath = %(sshd_log)s
backend = %(sshd_backend)s

[nginx-http-auth]

enabled = true
port    = http,https
logpath = %(nginx_error_log)s

[nginx-botsearch]

enabled = true
port     = http,https
logpath  = %(nginx_error_log)s
maxretry = 2


# Ban attackers that try to use PHP's URL-fopen() functionality
# through GET/POST variables. - Experimental, with more than a year
# of usage in production environments.

[php-url-fopen]

enabled = true
port    = http,https
logpath = %(nginx_access_log)s


#
# Mail servers
#

[postfix]
# To use another modes set filter parameter "mode" in jail.local:
enabled = true
mode    = more
port    = smtp,465,submission
logpath = %(postfix_log)s
backend = %(postfix_backend)s

# dovecot defaults to logging to the mail syslog facility
# but can be set by syslog_facility in the dovecot configuration.
[dovecot]

enabled = true
port    = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s


[sieve]

enabled = true
port   = smtp,465,submission
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s


[phpmyadmin-syslog]

port    = http,https
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s

Relancer fail2ban

sudo systemctl restart fail2ban

Le fichier log /var/log/fail2ban.log

[...]
2020-02-10 11:06:01,841 fail2ban.filter         [7631]: INFO    Added logfile: '/var/log/mail.log' (pos = 0, hash = c0b5f515f663f8356553dd40fa2995db4329de94)
2020-02-10 11:06:01,842 fail2ban.filter         [7631]: INFO      encoding: UTF-8
2020-02-10 11:06:01,843 fail2ban.filter         [7631]: INFO      maxRetry: 5
2020-02-10 11:06:01,843 fail2ban.filter         [7631]: INFO      findtime: 600
2020-02-10 11:06:01,843 fail2ban.actions        [7631]: INFO      banTime: 600
2020-02-10 11:06:01,845 fail2ban.jail           [7631]: INFO    Jail 'sshd' started
2020-02-10 11:06:01,847 fail2ban.jail           [7631]: INFO    Jail 'nginx-http-auth' started
2020-02-10 11:06:01,848 fail2ban.jail           [7631]: INFO    Jail 'nginx-botsearch' started
2020-02-10 11:06:01,849 fail2ban.jail           [7631]: INFO    Jail 'php-url-fopen' started
2020-02-10 11:06:01,850 fail2ban.jail           [7631]: INFO    Jail 'postfix' started
2020-02-10 11:06:01,851 fail2ban.jail           [7631]: INFO    Jail 'dovecot' started
2020-02-10 11:06:01,852 fail2ban.jail           [7631]: INFO    Jail 'sieve' started

Modifications

Cryptage SSL

Maintenant que l’authentification est mise en place, assurons-nous que le processus d’authentification est sécurisé. Pour ce faire, vous devrez crypter toutes les tentatives d’authentification avec SSL ou STARTTLS. Pour plus d’informations, consultez l’article du wiki de Dovecot sur le cryptage SSL.

Ouvrez le fichier /etc/dovecot/conf.d/10-ssl.conf pour l’éditer, puis réglez ssl à la valeur require

ssl = required

Vérifiez également dans /etc/dovecot/conf.d/10-ssl.conf les chemins d’accès au certificat et à la clé SSL. Ils doivent être définis par défaut sur le certificat et la clé de Dovecot. Si c’est ce que vous utilisez, laissez ces paramètres tels quels. Sinon, mettez à jour les chemins d’accès au certificat et à la clé que vous souhaitez utiliser.

ssl_cert = </etc/ssl/private/cinay.eu-fullchain.pem
ssl_key = </etc/ssl/private/cinay.eu-key.pem

Désactiver l’authentification plain-text en clair dans /etc/dovecot/conf.d/10-auth.conf

disable_plaintext_auth = yes

Désactivez les ports non chiffrés pour IMAP et POP3 afin que le serveur n’accepte pas les connexions non chiffrées. Dans /etc/dovecot/conf.d/10-master.conf

nano /etc/dovecot/conf.d/10-master.conf  
    service imap-login {
       inet_listener imap {
         port = 0
       }
      inet_listener imaps {
        #port = 993
        #ssl = yes
      }
     ...
     }

     service pop3-login {
       inet_listener pop3 {
         port = 0
       }
      inet_listener pop3s {
        #port = 995
        #ssl = yes
      }
     ...
     }

Laissez les ports imaps et pop3s tranquilles (ils sont commentés). Leurs paramètres par défaut sont corrects ; vous pourrez utiliser le 993 pour un IMAP sécurisé et le 995 pour un POP3 sécurisé.

Relancer dovecot

sudo service dovecot restart

SMTP

Maintenant que vous avez mis en place une authentification sécurisée, vous devez configurer le SMTP. Actuellement, Postfix ne relaie les courriels que s’ils sont adressés à un domaine sur le serveur ou s’ils sont envoyés par des utilisateurs du système, ce qui est suffisant pour le courrier entrant. Pour le courrier sortant, en revanche, vous voudrez assouplir les restrictions de relais afin que les utilisateurs authentifiés puissent envoyer des courriels de n’importe où.Fichier /etc/postfix/main.cf

cp /etc/postfix/main.cf /etc/postfix/main.cf.orig  
nano /etc/postfix/main.cf 
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination

Note : La ligne smtpd_recipient_restrictions énumère les critères que Postfix utilise pour décider quels e-mails il peut relayer.
permit_sasl_authenticated permet aux utilisateurs authentifiés d’envoyer du courrier. Il doit être listé en premier.
permit_mynetworks, qui permet aux utilisateurs qui sont déjà connectés au serveur d’envoyer du courrier. reject_unauth_destination empêche votre serveur d’envoyer du courrier pour des domaines pour lesquels il n’est pas configuré. Ne supprimez jamais ce dernier paramètre !. En gros, cela signifie que les utilisateurs authentifiés et les utilisateurs locaux sont toujours autorisés à envoyer du courrier n’importe où. Les utilisateurs non authentifiés et non locaux sont autorisés à envoyer du courrier uniquement aux domaines dont ce serveur est responsable.
Ces restrictions empêchent votre serveur d’être utilisé comme un relais ouvert qui peut envoyer du courrier indésirable de n’importe qui vers n’importe où.

Vous voudrez également forcer l’authentification sortante à être cryptée. Toujours dans /etc/postfix/main.cf

smtpd_tls_cert_file = /etc/ssl/private/cinay.eu-fullchain.pem
smtpd_tls_key_file = /etc/ssl/private/cinay.eu-key.pem
smtpd_use_tls=yes
smtpd_tls_auth_only = yes

Note : Tout d’abord, vous allez dire à Postfix d’utiliser le certificat et la clé SSL de Dovecot, car certains clients de messagerie “s’étoufferont” si les certificats des serveurs entrants et sortants ne correspondent pas.
Ensuite, vous direz à Postfix d’utiliser (uniquement) le cryptage TLS. Cela signifie que les utilisateurs peuvent se connecter sur le port standard (25), mais avant d’être autorisés à envoyer des informations d’authentification, ils doivent établir une connexion cryptée.

Localisez et décommentez les deux lignes commençant par soumission et smtps. Cela vous permettra d’envoyer du courrier en toute sécurité sur les ports 587 et 465, en plus du port 25 (qui est également sécurisé grâce à notre configuration SSL).Fichier /etc/postfix/master.cf

cp /etc/postfix/master.cf /etc/postfix/master.cf.orig  
nano /etc/postfix/master.cf
#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       -       -       -       smtpd
#smtp      inet  n       -       -       -       1       postscreen
#smtpd     pass  -       -       -       -       -       smtpd
#dnsblog   unix  -       -       -       -       0       dnsblog
#tlsproxy  unix  -       -       -       -       0       tlsproxy
submission inet n       -       -       -       -       smtpd
#  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
#  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       -       -       -       smtpd
#  -o syslog_name=postfix/smtps
#  -o smtpd_tls_wrappermode=yes
#  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING

Relancer postfix

sudo service postfix restart

Analyse , débogage

Dovecot - Débogage de l’authentification

La chose la plus importante à faire est de définir auth_debug = yes , et de préférence également auth_debug_passwords = yes . Après cela, vous verrez dans les journaux exactement ce que fait dovecot-auth, et cela devrait vous aider à résoudre le problème.

Mécanisme SASL PLAIN
Avec IMAP et POP3, il est facile de se connecter manuellement à l’aide de la commande LOGIN d’IMAP ou des commandes USER et PASS de POP3 (voir TestInstallation et TestPop3Installation pour plus de détails), mais avec SMTP AUTH, vous devrez utiliser le mécanisme d’authentification PLAIN, qui vous obligera à créer un Chaîne encodée en base64 au format correct. L’authentification PLAIN est également utilisée en interne par IMAP et POP3 pour s’authentifier auprès de dovecot-auth, vous la voyez donc dans les journaux de débogage.

Le format d’authentification du mécanisme PLAIN est: <ID d'autorisation> NUL <ID d'authentification> NUL <mot de passe>. L’ID d’autorisation est le nom d’utilisateur auquel vous souhaitez vous connecter et l’ID d’authentification est le nom d’utilisateur dont vous donnez le mot de passe. Si vous ne prévoyez pas d’effectuer une connexion utilisateur principale , vous pouvez soit définir ces deux champs sur le même nom d’utilisateur, soit laisser l’ID d’autorisation vide.

Encodage base64

printf 'username\0username\0password' |base64
dXNlcm5hbWUAdXNlcm5hbWUAcGFzc3dvcmQ=

Activer les logs dovecot postfix

Le journal de courrier par défaut peut ne pas contenir toutes les informations dont vous avez besoin. Dans ce cas, l’étape suivante consiste à activer l’enregistrement verbeux pour Postfix et Dovecot, et à séparer les journaux de Postfix et Dovecot en deux fichiers distincts afin qu’ils soient plus faciles à trier. Le journal de Postfix documentera les messages qui sont relayés vers ou depuis des serveurs extérieurs, et le journal de Dovecot enregistrera les tentatives d’autorisation.

Suivez ces instructions pour activer l’enregistrement verbeux pour Dovecot et changez l’emplacement du journal en /var/log/dovecot.log, ouvrir le fichier /etc/dovecot/conf.d/10-logging.conf pour l’éditer

nano /etc/dovecot/conf.d/10-logging.conf
log_path = /var/log/dovecot.log
auth_verbose = yes
auth_debug = yes
auth_debug_passwords = yes

Redémarrer dovecot

service dovecot restart

Le journal dovecot affichera désormais plus d’informations sur les tentatives d’autorisation et les connexions à la boîte de réception. Vous pouvez consulter le nouveau journal à l’adresse /var/log/dovecot.log.

N’oubliez pas de désactiver la journalisation verbeuse lorsque vous avez terminé le dépannage afin que votre serveur ne se remplisse pas de journaux.

Suivez ces instructions pour permettre l’enregistrement verbeux de Postfix, ouvrir le fichier /etc/postfix/master.cf

nano /etc/postfix/master.cf

Ajoutez un -v à la ligne smtp pour permettre une journalisation détaillée :

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
smtp      inet  n       -       -       -       -       smtpd -v

Redémarrer Postfix

service postfix restart

Le journal de Postfix affichera désormais plus d’informations sur les messages qui proviennent ou vont vers des serveurs extérieurs. Vous pouvez toujours consulter le journal à l’adresse /var/log/mail.log.

N’oubliez pas de désactiver la journalisation

Dovecot - Résoudre problème authentification avec “Mutt”

On ne peut pas envoyer de message avec mutt

Mar 04 06:25:34 auth-worker(7442): Debug: Module loaded: /usr/lib/dovecot/modules/auth/lib20_auth_var_expand_crypt.so
Mar 04 06:25:34 auth-worker(7442): Debug: Module loaded: /usr/lib/dovecot/modules/auth/libdriver_mysql.so
Mar 04 06:25:34 auth-worker(7442): Debug: sql(yann,193.32.126.219): query: SELECT username AS user,password FROM mailbox   WHERE username = 'yann' AND active='1'
Mar 04 06:25:34 auth-worker(7442): Info: sql(yann,193.32.126.219): unknown user
Mar 04 06:25:36 auth: Debug: client passdb out: FAIL	1	user=yann

Le problème est lié à l’utilisateur qui est fourni par mutt sans le domaine
Il faut pouvoir identifier sans le domaine…

Dovecot - Authentifier sans la partie domaine de l’adresse électronique
Avec les paramètres par défaut, le client doit utiliser l’adresse électronique complète comme nom d’utilisateur pour la connexion POP3/IMAP/SMTP/webmail. Si vous souhaitez vous connecter sans la partie nom de domaine dans l’adresse électronique,ouvrir le fichier de configuration de Dovecot /etc/dovecot/dovecot.conf (Linux/OpenBSD) ou /usr/local/etc/dovecot/dovecot.conf (FreeBSD), trouvez le paramètre auth_default_realm, définissez le nom de domaine que vous souhaitez autoriser à l’utilisateur à se connecter sans la partie nom de domaine dans l’adresse électronique.

auth_default_realm = cinay.eu

Le redémarrage dovecot est obligatoire. Après le redémarrage de Dovecot, l’utilisateur se connectera sous john.smith et sera réécrit par Dovecot sur john.smith@cinay.eu
Cela fonctionne pour les services POP3/IMAP/SMTP.

Le problème est corrigé

Mar 04 07:59:48 imap-login: Info: Login: user=<yann@cinay.eu>, method=PLAIN, rip=193.32.126.219, lip=54.37.13.57, mpid=10487, TLS, session=<xYVQ9wGg4LfBIH7b>
Mar 04 08:00:04 auth: Debug: auth client connected (pid=0)
Mar 04 08:00:05 auth: Debug: client in: AUTH	1	PLAIN	service=smtp	nologin	lip=54.37.13.57	rip=193.32.126.219	secured	resp=XNlcmz5hbcWUAdXNl5hbcm5hbAdXN3dvcmQ== (previous base64 data may contain sensitive data)
Mar 04 08:00:05 auth-worker(10484): Debug: sql(yann@cinay.eu,193.32.126.219): query: SELECT username AS user,password FROM mailbox   WHERE username = 'yann@cinay.eu' AND active='1'
Mar 04 08:00:05 auth: Debug: client passdb out: OK	1	user=yann@cinay.eu		original_user=yann

Résoudre problème création compte de messagerie sur “Thunderbird”

Impossible de créer un compte sur thunderbird avec erreur suivante

Mar  3 13:18:16 cinay dovecot: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=193.32.126.231, lip=54.37.13.57, TLS handshaking: SSL_accept() failed: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate: SSL alert number 42, session=<8U1pTPKfLsXBIH7n>
Mar  3 13:18:16 cinay postfix/submission/smtpd[3835]: lost connection after CONNECT from unknown[193.32.126.231]
Mar  3 13:18:16 cinay postfix/submission/smtpd[3835]: disconnect from unknown[193.32.126.231] commands=0/0

Cela est lié à OCSP , il faut modifier le paramétrage avancé de thunderbird
Edition → Préférences → Avancé Général → Editeur de configuration… Rechercher ocsp , adapter le paramétrage à ce qui suit

security.ocsp.enabled: 1
security.ocsp.require: false
security.ssl.enable_ocsp_must_staple: false
security.ssl.enable_ocsp_stapling: true


Puis créer le compte de messagerie sur thunderbird

Tester un serveur de messagerie via OpenSSL

Prérequis:

  • Un compte de messagerie avec un utilisateur enregistré
  • Un codage base64 de l’utilisateur mot de passe de la forme (\0 → NUL): printf 'username\0username\0password' |base64

Test

openssl s_client -starttls smtp -host cinay.eu -port 587 -quiet
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = cinay.eu
verify return:1
250 CHUNKING
EHLO localhost
250-cinay.eu
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING
AUTH PLAIN <utilisateur mot de passe Base 64>
235 2.7.0 Authentication successful
MAIL FROM:<yann@cinay.eu>
250 2.1.0 Ok
RCPT TO:<yannick@cinay.xyz>
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
Test 2 via openssl depuis PC...
.
250 2.0.0 Ok: queued as DD46242FB4
QUIT
221 2.0.0 Bye

PostfixAdmin

Problème d’accès en administration : “Invalid token” On recherche la provenance

root@cinay:/home/wguser# find /var/www/postfixadmin/ -name "*.php" -exec grep -Hn "Invalid token" {} \;
/var/www/postfixadmin/public/sendmail.php:42:        die('Invalid token!');
/var/www/postfixadmin/public/editactive.php:23:    die('Invalid token!');
/var/www/postfixadmin/public/edit.php:99:        die('Invalid token!');
/var/www/postfixadmin/public/broadcast-message.php:48:        die('Invalid token!');
/var/www/postfixadmin/public/list.php:20:# if (safeget('token') != $_SESSION['PFA_token']) die('Invalid token!');
/var/www/postfixadmin/public/users/password.php:40:        die('Invalid token!');
/var/www/postfixadmin/public/users/edit-alias.php:62:        die('Invalid token!');
/var/www/postfixadmin/public/users/login.php:37:        die('Invalid token!');
/var/www/postfixadmin/public/delete.php:23:    die('Invalid token!');
/var/www/postfixadmin/public/login.php:41:        die('Invalid token!');
/var/www/postfixadmin/public/vacation.php:110:        die('Invalid token!');

Au login : /var/www/postfixadmin/public/login.php