check

------

 we check

# id vmail uid=150(vmail) gid=8(mail) groups=8(mail),121(dovecot)

Sieve

cat /etc/dovecot/conf.d/90-sieve.conf | grep -v "#" | grep -v "^ *$" plugin {  sieve_dir = ~/sieve  sieve = ~/sieve/dovecot.sieve  sieve_global_dir = /var/vmail/sieve  sieve_before = /var/vmail/sieve/dovecot.sieve  sieve_max_redirects = 30  sieve_vacation_send_from_recipient = yes }

Activate sieve for lmtp protocol

cat 10-director.conf | grep -v "^ *#" | grep -v "^ *$" service director {  unix_listener login/director {  }  fifo_listener login/proxy-notify {  }  unix_listener director-userdb {  }  inet_listener {  } } service imap-login { } service pop3-login { } protocol lmtp {  mail_plugins = $mail_plugins sieve }

And for protocol lda

cat 15-lda.conf | grep -v "^ *#" | grep -v "^ *$" postmaster_address = domain@oamis.net protocol lda {  mail_plugins = $mail_plugins sieve }

We create the master sieve file

cd /var/vmail/mkdir sievechown vmail:mail sieve/cd sieve/cat dovecot.sieve require ["fileinto"];

# rule:[Move Spam to Junk Folder] if header :is "X-Spam-Flag" "YES" {    fileinto "Junk"; } # rule:[Openmarc fails to Junk Folder] if header :contains "Authentication-Results" "OpenDmarc; dmarc=fail" {   fileinto "Junk"; }

chmod 500 dovecot.sievechown vmail:mail dovecot.sieve

SpamAssassin

spamassassin -V SpamAssassin version 3.4.2  running on Perl version 5.26.1

Download schema and create database

wget http://svn.apache.org/repos/asf/spamassassin/tags/spamassassin_release_3_4_2/sql/bayes_mysql.sqlmysql -p Enter password: Welcome to the MySQL monitor.  Commands end with ; or \g. Your MySQL connection id is 3267 Server version: 5.7.27-0ubuntu0.18.04.1-log (Ubuntu) Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create database sa_bayes; Query OK, 1 row affected (0.01 sec) mysql> use sa_bayes; Database changed mysql> source bayes_mysql.sql Query OK, 0 rows affected (0.09 sec) Query OK, 0 rows affected (0.02 sec) Query OK, 1 row affected (0.02 sec) Query OK, 0 rows affected (0.02 sec) Query OK, 0 rows affected (0.03 sec) Query OK, 0 rows affected (0.03 sec) mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON sa_bayes.* TO sa_user@localhost IDENTIFIED BY 'xxxxxxxxxxxxxxxxx'; Query OK, 0 rows affected, 1 warning (0.07 sec) mysql> flush privileges; Query OK, 0 rows affected (0.02 sec) mysql> quit Bye

Modify setup

cd /etc/spamassassin/  cat /etc/spamassassin/local.cf | grep -v "^#" | grep -v "^ *$" ifplugin Mail::SpamAssassin::Plugin::Shortcircuit endif # Mail::SpamAssassin::Plugin::Shortcircuit required_score      5.0 rewrite_header      subject 🚽⛔ report_safe         0 lock_method         flock use_bayes          1 bayes_auto_learn   1 bayes_auto_expire  1 bayes_store_module Mail::SpamAssassin::BayesStore::MySQL bayes_sql_dsn      DBI:mysql:sa_bayes:127.0.0.1:3306 bayes_sql_username sa_user bayes_sql_password xxxxxxxxxxxxxxxxx score DNS_FROM_AHBL_RHSBL 0 score URIBL_AB_SURBL 0 0.3306 0 0.3812 score URIBL_JP_SURBL 0 0.3360 0 0.4087 score URIBL_OB_SURBL 0 0.2617 0 0.3008 score URIBL_PH_SURBL 0 0.2240 0 0.2800 score URIBL_SBL 0 0.1094 0 0.1639 score URIBL_SC_SURBL 0 0.3600 0 0.4498 score URIBL_WS_SURBL 0 0.1533 0 0.2140 loadplugin Mail::SpamAssassin::Plugin::DKIM whitelist_from_dkim *@paypal.com whitelist_from_dkim *@linkedin.com whitelist_from_dkim *@twitter.com whitelist_from_dkim *@bounce.twitter.com ok_locales          all score RP_MATCHES_RCVD 0

Amavis, ClamAV, and SpamAssassin

add users to group of each other

adduser amavis clamav Adding user `amavis' to group `clamav' ... Adding user amavis to group clamav Done.

We check

