9

---------

Postfix mail server on CentOS 7 with virtual domains, management system, web access and many others

https://www.dmosk.ru/instruktions.php?object=postfix-centos

Terms on the topic: Postfix , POP3 , SMTP , IMAP , MariaDB , CentOS , PostfixAdmin , DovecotRoundcube

In this manual, you configure a full-fledged mail server. List of all features and capabilities:

Content

1. Pre-installation of the system 

2. Configuring the Web server: NGINX + PHP + MariaDB 

3. Installing and configuring PostfixAdmin 

4. Configuring Postfix 

5. Configuring Dovecot 

6. Checking the server 

7. Configuring Roundcube Webmail 

8. Protection from viruses 

9. Protection from SPAM

1. Presetting the system

I remind you, this instruction is written under the Linux system CentOS version 7.

Setting the correct name to the server is an important step, since most antispam systems perform checks, referring to the server by name in anticipation of a response.

vi / etc / hostname

relay.dmosk.ru

* You must specify the FQDN name that will be available from the WAN. In this example, relay.dmosk.ru is specified  .

After we enter the following command:

hostname relay.dmosk.ru

Install service packs (they will be needed during server configuration):

yum install ntp wget

ntp for the ability to synchronize the time on the server; wget - client for downloading files.

Set the time zone (in this example, Moscow time):

\ cp / usr / share / zoneinfo / Europe / Moscow / etc / localtime

Synchronize time:

ntpdate en.pool.ntp.org

We update the system:

yum update

We open the ports in advance on the  firewall :

firewall-cmd --permanent --add-port = 25 / tcp

firewall-cmd --permanent --add-port = 80 / tcp

firewall-cmd --permanent --add-port = 110 / tcp

firewall-cmd --permanent --add-port = 143 / tcp

firewall-cmd --permanent --add-port = 443 / tcp

firewall-cmd --permanent --add-port = 465 / tcp

firewall-cmd --permanent --add-port = 587 / tcp

firewall-cmd --permanent --add-port = 993 / tcp

firewall-cmd --permanent --add-port = 995 / tcp

firewall-cmd --reload

* where we will open the following ports:

2. Configuring the web server: NGINX + PHP + MariaDB

The PostfixAdmin control system operates as a web application developed in  PHP , and stores information in the database. In our example, we will use the  web server on NGINX , and the database will be MariaDB.

NGINX installation

Add the repository with the required package:

vi /etc/yum.repos.d/nginx.repo

[nginx] 

name = nginx repo 

baseurl = http: //nginx.org/packages/centos/$releasever/$basearch/ 

gpgcheck = 0 

enabled = 1

Install nginx:

yum install nginx

We allow autostart service and start it:

systemctl enable nginx

systemctl start nginx

We check the working capacity of the web server by accessing it in the browser using the IP address . If you see the title "Welcome to nginx!", NGINX is configured correctly.

PHP + PHP-FPM + NGINX

Install php and php-fpm :

yum install php

yum install php-fpm

Configuring NGINX:

vi /etc/nginx/conf.d/default.conf

server { 

    listen 80 default_server; 

    set $ root_path / usr / share / nginx / html; 

    location / { 

        root $ root_path; 

        index index.php index.hml; 

    } 

    location ~ \ .php $ { 

        fastcgi_pass unix: /var/run/php-fpm/php5-fpm.sock; 

        fastcgi_index index.php; 

        fastcgi_param SCRIPT_FILENAME $ root_path $ fastcgi_script_name; 

        include fastcgi_params; 

        fastcgi_param DOCUMENT_ROOT $ root_path; 

    } 

}

* where  / usr / share / nginx / html - directory for posting the Postfix management portal.

Configure PHP-FPM:

vi /etc/php-fpm.d/www.conf

listen = /var/run/php-fpm/php5-fpm.sock

* here we changed the line  127.0.0.1:9000 .

Run the services:

systemctl enable php-fpm

systemctl start php-fpm

systemctl restart nginx

* If during the restart of nginx the nginx error pops up  : [emerg] a duplicate default server , it is necessary to find the virtual domain setting, which also specifies the option  default_server - the option should be removed. Or you can configure another virtual domain yourself.

For verification, create an index file in the site directory with the following content:

vi /usr/share/nginx/html/index.php

<? php phpinfo (); ?>

Open the site in the browser by its IP address. On the opened page we should see the detailed information on php:

MariaDB

Install the database server with the following command:

yum install mariadb mariadb-server

Enable the autostart service and run it:

systemctl enable mariadb

systemctl start mariadb

Set the password for the user sql root:

mysqladmin -u root password

3. Installing and Configuring PostfixAdmin

