Mail server
# Config in distributor VPS web
Set Reverse DNS on VPS
mail.{domain}
Config SELinux
sudo nano /etc/selinux/config SELINUX=disabledConfig HOSTNAME
sudo nano /etc/hosts {IP_VPS} mail.{domain} mailConfig NetworkManager
sudo nano /etc/sysconfig/network HOSTNAME=mail.{domain}Restart NetworkManager service
sudo systemctl restart NetworkManagerConfig DNS record
A @ 3600 {IP}
A mail 3600 {IP}
MX @ 3600 mail.{domain}
TXT @ 3600 "v=spf1 +a +mx +ip4:{IP} ~all"
TXT _dmarc 3600 "v=DMARC1; p=quarantine; pct=100; rua=mailto:{admin_email}; sp=none; aspf=r;"
TXT default._domainkey 3600 "v=DKIM1; k=rsa; p={dkim_token};"Test HOST
host {domain}
{domain} has address {IP}
{domain} mail is handled by {priority} mail.{domain}Test nslookup
nslookup
> mail.{domain}
Name: mail.{domain}
Address: {IP}
> exitTest dig
dig {domain}
{domain}. {number} IN A {IP} dig {domain} MX
{domain}. {number} IN MX 10 mail.{domain}.Test ping
ping mail.{domain}# Install Postfix
Install Postfix
sudo dnf install -y postfix postfix-mysqlEnable and start Postfix service
sudo systemctl enable --now postfix# Install Dovecot
Install Dovecot
sudo dnf install -y dovecot dovecot-mysqlEnable and start Dovecot service
sudo systemctl enable --now dovecot# Create mail database
Login MySQL
mysql -u root -pCreate database
CREATE DATABASE {db_mail};Create user MySQL
CREATE USER '{user_db}'@'localhost' IDENTIFIED BY '{password_mail}';Grand permission user with database
GRANT ALL PRIVILEGES ON {db_mail}.* TO '{user_db}'@'localhost';Apply privileges
FLUSH PRIVILEGES;Use database
USE {db_mail};Create table domain
CREATE TABLE tbl_domains (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
active INT NOT NULL DEFAULT 1,
PRIMARY KEY (id),
UNIQUE KEY name (name))
ENGINE=InnoDB DEFAULT CHARSET=utf8;Create table user
CREATE TABLE tbl_users (
id INT NOT NULL AUTO_INCREMENT,
email VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
full_name VARCHAR(255) NOT NULL,
department VARCHAR(255) NOT NULL,
active INT NOT NULL DEFAULT 1,
domain_id INT NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY email (email),
FOREIGN KEY (domain_id) REFERENCES tbl_domains(id) ON DELETE CASCADE)
ENGINE=InnoDB DEFAULT CHARSET=utf8;Create table alias
CREATE TABLE tbl_aliases (
id INT NOT NULL AUTO_INCREMENT,
source VARCHAR(255) NOT NULL,
destination TEXT NOT NULL,
active INT NOT NULL default 1,
domain_id INT NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY source (source),
FOREIGN KEY (domain_id) REFERENCES tbl_domains (id))
ENGINE=InnoDB DEFAULT CHARSET=utf8;Insert data to table
INSERT INTO tbl_domains (name, active) VALUES ('{domain}', '1'); INSERT INTO tbl_users (email, password, full_name, department, domain_id) VALUES ('{email}', ENCRYPT('{password}'), '{full_name}', '{department}', '1'); INSERT INTO tbl_aliases (source, destination, domain_id) VALUES ('{alias}@{domain}', '{email}', '1');Test database
SELECT * FROM tbl_domains; SELECT * FROM tbl_users; SELECT * FROM tbl_aliases; exit;# Config Postfix
main.cf
sudo nano /etc/postfix/main.cf myhostname = mail.{domain}
mydomain = {domain}
myorigin = $mydomain
inet_interfaces = all
mydestination = localhost, localhost.localdomain
mynetworks = 127.0.0.0/8
relayhost =
recipient_delimiter = +
smtpd_banner = $myhostname ESMTP $mail_name
biff = no Move end of file
# Config SASL Authentication
# Enabling SMTP for authenticated users, and handing off authentication to Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_authenticated_header = yes
virtual_transport = lmtp:unix:private/dovecot-lmtp
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated permit_inet_interfaces reject_unauth_destination
# Config Virtual mailbox settings
# Virtual domains, users, and aliases
virtual_alias_domains =
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf
virtual_mailbox_base = /home/{user_mail}
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_create_maildirsize = yes
virtual_maildir_extended = yes
proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps
# SSL-TLS parameters
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
smtpd_tls_cert_file = /etc/letsencrypt/live/{domain}/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/{domain}/privkey.pem
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous
# Integrate OpenDKIM with Postfix
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
# Integrate Amavis-new with Postfix
content_filter=smtp-amavis:[127.0.0.1]:10024mysql-virtual_domains.cf
sudo nano /etc/postfix/mysql-virtual_domains.cf user = {user_db}
password = {password_db}
dbname = {db_name}
query = SELECT name FROM tbl_domains WHERE name='%s' AND active=1
hosts = 127.0.0.1mysql-virtual_forwardings.cf
sudo nano /etc/postfix/mysql-virtual_forwardings.cf user = {user_db}
password = {password_db}
dbname = {db_name}
query = SELECT destination FROM tbl_aliases WHERE source='%s' AND active=1
hosts = 127.0.0.1mysql-virtual_mailboxes.cf
sudo nano /etc/postfix/mysql-virtual_mailboxes.cf user = {user_db}
password = {password_db}
dbname = {db_name}
query = SELECT CONCAT(SUBSTRING_INDEX(email, '@', -1), '/', SUBSTRING_INDEX(email, '@', 1), '/') FROM tbl_users WHERE email='%s' AND active=1
hosts = 127.0.0.1mysql-virtual_email2email.cf
sudo nano /etc/postfix/mysql-virtual_email2email.cf user = {user_db}
password = {password_db}
dbname = {db_name}
query = SELECT email FROM tbl_users WHERE email='%s' AND active=1
hosts = 127.0.0.1Assign permission for mysql-virtual_*
sudo chmod o= /etc/postfix/mysql-virtual_* sudo chgrp postfix /etc/postfix/mysql-virtual_*Test connection
sudo postmap -q {domain} mysql:/etc/postfix/mysql-virtual_domains.cf
{domain} sudo postmap -q {email} mysql:/etc/postfix/mysql-virtual_mailboxes.cf
{domain}/{email_name} sudo postmap -q {alias}@{domain} mysql:/etc/postfix/mysql-virtual_forwardings.cf
{email}Create group and assign permission
sudo groupadd -g 5000 {user_mail} sudo useradd -g {user_mail} -u 5000 {user_mail} -d /home/{user_mail} -mmaster.cf
sudo nano /etc/postfix/master.cf smtp inet n - n - - smtpd
-o content_filter=spamassassin
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_reject_unlisted_recipient=no
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
-o content_filter=spamassassin Move end of file
dovecot unix - n n - - pipe flags=DRhu user={user_mail}:{user_mail} argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
spamassassin unix - n n - - pipe flags=R user=spamd argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
smtp-amavis unix - - n - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
127.0.0.1:10025 inet n - n - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o strict_rfc821_envelopes=yes
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000Restart Postfix service
sudo systemctl restart postfixAdd service to Firewall
sudo firewall-cmd --permanent --add-service=smtp sudo firewall-cmd --permanent --add-service=smtpsReload Firewall service
sudo firewall-cmd --reload# Config Dovecot
dovecot.cf
sudo nano /etc/dovecot/dovecot.conf protocols = imap pop3 lmtp
listen = *10-mail.conf
sudo nano /etc/dovecot/conf.d/10-mail.conf mail_location = maildir:/home/{user_mail}/%d/%n/maildir
mail_privileged_group = mail10-auth.conf
sudo nano /etc/dovecot/conf.d/10-auth.conf disable_plaintext_auth = no (SMTP) yes (TLS)
auth_mechanisms = plain login
!include auth-sql.conf.extauth-sql.conf.ext
sudo nano /etc/dovecot/conf.d/auth-sql.conf.ext userdb {
driver = static
args = uid=5000 gid=5000 home=/home/{user_mail}/%d/%n allow_all_users=yes
}dovecot-sql.conf.ext
sudo nano /etc/dovecot/dovecot-sql.conf.ext driver = mysql
connect = host=127.0.0.1 dbname={db_name} user={user_db} password={password_db}
default_pass_scheme = SHA512-CRYPT
password_query = SELECT email AS user, password FROM tbl_users WHERE email='%u' AND active=1;Assign permission for dovecot-sql.conf.ext
sudo chgrp dovecot /etc/dovecot/dovecot-sql.conf.ext sudo chmod o= /etc/dovecot/dovecot-sql.conf.ext10-master.conf
sudo nano /etc/dovecot/conf.d/10-master.conf service imap-login {
inet_listener imap {
port = 143
}
inet_listener imaps {
port = 993
ssl = yes
}
} service pop3-login {
inet_listener pop3 {
port = 110
}
inet_listener pop3s {
port = 995
ssl = yes
}
} service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0660
user = postfix
group = postfix
}
} service auth {
unix_listener auth-userdb {
mode = 0600
user = {user_mail}
}
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
user = dovecot
} service auth-worker {
user = {user_mail}
}10-ssl.conf
Mail no SSL/TLS
sudo nano /etc/dovecot/conf.d/10-ssl.conf ssl = no
#ssl_cert = ...
#ssl_key = ... Mail with SSL/TLS
sudo nano /etc/dovecot/conf.d/10-ssl.conf ssl = required
ssl_cert = </etc/letsencrypt/live/{domain}/fullchain.pem
ssl_key = </etc/letsencrypt/live/{domain}/privkey.pemRestart Dovecot service
sudo systemctl restart dovecotRestart Postfix service
sudo systemctl restart postfixAdd service to Firewall
sudo firewall-cmd --permanent --add-service=pop3 sudo firewall-cmd --permanent --add-service=pop3sReload Firewall service
sudo firewall-cmd --reload# Test Postfix
Test SMTP
telnet mail.{domain} smtp
220 mail.{domain} ESMTP Postfix
ehlo mail.{domain}
250 mail.{domain}
...
quitTest POP3
telnet mail.{domain} pop3
+OK Dovecot ready
quitView log mail
sudo tail -f /var/log/maillog# Roundcube
Download current release
wget https://github.com/roundcube/roundcubemail/releases/download/1.6.8/roundcubemail-1.6.8-complete.tar.gzExtract file
tar xvf roundcubemail-1.6.8-complete.tar.gzRename folder
mv roundcubemail-1.6.8 webmailCopy to Apache
sudo cp -rf webmail /var/www/htmlLogin MySQL
mysql -u root -pCreate database
CREATE DATABASE {db_roundcube};Create user MySQL
CREATE USER '{user_roundcube}'@'localhost' IDENTIFIED BY '{password_roundcube}';Grand permission user with database
GRANT ALL PRIVILEGES ON {db_roundcube}.* TO '{user_roundcube}'@'localhost';Apply privileges
FLUSH PRIVILEGES; exit;Init database
mysql -u {user_roundcube} -p {db_roundcube} < /var/www/html/webmail/SQL/mysql.initial.sqlChange timezone
sudo nano /etc/php.ini date.timezone = Asia/Ho_Chi_MinhGive ownership to the folder
sudo chown -R apache:apache /var/www/html/webmail/temp sudo chown -R apache:apache /var/www/html/webmail/logsGrant write permissions to the directory
sudo chmod -R 755 /var/www/html/webmail/temp sudo chmod -R 755 /var/www/html/webmail/logsRestart php-fpm service
sudo systemctl restart php-fpmAccess installer
https://mail.{domain}/installerIMAP host
ssl://mail.{domain}:993SMTP server
tls://mail.{domain}:587 ssl://mail.{domain}:465Tick plugins and save config
Save as config.inc.php under /var/www/html/webmail/config/ directory
Restart httpd service
sudo systemctl restart httpdTest send email and remove installer directory
# SpamAssassin
Install SpamAssassin
sudo dnf install -y spamassassinConfig SpamAssassin
sudo nano /etc/mail/spamassassin/local.cf required_score 5Assign permission for SpamAssassin
sudo groupadd -g 5555 {user_spamd} sudo useradd -u 5555 -g {user_spamd} -s /bin/false -d /var/log/spamassassin {user_spamd} sudo chown {user_spamd}:{user_spamd} /var/log/spamassassinEnable and start SpamAssassin service
sudo systemctl enable --now spamassassinRestart Dovecot service
sudo systemctl restart dovecotRestart Postfix service
sudo systemctl restart postfixSend email with SPAM title from another email to email config
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X# OpenDKIM
Install OpenDKIM
sudo dnf --enablerepo=epel,crb -y install opendkim opendkim-toolsCreate public and private key
sudo opendkim-genkey -D /etc/opendkim/keys -d {domain} sudo ls -la /etc/opendkim/keysConfig OpenDKIM
sudo nano /etc/opendkim.conf Mode sv
Socket inet:8891@127.0.0.1
Umask 022
Canonicalization relaxed/simple
Domain {domain}
# KeyFile ...
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts ls -la /etc/opendkim sudo nano /etc/opendkim/KeyTable default._domainkey.{domain} {domain}:default:/etc/opendkim/keys/default.private sudo nano /etc/opendkim/SigningTable *@{domain} default._domainkey.{domain} sudo nano /etc/opendkim/TrustedHosts # ::1
{domain}
mail.{domain}Assign permission for opendkim
sudo chown -R opendkim:opendkim /etc/opendkimRestart Dovecot service
sudo systemctl restart dovecotRestart Postfix service
sudo systemctl restart postfixEnable and start OpenDKIM service
sudo systemctl enable --now opendkimCopy OpenDKIM key in config and paste to DNS default._domainkey record
sudo nano /etc/opendkim/keys/default.txtTest listen port 8891
sudo ss -lnpt | grep 8891Send email to verify
check-auth@verifier.port25.com# Check virus
Install Amavisd
sudo dnf install -y clamav clamav-update amavisd-newConfig Amavisd
sudo nano /etc/amavisd/amavisd.conf $mydomain = '{domain}';
$myhostname = 'mail.{domain}';
$notify_method = 'smtp:[127.0.0.1]:10025';
$forward_method = 'smtp:[127.0.0.1]:10025';Enable and start Amavisd service
sudo systemctl enable --now amavisdRestart Postfix service
sudo systemctl restart postfixSend email to another email and go to "Show original" and find X-Virus-Scanned
# Block mail server attacks
Install Fail2Ban
sudo dnf install -y fail2banEnable and start Fail2Ban service
sudo systemctl enable --now fail2banConfig Fail2Ban
sudo nano /etc/fail2ban/jail.local [postfix-sasl]
enabled = true
port = smtp,ssmtp,submission
filter = postfix-sasl
logpath = /var/log/maillog
maxretry = 3 ; 3 times wrong password
findtime = 600 ; in 10 minutes
bantime = 3600 ; ban in 1 hourView Mail log
sudo tail -f /var/log/maillogFilter attack by postfix-sasl
sudo nano /etc/fail2ban/filter.d/postfix-sasl.conf [Definition]
failregex = ^.*postfix/smtps/smtpd\[\d+\]: warning: unknown\[<HOST>\]: SASL LOGIN authentication failed: .*
ignoreregex =Test regex with log
sudo fail2ban-regex /var/log/maillog /etc/fail2ban/filter.d/postfix-sasl.conf If exist matched line it is work well
Restart Fail2Ban service
sudo systemctl restart fail2banCheck status postfix-sasl
sudo fail2ban-client status postfix-saslUnban IP
sudo fail2ban-client set postfix-sasl unbanip {IP}