id clamav uid=115(clamav) gid=123(clamav) groups=123(clamav),127(amavis) id amavis uid=119(amavis) gid=127(amavis) groups=127(amavis),123(clamav)

Enable amavis

Enable antivirus and spam check

cat /etc/amavis/conf.d/15-content_filter_mode |  grep -v "#" | grep -v "^$" use strict; @bypass_virus_checks_maps = (   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re); @bypass_spam_checks_maps = (   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

Enable spamassasin

We change the option ENABLE from 0 to 1 and CRON from 0 to 1 in file /etc/default/spamassassin

cat /etc/default/spamassassin |  grep -v "#" | grep -v "^$" ENABLED=1 OPTIONS="--create-prefs --max-children 5 --helper-home-dir" PIDFILE="/var/run/spamd.pid" CRON=1

Enable it.

systemctl enable spamassassin.service Synchronizing state of spamassassin.service with SysV init with /lib/systemd/systemd-sysv-install... Executing /lib/systemd/systemd-sysv-install enable spamassassin

Ensure mails through amavis are for local delivery

We let deliver spam mails

cat /etc/amavis/conf.d/50-user |  grep -v "^#" | grep -v "^$" use strict; $final_virus_destiny      = D_DISCARD;  # (data not lost, see virus quarantine) $final_banned_destiny     = D_BOUNCE;   # D_REJECT when front-end MTA $final_spam_destiny       = D_PASS; $final_bad_header_destiny = D_PASS;     # False-positive prone (for spam) $max_servers  = 3; $sa_tag_level_deflt  = -9999; @lookup_sql_dsn = (    ['DBI:mysql:database=mail;host=127.0.0.1;port=3306',     'postfix',     'postfixpassowrd']); $sql_select_policy = 'SELECT domain from domain WHERE CONCAT("@",domain) IN (%k)'; 1;  # ensure a defined return

Update clamav database

# freshclam Sun Aug 26 20:42:35 2018 -> ClamAV update process started at Sun Aug 26 20:42:35 2018 Sun Aug 26 20:42:38 2018 -> Downloading main.cvd [100%] Sun Aug 26 20:42:49 2018 -> main.cvd updated (version: 58, sigs: 4566249, f-level: 60, builder: sigmgr) Sun Aug 26 20:42:51 2018 -> Downloading daily.cvd [100%] Sun Aug 26 20:42:57 2018 -> daily.cvd updated (version: 24875, sigs: 2064192, f-level: 63, builder: neo) Sun Aug 26 20:42:57 2018 -> Downloading bytecode.cvd [100%] Sun Aug 26 20:42:58 2018 -> bytecode.cvd updated (version: 327, sigs: 91, f-level: 63, builder: neo) Sun Aug 26 20:43:03 2018 -> Database updated (6630532 signatures) from db.local.clamav.net (IP: 2400:cb00:2048:1::6810:bd8a) Sun Aug 26 20:43:03 2018 -> ^Clamd was NOT notified: Can't connect to clamd through /var/run/clamav/clamd.ctl: No such file or directory

Restart services

systemctl restart clamav-daemonsystemctl status clamav-daemon ● clamav-daemon.service - Clam AntiVirus userspace daemon   Loaded: loaded (/lib/systemd/system/clamav-daemon.service; enabled; vendor preset: enabled)  Drop-In: /etc/systemd/system/clamav-daemon.service.d           └─extend.conf   Active: active (running) since Sun 2018-08-26 20:44:08 CEST; 6s ago     Docs: man:clamd(8)           man:clamd.conf(5)           https://www.clamav.net/documents/  Process: 13261 ExecStartPre=/bin/chown clamav /run/clamav (code=exited, status=0/SUCCESS)  Process: 13256 ExecStartPre=/bin/mkdir /run/clamav (code=exited, status=0/SUCCESS) Main PID: 13264 (clamd)   CGroup: /system.slice/clamav-daemon.service           └─13264 /usr/sbin/clamd --foreground=true

Aug 26 20:44:08 rigel systemd[1]: Starting Clam AntiVirus userspace daemon... Aug 26 20:44:08 rigel systemd[1]: Started Clam AntiVirus userspace daemon.

systemctl restart amavissystemctl status amavis ● amavis.service - LSB: Starts amavisd-new mailfilter   Loaded: loaded (/etc/init.d/amavis; bad; vendor preset: enabled)   Active: active (running) since Sun 2018-08-26 20:45:21 CEST; 9s ago     Docs: man:systemd-sysv-generator(8)  Process: 13272 ExecStop=/etc/init.d/amavis stop (code=exited, status=0/SUCCESS)  Process: 13280 ExecStart=/etc/init.d/amavis start (code=exited, status=0/SUCCESS)   CGroup: /system.slice/amavis.service           ├─  635 /usr/sbin/amavisd-new (master           ├─13293 /usr/sbin/amavisd-new (master           ├─13295 /usr/sbin/amavisd-new (virgin child           ├─13296 /usr/sbin/amavisd-new (virgin child           ├─13297 /usr/sbin/amavisd-new (virgin child           ├─37445 /usr/sbin/amavisd-new (master           ├─43440 /usr/sbin/amavisd-new (virgin child           ├─43464 /usr/sbin/amavisd-new (virgin child           ├─43577 /usr/sbin/amavisd-new (virgin child           └─43578 /usr/sbin/amavisd-new (virgin child Aug 26 20:45:21 rigel amavis[13293]: Found decoder for    .lha  at /usr/bin/7z Aug 26 20:45:21 rigel amavis[13293]: Found decoder for    .iso  at /usr/bin/7z Aug 26 20:45:21 rigel amavis[13293]: Found decoder for    .exe  at /usr/bin/unrar-free; /usr/bin/arj Aug 26 20:45:21 rigel amavis[13293]: No decoder for       .F Aug 26 20:45:21 rigel amavis[13293]: No decoder for       .lrz Aug 26 20:45:21 rigel amavis[13293]: No decoder for       .lz4 Aug 26 20:45:21 rigel amavis[13293]: Using primary internal av scanner code for ClamAV-clamd Aug 26 20:45:21 rigel amavis[13293]: Found secondary av scanner ClamAV-clamscan at /usr/bin/clamscan Aug 26 20:45:21 rigel amavis[13293]: Deleting db files snmp.db,__db.003,__db.001,nanny.db,__db.002 in /var/lib/amavis/db Aug 26 20:45:21 rigel amavis[13293]: Creating db in /var/lib/amavis/db/; BerkeleyDB 0.55, libdb 5.3

systemctl restart spamassassinsystemctl status spamassassin ● spamassassin.service - Perl-based spam filter using text analysis   Loaded: loaded (/lib/systemd/system/spamassassin.service; enabled; vendor preset: enabled)   Active: active (running) since Sun 2018-08-26 20:47:02 CEST; 6s ago  Process: 13304 ExecStart=/usr/sbin/spamd -d --pidfile=/var/run/spamassassin.pid $OPTIONS (code=exited, status=0/SUCCESS) Main PID: 13307 (/usr/sbin/spamd)   CGroup: /system.slice/spamassassin.service           ├─13307 /usr/sbin/spamd -d --pidfile=/var/run/spamassassin.pid --create-prefs --max-children 5 --helper-home-di           ├─13309 spamd chil           └─13310 spamd chil Aug 26 20:46:58 rigel systemd[1]: Starting Perl-based spam filter using text analysis... Aug 26 20:46:58 rigel spamd[13304]: logger: removing stderr method Aug 26 20:46:59 rigel spamd[13307]: zoom: able to use 353/353 'body_0' compiled rules (100%) Aug 26 20:47:02 rigel spamd[13307]: spamd: server started on IO::Socket::IP [::1]:783, IO::Socket::IP [127.0.0.1]:783 (running version 3.4.1) Aug 26 20:47:02 rigel spamd[13307]: spamd: server pid: 13307 Aug 26 20:47:02 rigel spamd[13307]: spamd: server successfully spawned child process, pid 13309 Aug 26 20:47:02 rigel systemd[1]: Started Perl-based spam filter using text analysis. Aug 26 20:47:02 rigel spamd[13307]: spamd: server successfully spawned child process, pid 13310 Aug 26 20:47:02 rigel spamd[13307]: prefork: child states: IS Aug 26 20:47:02 rigel spamd[13307]: prefork: child states: II

Automatic learning from spam or ham

Feed spamassassin with a spam message to initialize the database

cd /usr/share/doc/spamassassin/examples/sa-learn --spam --username=vmail sample-spam.txt Learned tokens from 1 message(s) (1 message(s) examined)

We check version to be sure dovecot is over 2.2.24

dovecot --version 2.2.33.2 (d6601f4ec)

We add the parameter mail_attribute_dict

cat /etc/dovecot/conf.d/10-mail.conf | grep mail_attribute_dict mail_attribute_dict = file:%h/dovecot-attributes

We add the plugin imap_sieve to imap protocol

cat /etc/dovecot/conf.d/20-imap.conf | grep -v "^ *#" | grep -v "^ *$" protocol imap {  mail_plugins = imap_sieve }

Setup of plugin imapsieve

cat /etc/dovecot/conf.d/90-sieve-extprograms.conf | grep -v "^ *#" | grep -v "^ *$" plugin {  sieve_plugins = sieve_imapsieve sieve_extprograms  imapsieve_url = sieve://127.0.0.1:4190  imapsieve_mailbox1_name = Junk  imapsieve_mailbox1_causes = COPY APPEND  imapsieve_mailbox1_before = file:/var/vmail/sieve/report_spam.sieve  imapsieve_mailbox2_name = *  imapsieve_mailbox2_from = Junk  imapsieve_mailbox2_causes = COPY  imapsieve_mailbox2_before = file:/var/vmail/sieve/report_ham.sieve  sieve_pipe_bin_dir = /etc/dovecot/sieve/pipe  sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment }

We create needed folder

mkdir -p /etc/dovecot/sieve/pipemkdir -p /var/vmail/imapsieve_copychown vmail:mail /var/vmail/imapsieve_copychmod 0700 /var/vmail/imapsieve_copy

We create sieve rule for spam

cat /var/vmail/sieve/report_spam.sieve require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; if environment :matches "imap.user" "*" {   set "username" "${1}"; } pipe :copy "imapsieve_copy" [ "${username}", "spam" ]; 

We create the sieve rules for ham

cat /var/vmail/sieve/report_ham.sieve require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; if environment :matches "imap.mailbox" "*" {   set "mailbox" "${1}"; } if string "${mailbox}" "Trash" {   stop; } if environment :matches "imap.user" "*" {   set "username" "${1}"; } pipe :copy "imapsieve_copy" [ "${username}", "ham" ];

Script pipe run when move mails from/to spam

cat /etc/dovecot/sieve/pipe/imapsieve_copy #!/usr/bin/env bash # Author: Zhang Huangbin <zhb@iredmail.org> # Purpose: Read full email message from stdin, and save to a local file.

# Usage: bash imapsieve_copy <email> <spam|ham> <output_base_dir>

export USER="$1" export MSG_TYPE="$2"

export OUTPUT_BASE_DIR="/var/vmail/imapsieve_copy" export OUTPUT_DIR="${OUTPUT_BASE_DIR}/${MSG_TYPE}" export FILE="${OUTPUT_DIR}/${USER}-$(date +%Y%m%d%H%M%S)-${RANDOM}${RANDOM}.eml"

export OWNER="vmail" export GROUP="mail"

for dir in "${OUTPUT_BASE_DIR}" "${OUTPUT_DIR}"; do     if [[ ! -d ${dir} ]]; then         mkdir -p ${dir}         chown ${OWNER}:${GROUP} ${dir}         chmod 0700 ${dir}     fi done

cat > ${FILE} < /dev/stdin

# Logging export LOG='logger -p local5.info -t imapsieve_copy' [[ $? == 0 ]]> && ${LOG} "Copied one ${MSG_TYPE} email reported by ${USER}: ${FILE}"

Fix file rights

chown vmail:mail /var/vmail/sieve/report_spam.sieve /var/vmail/sieve/report_ham.sieve /etc/dovecot/sieve/pipe/imapsieve_copychmod 700 /var/vmail/sieve/report_spam.sieve /var/vmail/sieve/report_ham.sieve /etc/dovecot/sieve/pipe/imapsieve_copy

Restart dovecot service

systemctl restart dovecot systemctl status dovecot ● dovecot.service - Dovecot IMAP/POP3 email server   Loaded: loaded (/lib/systemd/system/dovecot.service; enabled; vendor preset: enabled)   Active: active (running) since Wed 2019-08-21 22:54:25 EDT; 4s ago     Docs: man:dovecot(1)           http://wiki2.dovecot.org/  Process: 61281 ExecStop=/usr/bin/doveadm stop (code=exited, status=0/SUCCESS) Main PID: 61284 (dovecot)    Tasks: 4 (limit: 1114)   CGroup: /system.slice/dovecot.service           ├─61284 /usr/sbin/dovecot -F           ├─61285 dovecot/anvil           ├─61286 dovecot/log           └─61288 dovecot/config Aug 21 22:54:25 rigel systemd[1]: Started Dovecot IMAP/POP3 email server. Aug 21 22:54:25 rigel dovecot[61284]: doveconf: Warning: SSLv2 not supported by OpenSSL. Please consider removing it from ssl_protocols. Aug 21 22:54:25 rigel dovecot[61284]: master: Dovecot v2.2.33.2 (d6601f4ec) starting up for imap (core dumps disabled) Aug 21 22:54:25 rigel dovecot[61286]: config: Warning: SSLv2 not supported by OpenSSL. Please consider removing it from ssl_protocols.

cat /etc/dovecot/sieve/scan_reported_mails.sh #!/usr/bin/env bash # Author: Zhang Huangbin <zhb@iredmail.org> # Purpose: Copy spam/ham to another directory and call sa-learn to learn.

# Paths to find program. export PATH="/bin:/usr/bin:/usr/local/bin:$PATH"

export OWNER="vmail" export GROUP="vmail"

# The Amavisd daemon user. # Note: on OpenBSD, it's "_vscan". On FreeBSD, it's "vscan". export AMAVISD_USER='amavis'

# Kernel name, in upper cases. export KERNEL_NAME="$(uname -s | tr '[a-z]' '[A-Z]')"

# A temporary lock file. should be removed after successfully examed messages. export LOCK_FILE='/tmp/scan_reported_mails.lock'

# Logging to syslog with 'logger' command. export LOG='logger -p local5.info -t scan_reported_mails'

# `sa-learn` command, with optional arguments. export SA_LEARN="sa-learn -u ${AMAVISD_USER}"

# Spool directory. # Must be owned by vmail:vmail. export SPOOL_DIR='/var/vmail/imapsieve_copy'

# Directories which store spam and ham emails. # These 2 should be created while setup Dovecot antispam plugin. export SPOOL_SPAM_DIR="${SPOOL_DIR}/spam" export SPOOL_HAM_DIR="${SPOOL_DIR}/ham"

# Directory used to store emails we're going to process. # We will copy new spam/ham messages to these directories, scan them, then # remove them. export SPOOL_LEARN_SPAM_DIR="${SPOOL_DIR}/processing/spam" export SPOOL_LEARN_HAM_DIR="${SPOOL_DIR}/processing/ham"

if [ -e ${LOCK_FILE} ]; then     find $(dirname ${LOCK_FILE}) -maxdepth 1 -ctime 1 "$(basename ${LOCK_FILE})" >/dev/null 2>&1     if [ X"$?" == X'0' ]; then         rm -f ${LOCK_FILE} >/dev/null 2>&1     else         ${LOG} "Lock file exists (${LOCK_FILE}), abort."         exit     fi fi

for dir in "${SPOOL_DIR}" "${SPOOL_LEARN_SPAM_DIR}" "${SPOOL_LEARN_HAM_DIR}"; do     if [[ ! -d ${dir} ]]; then         mkdir -p ${dir}     fi

    chown ${OWNER}:${GROUP} ${dir}     chmod 0700 ${dir} done

# If there're a lot files, direct `mv` command may fail with error like # `argument list too long`, so we need `find` in this case. if [[ X"${KERNEL_NAME}" == X'OPENBSD' ]]; then     [[ -d ${SPOOL_SPAM_DIR} ]] && find ${SPOOL_SPAM_DIR} -name '*.eml' -exec mv {} ${SPOOL_LEARN_SPAM_DIR}/ \;     [[ -d ${SPOOL_HAM_DIR} ]]  && find ${SPOOL_HAM_DIR}  -name '*.eml' -exec mv {} ${SPOOL_LEARN_HAM_DIR}/  \; else     [[ -d ${SPOOL_SPAM_DIR} ]] && find ${SPOOL_SPAM_DIR} -name '*.eml' -exec mv -t ${SPOOL_LEARN_SPAM_DIR}/ {} +     [[ -d ${SPOOL_HAM_DIR} ]]  && find ${SPOOL_HAM_DIR}  -name '*.eml' -exec mv -t ${SPOOL_LEARN_HAM_DIR}/  {} + fi

# Try to delete empty directory, if failed, that means we have some messages to # scan. rmdir ${SPOOL_LEARN_SPAM_DIR} &>/dev/null if [[ X"$?" != X'0' ]]; then     output="$(${SA_LEARN} --spam ${SPOOL_LEARN_SPAM_DIR})"     rm -rf ${SPOOL_LEARN_SPAM_DIR} &>/dev/null     ${LOG} '[SPAM]' ${output} fi

rmdir ${SPOOL_LEARN_HAM_DIR} &>/dev/null if [[ X"$?" != X'0' ]]; then     output="$(${SA_LEARN} --ham ${SPOOL_LEARN_HAM_DIR})"     rm -rf ${SPOOL_LEARN_HAM_DIR} &>/dev/null     ${LOG} '[CLEAN]' ${output} fi

rm -f ${LOCK_FILE} &>/dev/null

We add a crontab to process them each 10 minutes

crontab -l | grep sieve */10   *   *   *   *   /bin/bash /etc/dovecot/sieve/scan_reported_mails.sh

Sfp

We want SFP check the headers, but not reject the email.

cat /etc/postfix-policyd-spf-python/policyd-spf.conf | grep -v "^$" #  For a fully commented sample config file see policyd-spf.conf.commented debugLevel = 1 defaultSeedOnly = 1 HELO_reject = False Mail_From_reject = False PermError_reject = False TempError_Defer = False skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1

Opendkim

/etc/opendkim.conf

cat opendkim.conf | grep -v "#" | grep -v "^$" Syslog                  yes LogWhy                  yes UMask                   022 UserID                  opendkim:opendkim Canonicalization        relaxed/simple Mode                    sv SubDomains              yes OversignHeaders         From KeyTable                /etc/opendkim/KeyTable SigningTable            /etc/opendkim/SigningTable ExternalIgnoreList      /etc/opendkim/TrustedHosts InternalHosts           /etc/opendkim/TrustedHosts Socket                  inet:8891@localhost

TrustedHosts file

mkdir /etc/opendkimcd /etc/opendkimcat TrustedHosts 127.0.0.1 localhost 93.90.207.52 2001:8d8:1800:8008::1 rigel.oamis.net

/etc/default/opendkim

cat /etc/default/opendkim | grep -v "^#" SOCKET="inet:8891@localhost"

create keys for a domain

mkdir -p /etc/opendkim/keyscd /etc/opendkim/keysmkdir oamis.netcd oamis.netopendkim-genkey -h rsa-sha256 -b 2048 -s dkim -d oamis.net   chown opendkim:opendkim dkim.privateecho "dkim._domainkey.oamis.net oamis.net:dkim:/etc/opendkim/keys/oamis.net/dkim.private" >> /etc/opendkim/KeyTableecho "oamis.net dkim._domainkey.oamis.net" >> /etc/opendkim/SigningTableecho oamis.net >> /etc/opendkim/TrustedHosts

Add DNS record for a domain

cat /etc/opendkim/keys/oamis.net/dkim.txt >> oamis.net/etc/init.d/bind9 restart

restart service

/etc/init.d/bind9 restart

Opendmarc

Create database

cat /usr/share/doc/opendmarc/schema.mysql | mysql -p Enter password: mysql -p Enter password: Welcome to the MySQL monitor.  Commands end with ; or \g. Your MySQL connection id is 418 Server version: 5.7.27-0ubuntu0.18.04.1-log (Ubuntu) Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> CREATE USER 'opendmarc'@'localhost' IDENTIFIED BY 'xxxxxxxxxxxx'; Query OK, 0 rows affected (0.01 sec) mysql>  GRANT ALL ON opendmarc.* to 'opendmarc'@'localhost'; Query OK, 0 rows affected (0.00 sec) mysql> quit Bye

/etc/opendmarc.conf

cat /etc/opendmarc.conf | grep -v "^#" | grep -v "^$" AuthservID OpenDmarc PidFile /var/run/opendmarc/opendmarc.pid PublicSuffixList /usr/share/publicsuffix RejectFailures false Socket inet:8892@localhost Syslog true SyslogFacility mail UMask 0002 UserID opendmarc IgnoreAuthenticatedClients true HistoryFile /var/vmail/opendmarc/opendmarc.dat FailureReports true FailureReportsBcc servers@oamis.net FailureReportsSentBy noreply@oamis.net CopyFailuresTo servers@oamis.net

/etc/default/opendmarc

cat /etc/default/opendmarc | grep -v "^#" RUNDIR=/var/run/opendmarc SOCKET=inet:8892@localhost USER=opendmarc GROUP=opendmarc PIDFILE=$RUNDIR/$NAME.pid EXTRAAFTER=

Create opendmarc folder

mkdir -p /var/vmail/opendmarcchown opendmarc:opendmarc /var/vmail/opendmarcchmod 700 /var/vmail/opendmarc

Enable service

systemctl enable opendmarc Synchronizing state of opendmarc.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable opendmarc

Create script to transmit reports

Parameters file

rigel:~# cat /etc/luniel/etc/opendmarc-send-reports.conf DBHOST='localhost' DBUSER='opendmarc' DBPASS='xxxxxxxxxxxxxxxxx' DBNAME='opendmarc' HISTDIR='/var/vmail/opendmarc' HISTFILE='opendmarc'

Script file

rigel:~# cat /etc/luniel/opendmarc-send-reports.sh #!/bin/bash # Imports data from OpenDMARC's opendmarc.dat file into a local MySQL DB # and sends DMARC failure reports to domain owners. # Based on a script from Hamzah Khan (http://blog.hamzahkhan.com/) source /etc/luniel/etc/opendmarc-send-reports.conf UTCHOUR=`date -u +"%H"` #We check that it is 00:00 UTC time if [ ! "#${UTCHOUR}#" = "#00#" ] ; then        exit 0 fi set -e DATESTAMP=`date +%Y%m%d%H%M%S` # Make sure history file exists touch ${HISTDIR}/${HISTFILE}.dat # Move history file temp dir for processing mv ${HISTDIR}/${HISTFILE}.dat ${HISTDIR}/${HISTFILE}.${DATESTAMP} # Import temp history file data and send reports /usr/sbin/opendmarc-import -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} -verbose < ${HISTDIR}/${HISTFILE}.${DATESTAMP} /usr/sbin/opendmarc-reports -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} --utc --keepfiles -verbose -interval=86400 -report-email 'noreply@oamis.net' -report-org 'oamis.net' #/usr/sbin/opendmarc-expire -dbhost=${DBHOST} -dbuser=${DBUSER} -dbpasswd=${DBPASS} -dbname=${DBNAME} -verbose # Delete temp history file # rm -rf *.$$

Add crontab line to run reports each hour but reports will be only sent at 0:00 UTC

rigel:~# crontab -l | grep opendmarc 0 * * * * /etc/luniel/opendmarc-send-reports.sh

Postfix

SQL maps files

cat /etc/postfix/mysql_virtual_alias_domainaliases_maps.cf user = postfix password = postfixpassword hosts = 127.0.0.1 dbname = mail 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

cat /etc/postfix/mysql_virtual_alias_maps.cf user = postfix password = postfixpassword hosts = 127.0.0.1 dbname = mail table = alias select_field = goto where_field = address additional_conditions = and active = '1'

cat /etc/postfix/mysql_virtual_domains_maps.cf user = postfix password = postfixpassword hosts = 127.0.0.1 dbname = mail table = domain select_field = domain where_field = domain additional_conditions = and backupmx = '0' and active = '1'

cat /etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf user = postfix password = postfixpassword hosts = 127.0.0.1 dbname = mail 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

cat /etc/postfix/mysql_virtual_mailbox_maps.cf user = postfix password = postfixpassword hosts = 127.0.0.1 dbname = mail table = mailbox select_field = CONCAT(domain, '/', local_part) where_field = username additional_conditions = and active = '1'

cat /etc/postfix/mysql_virtual_sender_login_maps.cf user = postfix password = postfixpassword hosts = 127.0.0.1 dbname = mail query = SELECT goto FROM alias WHERE address='%s'

Headers check

cat /etc/postfix/header_checks /^Received:/                 IGNORE /^User-Agent:/               IGNORE /^X-Mailer:/                 IGNORE /^X-Originating-IP:/         IGNORE /^x-cr-[a-z]*:/              IGNORE /^Thread-Index:/             IGNORE

Generating DH file

cd /etc/postfix/ssl/ openssl dhparam -out dh4096.pem 4096 Generating DH parameters, 4096 bit long safe prime, generator 2 This is going to take a long time

main.cf

cat main.cf |  grep -v "#" | grep -v "^$" smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu) biff = no append_dot_mydomain = no readme_directory = no smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes broken_sasl_auth_clients = yes smtpd_sasl_security_options = noanonymous smtpd_sasl_local_domain = smtpd_sasl_authenticated_header = yes smtpd_tls_cert_file = /etc/postfix/ssl/rigel.oamis.net.cer smtpd_tls_key_file = /etc/postfix/ssl/rigel.oamis.net.key smtpd_tls_CAfile = /etc/postfix/ssl/ca.cer smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3 smtp_tls_note_starttls_offer = yes smtpd_tls_loglevel = 1 smtpd_tls_received_header = yes smtpd_tls_session_cache_timeout = 3600s tls_random_source = dev:/dev/urandom smtpd_tls_security_level = may smtp_tls_security_level = may smtpd_tls_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CDC3-SHA, KRB5-DE5, CBC3-SHA smtpd_tls_dh1024_param_file = /etc/postfix/ssl/dh4096.pem unknown_local_recipient_reject_code = 450 maximal_queue_lifetime = 7d minimal_backoff_time = 300s maximal_backoff_time = 8000s smtp_helo_timeout = 60s smtpd_recipient_limit = 16 smtpd_soft_error_limit = 3 smtpd_hard_error_limit = 12 smtpd_helo_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit smtpd_sender_restrictions = permit_mynetworks, reject_authenticated_sender_login_mismatch, permit_sasl_authenticated, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit smtpd_client_restrictions = reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service  unix:private/policy-spf, check_policy_service inet:127.0.0.1:10023, permit smtpd_data_restrictions = reject_unauth_pipelining smtpd_relay_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service unix:private/policy-spf, check_policy_service inet:127.0.0.1:10023, permit smtpd_helo_required = yes smtpd_delay_reject = yes disable_vrfy_command = yes myhostname = rigel.oamis.net mydestination = myorigin = /etc/mailname mydestination = $myhostname, rigel.oamis.net, rigel, localhost.localdomain, localhost relayhost = mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all inet_protocols = all mynetworks_style = host virtual_mailbox_base = /var/vmail virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf, mysql:/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf virtual_uid_maps = static:150 virtual_gid_maps = static:8 virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf smtpd_sender_login_maps = mysql:/etc/postfix/mysql_virtual_sender_login_maps.cf virtual_transport = dovecot dovecot_destination_recipient_limit = 1 content_filter = amavis:[127.0.0.1]:10024 policy-spf_time_limit = 3600s header_checks = regexp:/etc/postfix/header_checks enable_original_recipient = no milter_default_action = accept milter_protocol = 6 smtpd_milters = inet:localhost:8891,inet:localhost:8892 non_smtpd_milters = inet:localhost:8891,inet:localhost:8892 alias_maps = hash:/etc/aliases # Increase message size limit to 200MB message_size_limit = 209715200

master.cf

cat master.cf |  grep -v "#" | grep -v "^$" smtp      inet  n       -       y       -       -       smtpd 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=yes  -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject  -o smtpd_helo_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit  -o smtpd_sender_restrictions = permit_mynetworks, reject_authenticated_sender_login_mismatch, permit_sasl_authenticated, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject  -o milter_macro_daemon_name=ORIGINATING pickup    unix  n       -       y       60      1       pickup cleanup   unix  n       -       y       -       0       cleanup qmgr      unix  n       -       n       300     1       qmgr tlsmgr    unix  -       -       y       1000?   1       tlsmgr rewrite   unix  -       -       y       -       -       trivial-rewrite bounce    unix  -       -       y       -       0       bounce defer     unix  -       -       y       -       0       bounce trace     unix  -       -       y       -       0       bounce verify    unix  -       -       y       -       1       verify flush     unix  n       -       y       1000?   0       flush proxymap  unix  -       -       n       -       -       proxymap proxywrite unix -       -       n       -       1       proxymap smtp      unix  -       -       y       -       -       smtp relay     unix  -       -       y       -       -       smtp showq     unix  n       -       y       -       -       showq error     unix  -       -       y       -       -       error retry     unix  -       -       y       -       -       error discard   unix  -       -       y       -       -       discard local     unix  -       n       n       -       -       local virtual   unix  -       n       n       -       -       virtual lmtp      unix  -       -       y       -       -       lmtp anvil     unix  -       -       y       -       1       anvil scache    unix  -       -       y       -       1       scache maildrop  unix  -       n       n       -       -       pipe  flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient} uucp      unix  -       n       n       -       -       pipe  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient) ifmail    unix  -       n       n       -       -       pipe  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient) bsmtp     unix  -       n       n       -       -       pipe  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient scalemail-backend unix  -       n       n       -       2       pipe  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension} mailman   unix  -       n       n       -       -       pipe  flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py  ${nexthop} ${user} amavis      unix    -       -       y       -       3       smtp  -o smtp_data_done_timeout=1200  -o smtp_send_xforward_command=yes  -o disable_dns_lookups=yes  -o max_use=20 127.0.0.1:10025 inet    n       -       y       -       -       smtpd  -o content_filter=  -o local_recipient_maps=  -o relay_recipient_maps=  -o smtpd_restriction_classes=  -o smtpd_delay_reject=no  -o smtpd_client_restrictions=permit_mynetworks,reject  -o smtpd_helo_restrictions=  -o smtpd_sender_restrictions=  -o smtpd_recipient_restrictions=permit_mynetworks,reject  -o smtpd_data_restrictions=reject_unauth_pipelining  -o smtpd_end_of_data_restrictions=  -o mynetworks=127.0.0.0/8  -o smtpd_error_sleep_time=0  -o smtpd_soft_error_limit=1001  -o smtpd_hard_error_limit=1000  -o smtpd_client_connection_count_limit=0  -o smtpd_client_connection_rate_limit=0  -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters dovecot      unix   -        n      n       -       -   pipe  flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient) policy-spf  unix  -       n       n       -       -       spawn     user=nobody argv=/usr/bin/policyd-spf

Restart all services

service postfix restartservice opendkim restartservice opendmarc restartservice spamassassin restartservice clamav-daemon restartservice amavis restartservice dovecot restart

---