Install additional components for PHP:

yum install php-mysql php-mbstring php-imap

To apply installed packages, restart the script handler:

systemctl restart php-fpm

Download PostfixAdmin:

wget https://sourceforge.net/projects/postfixadmin/files/latest/download -O postfixadmin.tar.gz

In the directory of nginx sites we create a directory for postfixadmin and unpack the archive into it:

mkdir / usr / share / nginx / html / postfixadmin

tar -C / usr / share / nginx / html / postfixadmin -xvf postfixadmin.tar.gz --strip-components 1

We set the rights to the directory:

chown -R apache: apache / usr / share / nginx / html / postfixadmin

* despite the fact that we use the nginx web server, php-fpm by default, is run from the apache user.

Create the postfix database and the account in mariadb:

mysql -u root -p

CREATE DATABASE postfix DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

* where postfix is the name of the database.

GRANT ALL ON postfix. * TO 'postfix' @ 'localhost' IDENTIFIED BY 'postfix123';

* where  postfix is the account name; postfix123 - password; localhost only allows connection from the local server.

Exit the MariaDB command shell:

\ q

Open the configuration file postfixadmin:

vi /usr/share/nginx/html/postfixadmin/config.inc.php

And we edit the following:

$ CONF ['configured'] = true; 

$ CONF ['default_language'] = 'ru'; 

$ CONF ['database_password'] = 'postfix123'; 

$ CONF ['emailcheck_resolve_domain'] = 'NO';

Launch the browser and enter the address http: // <server IP address> /postfixadmin/setup.php

The process of verifying the configuration and installing the PostfixAdmin portal will begin. After it's finished, enter the password twice and generate a hash:

After reloading the page, we copy the hash:

Open the configuration file:

vi /usr/share/nginx/html/postfixadmin/config.inc.php

We find the line:

$ CONF ['setup_password'] = 'changeme';

And we change it to:

$ CONF ['setup_password'] = '7a8e14 ... c26';

* where  '7a8e14 ... c26' is the copied hash.

After, on the same page where the hash is shown, add the superuser PostfixAdmin:

* where Setup password is the password that we entered on the previous page; Password - the new password for the account you are creating.

As a result, we will see the following:

And we go in the browser to the page http: // <IP-address of the server> / postfixadmin /

We enter login and password for the created user.

Done.

4. Configuring Postfix

By default, Postfix is ​​already installed in CentOS 7. But if the server does not exist without it, let's perform the installation with a simple command:

yum install postfix

We create an account from which we will work with the virtual mailbox directory:

groupadd -g 1024 vmail 

useradd -d / home / mail -g 1024 -u 1024 vmail -m

* First we create a group of  vmail and guid 1024 , after - the user  vmail with uid 1024 and home directory / home / mail . Note that on some systems, the group ID and user ID 1024 can be used. In this case, you must create another one, and in this manual, replace all 1024 with an alternative one.

Now open the configuration file of the mail server for editing:

vi /etc/postfix/main.cf

And we edit the following lines:

myorigin = $ mydomain

* This setting specifies which domain to substitute to the sender, if it is not specified in the FROM header.

mydestination = $ myhostname, localhost. $ mydomain, localhost, $ mydomain

* specify for which domains we receive incoming mail.

local_recipient_maps = unix: passwd.byname $ alias_maps

* indicate where to get the list of local users.

mynetworks = 127.0.0.0/8

* Permit to send messages to the local server.

alias_maps = hash: / etc / aliases

* indicate where to get the list of aliases.

inet_interfaces = all

* You need to make sure that postfix will listen on all necessary interfaces, in this case, at all.

Now at the end of the configuration file we will add the following:

virtual_mailbox_base = / home / mail 

virtual_alias_maps = proxy: mysql: /etc/postfix/mysql_virtual_alias_maps.cf 

virtual_mailbox_domains = proxy: mysql: /etc/postfix/mysql_virtual_domains_maps.cf 

virtual_mailbox_maps = proxy: mysql: /etc/postfix/mysql_virtual_mailbox_maps.cf 

virtual_minimum_uid = 1024 

virtual_uid_maps = static: 1024 

virtual_gid_maps = static: 1024 

virtual_transport = 

dovecot dovecot_destination_recipient_limit = 1

smtpd_sasl_auth_enable = yes 

smtpd_sasl_exceptions_networks = $ mynetworks 

smtpd_sasl_security_options = noanonymous 

broken_sasl_auth_clients = yes 

smtpd_sasl_type = 

dovecot smtpd_sasl_path = private / auth

smtpd_tls_cert_file = /etc/ssl/mail/public.pem 

smtpd_tls_key_file = /etc/ssl/mail/private.key 

smtpd_use_tls = yes 

smtpd_tls_auth_only = yes 

smtpd_helo_required = yes

* where:

Create a file with the settings for accessing the database with aliases:

vi /etc/postfix/mysql_virtual_alias_maps.cf

user = postfix 

password = postfix123 

hosts = localhost 

dbname = postfix 

query = SELECT goto FROM alias WHERE address = '% s' AND active = '1'

* where user and password - login and password to connect to MySQL; hosts - the name of the database server (in this case, the local server); dbname - the name of the database; query - a query template for data.

Create a file with instructions for obtaining data on virtual domains:

vi /etc/postfix/mysql_virtual_domains_maps.cf

user = postfix 

password = postfix123 

hosts = localhost 

dbname = postfix 

query = SELECT domain FROM domain WHERE domain = '% u'

And a file with mailboxes:

vi /etc/postfix/mysql_virtual_mailbox_maps.cf

user = postfix 

password = postfix123 

hosts = localhost 

dbname = postfix 

query = SELECT CONCAT (domain, '/', maildir) FROM mailbox WHERE username = '% s' AND active = '1'

Open the file master.cf and add to the very end:

vi /etc/postfix/master.cf

submission inet n - n - - smtpd 

    -o smtpd_tls_security_level = may 

    -o smtpd_sasl_auth_enable = yes 

    -o smtpd_sasl_type = dovecot 

    -o smtpd_sasl_path = / var / spool / postfix / private / auth 

    -o smtpd_sasl_security_options = noanonymous 

    -o smtpd_sasl_local_domain = $ myhostname

smtps inet n - 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

dovecot unix - n n - - pipe 

    flags = DRhu user = vmail: vmail argv = / usr / libexec / dovecot / deliver -d $ {recipient}

* Need to make sure that the contents of the file are no other options uncommented for  submission,  smtps and  dovecot (by default, they are not). In this case, we configured postfix on ports 25, 465 and 587.

Restart postfix:

systemctl restart postfix

5. Configuring Dovecot

Install Dovecot with the component to work with the DBMS:

yum install dovecot dovecot-mysql

We configure the way messages are stored:

vi /etc/dovecot/conf.d/10-mail.conf

mail_location = maildir: / home / mail /% d /% u / 

first_valid_gid = 1024

* In this example, the messages will be stored in the advanced maildir format  .

Configure the listener for authentication:

vi /etc/dovecot/conf.d/10-master.conf

service auth { 

  unix_listener / var / spool / postfix / private / auth { 

    mode = 0666 

    user = postfix 

    group = postfix 

  } 

  unix_listener auth-userdb { 

    mode = 0600 

    user = vmail 

    group = vmail 

  } 

}

* Please note that  / var / spool / postfix / private / auth is the same  private / auth that was registered by us in postfix.

Configure authentication in Dovecot:

vi /etc/dovecot/conf.d/10-auth.conf

#! include auth-system.conf.ext 

! include auth-sql.conf.ext

* in this case, we just comment on the usual authentication and remove the comment for using sql-auttification.

Configure the use of encryption:

vi /etc/dovecot/conf.d/10-ssl.conf

ssl = required 

ssl_cert = </etc/ssl/mail/public.pem 

ssl_key = </etc/ssl/mail/private.key

* This setting will tell dovecot to require clients to use encryption.

Let's configure automatic creation of directories when the user first connects to the mailbox:

vi /etc/dovecot/conf.d/15-lda.conf

lda_mailbox_autocreate = yes

We configure the connection to our database:

vi /etc/dovecot/conf.d/auth-sql.conf.ext

passdb { 

  ... 

  args = /etc/dovecot/sql.conf 

}

userdb { 

  ... 

  args = /etc/dovecot/sql.conf 

}

* In this example, we have specified a file that will contain the settings for retrieving users and passwords from the database.

Create a file with the settings for working with mysql:

vi /etc/dovecot/sql.conf

driver = mysql 

connect = host = localhost dbname = postfix user = postfix password = postfix123 

default_pass_scheme = MD5-CRYPT 

password_query = SELECT password FROM mailbox WHERE username = '% u' 

user_query = SELECT maildir, 1024 AS uid, 1024 AS gid FROM mailbox WHERE username = '% u' 

user_query = SELECT CONCAT ('/ home / mail /', LCASE (`domain`), '/', LCASE (` maildir`)), 1024 AS uid, 1024 AS gid FROM mailbox WHERE username = '% u'

And, finally, configure the protocols and interface, which will listen to dovecot:

vi /etc/dovecot/dovecot.conf

protocols = imap imaps pop3 pop3s 

listen = *

* By default, dovecot also listens on ipv6 ( listen = *, ::) . If the server does not use the 6th version of the TCP / IP protocol, errors will appear in the dovecot logs: 

master: Error: service (imap-login): listen (::, 143) failed 

: service (imap-login): listen (::, 993) failed: Address

Generate security certificates

Create a catalog in which to place the certificates:

mkdir -p / etc / ssl / mail

And we will generate them with the following command:

openssl req -new -x509 -days 1461 -nodes -out /etc/ssl/mail/public.pem -keyout /etc/ssl/mail/private.key -subj "/ C = RU / ST = SPb / L = SPb / O = Global Security / OU = IT Department / CN = relay.dmosk.ru "

* the certificate is generated for  1461 days, subj keys  can be arbitrary, CN must be specified in accordance with the name of the server by which we will connect to the mail.

Run the dovecot:

systemctl start dovecot

6. Create the first mailbox and check the server operation

In the browser, enter the path to Postfixadmin in the address bar - http: // <server IP address> / postfixadmin /.

We enter login and password from the administrative account that we created in step 3. We will see the account management page.

Let's move on to the Domain List - New Domain:

Fill out the forms and click on Add Domain:

Now go to Overview - Create a box:

Enter the data for the new user and click on Create a box:

Now you can connect to the server using any email program, for example, Mozilla Thunderbird.

Connection parameters:

7. Install and configure Roundcube Webmail

On the official site go to  the download page of  Roundcube. See the link to the latest stable version of the product:

Use the link to download the program archive:

wget https://github.com/roundcube/roundcubemail/releases/download/1.1.9/roundcubemail-1.1.9.tar.gz

Create a directory where the portal files will be located:

mkdir / usr / share / nginx / html / webmail

And unpack the downloaded archive:

tar -C / usr / share / nginx / html / webmail -xvf roundcubemail-1.1.9.tar.gz --strip-components 1

Copy the config template:

cp /usr/share/nginx/html/webmail/config/config.inc.php.sample /usr/share/nginx/html/webmail/config/config.inc.php

And we open it for editing:

vi /usr/share/nginx/html/webmail/config/config.inc.php

$ config ['db_dsnw'] = 'mysql: // roundcube: roundcube123 @ localhost / roundcubemail'; 

$ config ['enable_installer'] = true;

* We edit the first line, and add the second one. In the first line of the  roundcube: roundcube123 - login and password for accessing the database; localhost  - the database server; roundcubemail  - the name of the database.

We set the apache owner to the portal folder:

chown -R apache: apache / usr / share / nginx / html / webmail

Create a base in MariaDB for the roundcubemail:

mysql -uroot -p

> CREATE DATABASE roundcubemail DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

> GRANT ALL PRIVILEGES ON roundcubemail. * TO roundcube @ localhost IDENTIFIED BY 'roundcube123';

> quit

And load the data into the created database:

mysql -uroot -p roundcube </ usr/share/nginx/html/webmail/SQL/mysql.initial.sql

Install the components necessary for the work of Roundcube:

yum install php-pear php-php-php-php-php-php-pear-Net-SMTP php-pear-Net-IDNA2 php-pear-Mail-Mime

Let's configure php:

vi /etc/php.ini

date.timezone = "Europe / Moscow"

Reboot php-fpm:

systemctl restart php-fpm

Now open the browser and go to http: // <server IP address> / webmail / installer /. At the very bottom click on the Next button . If the button is inactive, check that there are no errors ( NOT OK ).

We check that all items are in the OK state .

After removing the folder with the installation scripts:

\ rm -R / usr / share / nginx / html / webmail / installer

And go to the browser at http: // <server IP address> / webmail /.

8. Protect yourself from viruses

Installing and Configuring ClamAV

Install the antivirus:

yum install clamav clamsmtp clamav-scanner-systemd clamav-update

Configuring postfix:

vi /etc/postfix/main.cf

content_filter = scan: [127.0.0.1]: 10025 

receive_override_options = no_address_mappings

* where  content_filter points to an application that will scan messages; receive_override_optionsallows you to see the original email addresses of emails with viruses.

Now edit master.cf:

vi /etc/postfix/master.cf

We add the following:

scan unix - - n - 16 smtp 

  -o smtp_send_xforward_command = yes 

  -o smtp_enforce_tls = no 

127.0.0.1:10026 inet n - n - 16 smtpd 

  -o content_filter = 

  -o receive_override_options = no_unknown_recipient_checks, no_header_body_checks 

  -o smtpd_helo_restrictions = 

  -o smtpd_client_restrictions = 

  - o smtpd_sender_restrictions = 

  -o smtpd_recipient_restrictions = permit_mynetworks, reject 

  -o mynetworks_style = host 

  -o smtpd_authorized_xforward_hosts = 127.0.0.0 / 8

Restart postfix:

systemctl restart postfix

Configure clamsmtpd:

vi /etc/clamsmtpd.conf

ClamAddress: /var/run/clamd.scan/clamd.sock 

TempDirectory: /var/run/clamd.scan

* Where  ClamAddress is pointing to the path to the socket file - it must match the path in the configuration file for clam scan; TempDirectory - the path for storing temporary files.

Editing the configuration file for clam scan:

vi /etc/clamd.d/scan.conf

PidFile /var/run/clamd.scan/clamd.pid 

LocalSocket /var/run/clamd.scan/clamd.sock 

User clamsmtp

* where  PidFile is the path for the service pid file; LocalSocket - the path to the socket file for interaction with clamsmtp; User - the user from which clamd will be launched.

Let's edit the owner on the directory for the socket file:

chown clamsmtp: clamscan /var/run/clamd.scan

Now let's run the antivirus and run it:

systemctl enable clamsmtpd

systemctl start clamsmtpd

systemctl enable clamd @ scan

systemctl start clamd @ scan

Update

Open the config freshclam and put a comment opposite Example:

vi /etc/freshclam.conf

#Example

We resolve and start the service:

systemctl enable clamd @ freshclam

systemctl start clamd @ freshclam

Run the update:

freshclam

To configure the automatic update, we edit cron:

crontab -e

15 3 * * * / bin / freshclam

* In this example, every day at 03:15 the clamav update process will be started.

Checking

To check, we send a message with the following content:

X5O! P% @ AP [4 \ PZX54 (P ^) 7CC) 7} $ EICAR-STANDARD-ANTIVIRUS-TEST-FILE! $ H + H *

The letter should not reach.

9. Fighting with SPAM

Checking content with Spamassassin

Install spamassassin

yum install spamassassin

Edit master.cf:

vi /etc/postfix/master.cf

For smtp, add the following option: 

smtp inet n - n - - smtpd 

    -o content_filter = spamassassin

And add the following:

spamassassin unix - n n - - pipe 

  flags = R user = spamd argv = / usr / bin / spamc -u spamd -e / usr / sbin / sendmail -f $ sender $ recipient

Updating spamassassin:

sa-update --nogpg

Let's start it and start the service:

systemctl enable spamassassin

systemctl start spamassassin

Restart postfix:

systemctl restart postfix

For automatic updates, add the following to cron:

crontab -e

30 3 * * * / bin / sa-update

* The update will occur every day at 03:30 .

To check the operation of the content antispam, send a message with the following content:

XJS * C4JDBQADN1.NSBN3 * 2IDNEN * GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL * C.34X

Antispam tools Postfix

MTA Postfix has its own mechanism for checking the headers of incoming messages. The rules are placed in 6 sections, which are processed in the following order:

client -> helo -> sender -> relay -> recipient -> data

And so, to configure the antispam in the main.cf configuration file,  add:

vi /etc/postfix/main.cf

= smtpd_client_restrictions 

        permit_mynetworks 

        permit_sasl_authenticated 

        reject_unauth_pipelining 

        permit 

smtpd_helo_restrictions = 

        permit 

smtpd_sender_restrictions = 

        permit_mynetworks 

        permit_sasl_authenticated 

        reject_non_fqdn_sender 

        reject_unknown_sender_domain 

        permit 

smtpd_relay_restrictions = 

        permit 

smtpd_recipient_restrictions = 

        permit_mynetworks 

        permit_sasl_authenticated 

        reject_non_fqdn_recipient 

        reject_unauth_destination

        reject_unknown_recipient_domain 

        reject_unverified_recipient 

        permit 

smtpd_data_restrictions = 

        permit 

smtpd_end_of_data_restrictions = 

        permit

* these are more or less mild rules. They can be used for the first time while testing the server.

To strengthen the protection we add:

smtpd_recipient_restrictions = 

        ... 

        reject_unknown_client_hostname 

        reject_invalid_helo_hostname 

        reject_non_fqdn_helo_hostname 

        reject_unknown_helo_hostname 

        reject_rbl_client bl.spamcop.net 

        reject_rbl_client cbl.abuseat.org 

        reject_rbl_client dul.ru 

        reject_rbl_client dnsbl.abuse.ch 

        permit

* where:

After making all edits, you need to restart Postfix:

systemctl restart postfix

The server is configured - you can use it.

# Servers # UNIX # NGINX # MySQL

--------