-
Notifications
You must be signed in to change notification settings - Fork 1
Email server
-
- 3.1. verify ports
-
- 8.1. Configuration
- 8.1.1. performance tuning
- 8.1. Configuration
-
- 9.1. configuration
- 9.1.1. maibox
- 9.1.2. Dovecot with LMTP
- 9.1.3. Basic doveonf command
- 9.1. configuration
-
- Basic Configuration: no devcot, no SASL, no TLS, system user only
-
- 11.1. configuration
- 11.2. Security
- 11.3. Verify
-
- 12.1. create spamd user/group
- 12.2. Configure postfix
- 12.3. systemd service
-
- 13.1. Create vmail user
- 13.1.1. Postgresql
- 13.1. Create vmail user
-
- 14.1. Create psql user
- 14.2. Log as psql user mailman and connect to thetradinghall db
- 14.3. Add crypto extension
- 14.4. Create tables
- 14.4.1. domainlist
- 14.4.2. mailusers
- 14.5. Create Views
- 14.6. Insert table values
- 14.7. Write queries
- 14.7.1. test queries in DB
- 14.7.2. write postfix query files
- 14.7.3. Test Postfix queries
- 14.7.4. Map queries
- 14.8. Test postfix setup
- 14.9. Modify Dovecot
- 14.10. Postfix milter
- 14.10.1. Configuring
-
- 15.1. Configuration
There are a number of components that make up a complete email system. Below is a brief description of each one:
- Mail User Agent
This is the part of the system that the typical user is likely to be most familiar with. The Mail User Agent (MUA), or mail client, is the application that is used to write, send and read email messages. Anyone who has written and sent a message on any computer has used a Mail User Agent of one type or another.
- Mail Transfer Agent
The Mail Transfer Agent (MTA) is the part of the email system that does much of the work of transferring the email messages from one computer to another (either on the same local network or over the internet to a remote system). Once configured correctly, most users will not have any direct interaction with their chosen MTA unless they wish to re-configure it for any reason. The two most popular choices of MTA available for Linux are sendmail and Postfix.
- Mail Delivery Agent (also called Local Delivery Agent)
Another part of the infrastructure that is typically hidden from the user, the Mail Delivery Agent (MDA) sits in the background and pass messages from an MTA and delivers it to a real or virtual mailbox. We will be running LMTP agent. MDA can performs too filtering on the email messages between the Mail Transfer Agent and the mail client (MUA).We use a spam filter to remove all the unwanted email messages from the system before they reach the inbox of the user’s mail client: Spamassassin
- SMTP
SMTP is an acronym for Simple Mail Transport Protocol. This is the protocol used by the email systems to transfer mail messages from one server to another. This protocol is essentially the communications language that the MTAs use to talk to each other and transfer messages back and forth.
One important point to make about the SMTP protocol is that it does not require authentication. This allows anyone on the Internet to send email to anyone else or even to large groups of people. It is this characteristic of SMTP that makes junk email or spam possible.
- Transport
A virtual transport is a default setting within Postfix that tells the system that this domain is the final destination.
All incoming mails destined to your server shall be received by Postfix (SMTP) and then handed over to Dovecot (LMTP) for storing in the Inbox
Incoming mail (From somewhere) -> Postfix (SMTP) -> Dovecot (LMTP) -> MailBox/Inbox
Outgoing mail (Thunderbird) -> Postfix (SMTP) -> Destination (SMTP) like gmail
Thunderbird <==> Dovecot (IMAP) <==> Inbox
- SASL
Simple Authentication and Security Layer is a framework for authentication and data security in Internet protocols. Application protocols that support SASL typically also support Transport Layer Security, TLS to complement the services offered by SASL. SASL provides a mechanism of authenticating users using their username and password.
By default, postfix uses the $mynetworks parameter to control access, i.e. who can send or relay mail through the mail server. There is no other authentication performed other than checking that the IP address of the user trying to send mail is part of a trusted network as specified in $mynetworks.
If you are only implementing a mail server where all your users are based on the same network then it is unlikely that you will need to use SASL or SSL/TLS. However, if there are mobile users that wish to use the mail server whilst away from base, we need a mechanism to authenticate them as trusted users so that they are able to send mail through the mail server
- TLS
SASL is sending usernames and passwords in plain text across the Internet. This poses a security risk as anyone can potentially intercept this information and steal login details so we need to encrypt the connection. TLS (Transport Layer Security), offer such a mechanism to encrypt communications between two hosts.
465 is needed for SMTP with SSL and 587 for SMTP. You may want to enable only the submission service, since SMTPS is now deprecated.
MSA (Mail submission Agent) will operate on port 587. SMTP uses SSL/TLS authentication type and MSA uses STARTTLS.
# netstat -ltnp
tcp 0 0 0.0.0.0:993 0.0.0.0:* LISTEN 7516/dovecot
tcp 0 0 0.0.0.0:587 0.0.0.0:* LISTEN 7672/master
tcp 0 0 0.0.0.0:143 0.0.0.0:* LISTEN 7516/dovecot
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 7672/master
- dovecot is holding ports 993 (IMAP secure) and 143 (IMAP)
- master (postfix) is holding 25 (SMTP) and 587 (MSA)
An MX record should point to the mail host. Usually this is done from configuration interface of your DNS provider.
NOTE: Some mail servers will not deliver mail to you if your MX record points to a CNAME. For best results, always point an MX record to an A record definition. For more information, see e.g. Wikipedia:List of DNS record types.
AXFR output:
mail.thetradinghall.com. 86400 IN A 212.147.52.214
thetradinghall.com. 86400 IN MX 10 mail.thetradinghall.com.
PTR record are used to map a network interface (IP) to a host name. These are primarily used for reverse DNS. The most common reason for establishing a reverse DNS is for outbound e-mail servers
Using the dig (domain information groper) or host commands, we can get some useful information about server and DNS. They both perform DNS lookups and display the answers that are returned from the name server(s) that were queried.
One can use the dig web interface. This website is especially very useful to check if some large resolver like GOOGLE can verify the reverse DNS.
$ host 212.147.52.214
214.52.147.212.in-addr.arpa domain name pointer dsldevice.lan.
$ host mail.thetradinghall.com
mail.thetradinghall.com has address 212.147.52.214
$ dig -x 212.147.52.214
;; Warning: Message parser reports malformed message packet.
; <<>> DiG 9.10.3-P3-RedHat-9.10.3-10.P3.fc23 <<>> -x 212.147.52.214
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31946
;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;214.52.147.212.in-addr.arpa. IN PTR
;; ANSWER SECTION:
214.52.147.212.in-addr.arpa. 1200 IN PTR dsldevice.lan.
;; Query time: 1 msec
;; SERVER: 192.168.1.254#53(192.168.1.254)
;; WHEN: Tue Feb 09 15:54:38 CET 2016
;; MSG SIZE rcvd: 72
$ dig -x thetradinghall.com
; <<>> DiG 9.10.3-P3-RedHat-9.10.3-10.P3.fc23 <<>> -x thetradinghall.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 60141
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;com.thetradinghall.in-addr.arpa. IN PTR
;; AUTHORITY SECTION:
in-addr.arpa. 3600 IN SOA b.in-addr-servers.arpa. nstld.iana.org. 2015072881 1800 900 604800 3600
;; Query time: 24 msec
;; SERVER: 192.168.1.254#53(192.168.1.254)
;; WHEN: Tue Feb 09 15:55:27 CET 2016
;; MSG SIZE rcvd: 128
$ dig +nocmd -x 212.147.52.214 +noadditional +noquestion +nocomments +nocmd +nostats @8.8.4.4
214.52.147.212.in-addr.arpa. 21599 IN PTR 212-147-52-214.fix.access.vtx.ch.
The Sender Policy Framework (SPF) is an open standard specifying a technical method to prevent sender address forgery.
If the postfix server sends out mails with "from address" of [email protected], then the TXT DNS records of example.com must contain the SPF validation information to indicate that this server is authorised to send out mails on behalf of example.com.
This will ensure that spammers may not spoof your email domain.
- Edit your nameserver's zone entries and add a TXT record containing the following:
v=spf1 ip4:192.168.1.1/24 mx a:thetradinghall.com include:_spf.google.com ~all
- Verify:
use the Online SPF Record Testing Tools
Install postfix package. Start the service with systemctl.
NOTE:
-
postfix logs are not in the usual
/var/log/mail.logbut are accessed with$ journalctl --unit postfix -r(-r is for reverse: start from the last logs). -
All needed service sockets are stored in
/var/spool/postfixdirectory.
The /etc/postfix/main.cf file is the main one where everything is configured.
The parameters are in the form parameter = value and you use it by putting
a "$" character in front of its name: other_parameter = $parameter.
As this is a very long file with lots of commented lines, best is to use the postconf command to see or change seetings.
- List default settings
$ postconf -df
- Edit a parameter
# postconf -e name=value
- List parameters
$ postconf -n
Install the dovecot, dovecot-pgsql packages. Start the service with systemctl.
Dovecot is an open source IMAP and POP3 email server for Linux/UNIX-like systems, written with security primarily in mind. We will only use the imap service.
-
Dovecot shall be given a location to store the incoming mails handed over by Postfix.
-
A separate system user account shall be created and given to dovecot so that dovecot can read/write the mail storage directory. The user is called "vmail" and has to be created.
-
Dovecot shall host secure IMAP service to allow email clients to read Inbox.
-
Dovecot shall provide the SASL authentication service to Postfix via a unix socket. The same username/password shall work with both Postfix (SMTP server) and Dovecot (IMAP/POP server)
-
We shall use the full email address ([email protected]) as the username and set a encrypted password too.
- default and currecnt settings can be listed this way:
$ doveconf -d
# dovecot -n
- format : Maildir
Each mailbox folder is a directory and each message a file. This improves efficiency because individual emails can be modified, deleted and added without affecting the mailbox or other emails
- structure
By default Dovecot uses Maildir++ directory layout for organizing mailbox directories. This means that all the folders are directly inside ~/Maildir directory:
~/Maildir/new, ~/Maildir/cur and ~/Maildir/tmp directories contain the messages for INBOX.
You can also optionally use the "fs" layout by appending :LAYOUT=fs to mail_location. This makes the folder structure look like:
~/Maildir/new, ~/Maildir/cur and ~/Maildir/tmp directories contain the messages for INBOX, just like with Maildir++.
~/Maildir/folder/ is a mailbox folder
- userdb
Use an user data base lookup. This will override any dovecot setting.
- passdb
Dovecot authenticates users against password databases. These databases simply verify if the given password is correct for the user. Dovecot doesn't get the correct password from the database, it only gets a "success" or a "failure" reply. Dovecot does a lookup based on the username and possibly other information (e.g. IP address) and verifies the password validity itself.
Fields that the lookup can return: -password -user
- Edit:
/etc/dovecot.conf
-----------------
protocols = imap lmtp
-
socket is defined in
/etc/dovecot/conf.d/10-master.conf -
Edit:
/etc/postfix/main.cf
--------------------
virtual_transport = lmtp:unix:private/dovecot-lmtp
- Dynamic address verification with LMTP
With Dovecot 2.0 you can also use LMTP and the Postfix setting "reject_unverified_recipient" for dynamic address verification. It's really nice because Postfix doesn't need to query an external datasource (MySQL, LDAP, postgreSQL...)
The $ dovadmin command list/set parameters.
The main configuration file is /etc/dovecot/dovecot.conf. Additional configuration are writen in files inside the /etc/dovecot/conf.d/ directory.
In all these files, there are a lot of parameter values and commented lines. A good practice is indeed to use the postconf command to list values. See man dovecot, man doveconf.
NOTE: with Fedora, the driver parameter must be set within two different files:
/etc/dovecot/conf.d/auth-sql.conf.ext
--------------
driver = sql
/etc/dovecot/dovecot-sql.conf.ext
--------------
driver = pgsql
- List actual configuration settings
$ dovconf -a
- List actual configuration parameters from a file
# doveconf -a -c config_file
- List non default actual configuration parameters
$ doveconf -n
- List password scheme enabled:
$ doveadm pw -l
- Canonical versus hosted versus other domains Most Postfix systems are final destination for only a few domain names. These include the hostnames and the IP addresses of the machine that Postfix runs on.
Besides the canonical domains, Postfix can be configured to be final destination for any number of additional domains. These domains are called hosted, because they are not directly associated with the name of the machine itself.
In our case, thetradinghall.com is the final destination thus the canonical one.
- Transport
With the Postfix virtual mailbox delivery agent, every recipient address can have its own virtual mailbox. The agent is designed for virtual mail hosting services. Originally based on the Postfix local(8) delivery agent, this agent looks up recipients with map lookups of their full recipient address, instead of using hard-coded unix password file lookups of the address local part only.
Our transport will thus be virtual.
- Postfix Address Classes
Postfix version 2.0 introduces the concept of address classes. This is a way of grouping recipient addresses by their delivery method. In our case, we use the local domain class. It purpose: final delivery for traditional UNIX system accounts and traditional Sendmail-style aliases.
- Local Recipients
As of Postfix version 2.0, the Postfix SMTP server rejects mail for unknown recipients in local domains. The local_recipient_maps parameter, $local_recipient_maps, specifies lookup tables with all names or addresses of local recipients. A recipient address is local when its domain matches $mydestination, $inet_interfaces or $proxy_interfaces. If a local username or address is not listed in $local_recipient_maps, then the Postfix SMTP server will reject the address with "User unknown in local recipient table".
NOTE: some variables settings can be either in a /etc/postfix/MyVariable or through the DB query. We will emphasis on the later.
The file has been changed with the following lines:
/etc/postfix/main.cf
----------------------------
myhostname = thetradinghall.com
mydomain = thetradinghall.com
myorigin = $mydomain
inet_interfaces = localhost,192.168.1.94
mynetworks = 127.0.0.0/8,212.147.52.214
home_mailbox = Maildir/
NOTE : the Maildir format is largely prefered to Mailbox. See this post.
File /etc/postfix/master.cf is the master configuration file where you can specify what kinds of protocols you will serve. Postfix daemon processes can be configured via the master.cf file to run in a chroot jail. The processes run at a fixed low privilege and with file system access limited to the Postfix queue directories /var/spool/postfix. This provides a significant barrier against intrusion.
The default specifies that no Postfix daemon runs chrooted
$ telnet thetradinghall.com 25
Trying 212.147.52.214...
Connected to thetradinghall.com.
Escape character is '^]'.
220 mail.thetradinghall.com ESMTP Postfix
ehlo mail.thetradinghall.com
250-mail.thetradinghall.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 SMTPUTF8
mail from:MyUser
250 2.1.0 Ok
rcpt to:MyUser
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 2.0.0 Ok: queued as 788FC21E39
quit
221 2.0.0 Bye
Connection closed by foreign host.
You have new mail.
$ cat /var/spool/mail/poisonivy
From [email protected] Tue Jan 26 15:13:14 2016
Return-Path: <[email protected]>
X-Original-To: poisonivy
Delivered-To: [email protected]
Received: from mail.thetradinghall.com (unknown [212.147.52.214])
by mail.thetradinghall.com (Postfix) with ESMTP id 788FC21E39
for <poisonivy>; Tue, 26 Jan 2016 15:12:42 +0100 (CET)
test
Currently the Postfix SMTP server supports the Cyrus SASL and Dovecot SASL implementations. We will use the latest one.
1- Edit
/etc/postfix/master.cf
--------------------------------------------
smtp inet n - n - - smtpd
submission inet n - n - - smtpd
-o smtpd_relay_restrictions=permit_mynetworks,permit_sasl_authenticated,defer_unauth_destination
-o smtpd_sasl_auth_enable=yes
-o broken_sasl_auth_clients=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_sasl_security_options=noanonymous
-o smtpd_sasl_local_domain=$myhostname
2 - Edit:
/etc/dovecot/conf.d/10-auth.conf
-----------------------------------
!include auth-passwdfile.conf.ext
3- Edit
/etc/dovecot/conf.d/10-auth.conf
------------------------------
auth_mechanisms = plain login
4- Edit
/etc/dovecot/conf.d/10-master.conf
-----------------------------------
service imap-login {
inet_listener imap {
port = 143
address = *
}
}
.............
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
}
.........
auth_mechanisms = plain login
5- create a user. Edit:
/etc/dovecot/users
-------------------
test:{PLAIN}test1234
6- encode username and password: A Base64 encoded string of our username and password may be generated using perl:
$ perl -MMIME::Base64 -e 'print encode_base64("\000test\000test1234");'
XXXYYYZZZZZ=
7- test with Telnet
% telnet mail.thetradinghall.com 587
Trying 212.147.52.214...
Connected to mail.thetradinghall.com.
Escape character is '^]'.
220 mail.thetradinghall.com ESMTP Postfix
EHLO thetradinghall.com
250-mail.thetradinghall.com
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
AUTH PLAIN AHRlc3QAdGVzdDEyMzQ=
235 2.7.0 Authentication successful
1- generate certificate
We will use the tradinghall.com ssl letsencrypt certification.
2- edit:
/etc/postfix/master.cf
-------------------------
-o smtpd_tls_security_level=may
-o smtpd_tls_auth_only=yes
3- Edit:
/etc/postfix/main.cf
---------------------------
smtpd_tls_key_file = /etc/letsencrypt/live/thetradinghall.com/privkey.pem
smtpd_tls_cert_file = /etc/letsencrypt/live/thetradinghall.com/fullchain.pem
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_timeout = 3600s
smtpd_tls_session_cache_database = btree:/storage/cache
tls_random_source = dev:/dev/urandom
tls_random_exchange_name = /var/lib/postfix/prng_exch
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3
smtpd_tls_mandatory_ciphers = high
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
4- Edit
/etc/dovecot/conf.d/10-master.conf
----------------------------------
service imap-login {
inet_listener imap {
port = 143
adress = *
}
inet_listener imaps {
port = 993
ssl = yes
}
}
5- Edit
/etc/dovecot/conf.d/10-ssl.conf
-----------------------------
ssl = required
ssl_key = /etc/letsencrypt/live/thetradinghall.com/privkey.pem
ssl_cert = /etc/letsencrypt/live/thetradinghall.com/fullchain.pem
ssl_dh_parameters_length = 2048
If everything is working as expected, we should see the server offering STARTTLS and because we have specified smtpd_tls_auth_only = yes , plain text SASL authentication (AUTH PLAIN LOGIN and AUTH=PLAIN LOGIN) is no longer available.
By default, ``disable_plaintext_auth_ is set to yes. disable_plaintext_auth=yes AND ```ssl=required``` guarantee that the entire connection is protected against eavesdropping (SSL/TLS encrypts the rest of the connection)
$ telnet mail.thetradinghall.com 587
Trying 212.147.52.214...
Connected to mail.thetradinghall.com.
Escape character is '^]'.
220 mail.thetradinghall.com ESMTP Postfix (3.0.3)
EHLO thetradinghall.com
250-mail.thetradinghall.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 SMTPUTF8
6- verify
$ openssl s_client -connect mail.thetradinghall.com:imaps
CONNECTED(00000003)
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 X1
verify return:1
depth=0 CN = thetradinghall.com
verify return:1
---
Certificate chain
0 s:/CN=thetradinghall.com
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X1
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X1
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
Basically DKIM means digitally signing all messages on the server to verify the message actually was sent from the domain in question and is not spam or pishing (and has not been modified). It enforces the authenticity of the mails and be treated as legitimate by major mail services like gmail. DKIM attaches a new domain name identifier to a message and uses cryptographic techniques to validate authorization for its presence.
The sender's mail server signs outgoing email with the private key.
When the message arrives, the receiver (or his server) requests the public key from the domain's DNS and verifies the signature.
This ensures the message was sent from a server who's private key matches the domain's public key.
DKIM is an Internet Standard that enables a person or organisation to associate a domain name with an email message. This, in effect, serves as a method of claiming responsibility for a message
install opendkim package. Start the service with systemctl.
BEFORE running OpenDKIM:
- make Postfix aware of OpenDKIM
- generate keys for the domain
- edit DNS records to publish public keys (if signing)
NOTE: opendkim.conf has been moved from /etc to /etc/opendkim. To reflect this change, edit /etc/sysconfig/opendkim accordingly.
1- Edit opendkim.conf file. Defaults settings are OK, we just need to uncomment these lines:
/etc/opendkim/opendkim.conf
---------------------
Selector mail
KeyFile /etc/opendkim/keys/thetradinghall/mail.private
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts
Keys will be stored in /etc/opendkim/ directory.
1- Edit:
/etc/opendkim/TrustedHosts
-------------------------
127.0.0.1
::1
mail.thetradinghall.com
192.168.1.94/24
2- Keytable A key table contains each selector/domain pair and the path to their private key. Uncomment and edit the line in:
/etc/opendkim/Keytable
----------------------
mail._domainkey.thetradinghall.com thetradinghall.com:mail:/etc/opendkim/keys/thetradin ghall/mail.private
3- Signing table
This file is used for declaring the domains/email addresses and their selectors. Edit:
/etc/opendkim/SigningTable
------------------------------
*@thetradinghall.com default._domainkey.thetradinghall.com
4- generate the key
$ cd /etc/opendkim/keys
# mkdir thetradinghall
$ su
# cd thetradinghall
# opendkim-genkey -t -s mail -d thetradinghall.com
# chown opendkim:opendkim mail.private
This command will create two files, mail.private is our private key and mail.txt contains the public key
5- Add public key to DNS
The public key is defined under the p parameter in mail.txt.
Create a new text entry in Hurricane Electric.
Name : mail._domainekey.thetradinghall.com
"v=DKIM1; k=rsa; p=XXXYYYYYZZZZZ"
6- Verify
-
Open DkimCore check page. Our selector is mail
-
Run
# opendkim-testkey -d thetradinghall.com -k /etc/opendkim/keys/thetradinghall/mail.private -s mail -vvv -x /etc/opendkim/opendkim.conf
opendkim-testkey: key loaded from /etc/opendkim/keys/thetradinghall/mail.private
opendkim-testkey: checking key 'mail._domainkey.thetradinghall.com'
opendkim-testkey: key OK
- Run:
$ dig mail._domainkey.thetradinghall.com TXT
- Run:
$ swaks -t [email protected] -f [email protected]
1- The OpenDKIM daemon does not need to run as root at all (the configuration suggested earlier will have OpenDKIM drop root privileges by himself but systemd can do this too and much earlier).
Edit:
/etc/tmpfiles.d/opendkim.conf
--------------------------
D /var/run/opendkim 0750 opendkim postfix
2- If your mail daemon is on the same host as the OpenDKIM daemon, there is no need for localhost tcp sockets and unix sockets may be used instead, allowing classic user/group access controls. OpenDKIM is using the /tmp folder by default whereas it could use its own folder with additional access restrictions.
- Edit:
/etc/opendkim/opendkim.conf
--------------------
Socket local:/run/opendkim/opendkim.sock
TemporaryDirectory /run/opendkim
- Edit:
/etc/postfix/master.cf
---------------------
smtpd_milters = unix:/run/opendkim/opendkim.sock
non_smtpd_milters = unix:/run/opendkim/opendkim.sock
for <[email protected]>; Tue, 9 Feb 2016 17:22:46 +0100 (CET)
DKIM-Filter: OpenDKIM Filter v2.10.3 mail.thetradinghall.com F1C9424F46
Authentication-Results: mail.thetradinghall.com;
dkim=pass (2048-bit key) header.d=gmail.com [email protected] header.b=qHLRol3C
Install package spamassassin. SpamAssassin is installed «out of the box» in /usr/share/spamassassin with a good set of spam identification rules. Start the service and timer with systemctl.
Main configuration files is /etc/mail/spamassassin/local.cf.
# groupadd spamd
# useradd -r -s /usr/bin/nologin -d /storage/log/spamassassin -g spamd spamd
# mkdir /storage/log/spamassassin
# chown spamd:spamd /storage/log/spamassassin
Some spam checks can be configured with Postfix and/or SpamAssassin - but it is recommend to do it NOT on both for performance reasons. Specially all RBL lookups should be deactived in the Postfix configuration file main.cf
Edit:
/etc/postfix/master.cf
-------------------------
smtp inet n - n - - smtpd -o content_filter=spamassassin
submission inet n - n - - smtpd -o content_filter=spamassassin
.................
spamassassin unix - n n - - pipe flags=R user=spamd argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
# systemctl edit spamassassin.service
[Service]
User=spamd
Group=spamd
Virtual mail are emails that does not map to a user account (/etc/passwd).
This configuration requires a user to own the database and all the virtual domains that will receive mail. We will use a vmail user insted of the mail user.
- store all emails in
/storage/vmail. Directory owner is vmail:vmail
# groupadd -g 5000 vmail
# useradd -u 5000 -g vmail -s /usr/bin/nologin -d /storage/vmail -m vmail
# passwd vmail
# mkdir /storage/vmail/vhosts/thetradinghall.com
# chown -R vmail:vmail /storage/vmail/
# chmod 700 /storage/vmail
# gpasswd --add vmail mail
- Edit:
/db/pgsql/data/pg_ident.conf
----------------------------
mailmap postfix mailman
mailmap dovecot mailman
mailmap postgres mailman
This file controls PostgreSQL user name mapping. It maps external external user names to their corresponding PostgreSQL user names.
mailmap is a freely choosen name.
- Edit:
/db/pgsql/data/pg_hba.conf
---------------------------
# TYPE DATABASE USER ADDRESS METHOD OPTION
local thetradinghall mailman peer map=mailmap
few basic syntax guidelines:
- Only one host entry per line is allowed and these lines may not wrap
- Each line has multiple sections and each section must be separated by spaces or tabs
The peer authorization method works by obtaining the client's operating system user name from the kernel and using it as the allowed database user name (with optional user name mapping). This method is only supported on local connections.
local is for unix socket connections
- Restart postgresql
Install postgresql, postfix-pgsql packages.
We are creating a thetradinghall database with mailusers and domainlist tables owned by mailman user, and inside a email schema.
NOTE: There are several reasons why one might want to use schemas:
To allow many users to use one database without interfering with each other.
To organize database objects into logical groups to make them more manageable.
Third-party applications can be put into separate schemas so they do not collide with the names of other objects.
The mailman psql user will own the email tables.
$ su - postgres
postgres@poppy ➤➤ ~ % psql postgres
Password:
postgres=# CREATE USER mailman PASSWORD 'XXXYYY';
CREATE ROLE
postgres=# CREATE GROUP virtual_mail LOGIN;
CREATE ROLE
postgres=# GRANT virtual_mail TO mailman;
GRANT ROLE
postgres=# CREATE DATABASE thetradinghall WITH OWNER mailman;
CREATE DATABSE
postgres=# \l
.....
thetradinghall | mailman | UTF8 | en_US.UTF8 | en_US.UTF8
postgres=# \c thetradinghall mailman
Password for user mailman:
You are now connected to database "thetradinghall" as user "mailman".
verify:
postgres@poppy ➤➤ pg_dumpall -g | grep mailman
Password:
14:CREATE ROLE mailman;
15:ALTER ROLE mailman WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN NOREPLICATION PASSWORD 'XXXXXYYYYYYYYYY';
28:GRANT virtual_mail TO mailman GRANTED BY postgres;
poisonivy@poppy ➤➤ ~ % su - postgres
Last login: Sun Jan 31 14:23:23 CET 2016 on pts/0
postgres@poppy ➤➤ ~ % psql -d thetradinghall -U mailman
Password for user mailman:
psql (9.4.5)
Type "help" for help.
thetradinghall=>
NOTE: Linux glibc has to be built with blowfish. Otherwise, dovedamin will NOT decript Blowfish encrypted password. This is not the case of Fedora, so we will not use this extension.
We want a strong bf/5 password, a BlowFish string hashed 5 times. An encryption of this type will take a 1.2 Ghz computer about 33 years to crack passwords only containing a-z. If you would use plain old md5 it would take that same computer only 1 day.
To make that hash on the fly we can use the crypt() and gen_salt() functions of PostgreSQL.
-
Install postgresql-contrib package.
-
Coonect to DB
postgres=# CREATE EXTENSION pgcrypto;
- Edit:
/etc/dovecot/dovecot-sql.conf.ext
----------------------------------
default_pass_scheme = BLF-CRYPT
This table contains list of domains if we want to use multi domains. We use the email schema.
thetradinghall=> CREATE TABLE email.domainlist (
domain_name TEXT NOT NULL PRIMARY KEY,
transport TEXT NOT NULL
);
CREATE TABLE
This table contains list of users with associated email address and password
To generate a SHA512 password with doveadm, issue the following command:
doveadm pw -s SHA512 -p yourpassword
thetradinghall=> CREATE TABLE email.mailusers (
username TEXT NOT NULL,
password TEXT NOT NULL,
domain_name TEXT NOT NULL,
created timestamp with time zone not null default now(),
CONSTRAINT mailusers_pkey PRIMARY KEY (username,domain_name),
CONSTRAINT mailusers_domain_fk FOREIGN KEY (domain_name)
REFERENCES email.domainlist(domain_name)
);
CREATE TABLE
thetradinghall=> TABLE email.mailusers;
username | password | domain_name | created
----------+----------+-------------+---------
(0 rows)
thetradinghall=> ALTER TABLE email.mailusers
ALTER COLUMN domain_name SET DEFAULT 'thetradinghall.com';
ALTER TABLE
thetradinghall=> GRANT ALL ON email.mailusers TO mailman;
GRANT
thetradinghall=> GRANT ALL ON email.domainlist TO mailman;
GRANT
thetradinghall=> \dp email.mailusers
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
--------+------+-------+-------------------------+--------------------------
email | mailuser | table | mailman=arwdDxt/mailman |
(1 row)
- List table
thetradinghall=> \dt email.
We will create one view to add the mail home directory and emal adress to our table.
thetradinghall=> CREATE VIEW email.db_query AS
SELECT *,((mailusers.domain_name || '/'::text) || mailusers.username) || '/'::text AS home_dir,
username||'@'||domain_name AS email_address
FROM email.mailusers;
CREATE VIEW
thetradinghall=> \d+ email.db_query
View "email.db_query"
Column | Type | Modifiers | Storage | Description
---------------+--------------------------+-----------+----------+-------------
username | text | | extended |
password | text | | extended |
domain_name | text | | extended |
created | timestamp with time zone | | plain |
home_dir | text | | extended |
email_address | text | | extended |
View definition:
SELECT mailusers.username,
mailusers.password,
mailusers.domain_name,
mailusers.created,
((mailusers.domain_name || '/'::text) || mailusers.username) || '/'::text AS home_dir,
(mailusers.username || '@'::text) || mailusers.domain_name AS email_address
FROM email.mailus
- List views:
thetradinghall=> \dv email.
- First we need to crypt and salt the password. Using dovadmn:
# doveadm pw -s ssha512 -r 100
TIP : The best way is to do the crypto on the client or application server, so the database has no idea what the keys are and cannot decrypt the data.
thetradinghall=> INSERT INTO email.domainlist (
domain_name,
transport
) VALUES (
'thetradinghall.com',
'virtual:'
);
INSERT 0 1
thetradinghall=> TABLE email.domainlist
;
id | domain_name | transport
----+--------------------+-----------
1 | thetradinghall.com | virtual:
(1 row)
thetradinghall=> INSERT INTO email.mailusers (username,password) VALUES ('arnaud.gaboury',ZZZZXXXXX);
INSERT 0 1
thetradinghall=> TABLE email.mailusers;
username | password | domain_name
| created
----------------+--------------------------------------------------------------+---------------
-----+-------------------------------
arnaud.gaboury | ZZZZZZZXXXXXXXXXYYYYYYY | thetradinghall
.com | 2016-02-04 09:48:58.834774+01
(1 row)
4- Verify
thetradinghall=> \dt email.
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+---------
email | domain | table | mailman
email | mailusers | table | mailman
- It is recommanded to test first in our DB the queries needed by Postfix.
- get home_dir
thetradinghall=> SELECT home_dir FROM email.db_query WHERE username='arnaud.gaboury';
home_dir
------------------------------------
thetradinghall.com/arnaud.gaboury/
(1 row)
- get email_address
thetradinghall=> SELECT email_address FROM email.db_query WHERE username='arnaud.gaboury';
email_address
-----------------------------------
[email protected]
(1 row)
- get transport
thetradinghall=> SELECT transport FROM email.domainlist WHERE domain_name='thetradinghall.com';
transport
-----------
virtual:
(1 row)
we have to instruct Postfix to get its information not from files but from the database. This is done by creating mapping files for the different Postfix mechanisms.
1- We need to add some configuration files for Postfix. For practical reason, they will be placed in a /etc/postfix/pgsql/ directory
NOTE:
%s This is replaced by the input key. SQL quoting is used
to make sure that the input key does not add unexpected
metacharacters.
%u When the input key is an address of the form user@domain,
%u is replaced by the SQL quoted local part of the
address. Otherwise, %u is replaced by the entire search
string. If the localpart is empty, the query is sup-
pressed and returns no results.
%d When the input key is an address of the form user@domain,
%d is replaced by the SQL quoted domain part of the
address. Otherwise, the query is suppressed and returns
no results.
# mkdir /etc/postfix/pgsql
2- We will use the postgresql unix socket to connect postfix to.Edit:
/etc/postfix/pgsql/maildir.cf
-------------------------
user=mailman
password=XXXYYYY
hosts=unix:/run/postgresql
dbname=thetradinghall
query=SELECT home_dir FROM email.db_query WHERE username='%u'
/etc/postfix/pgsql/address.cf
----------------------------------
user=mailman
password=XXXXXYY
hosts=/run/postgresql
dbname=thetradinghall
query=SELECT email_address FROM email.db_query WHERE username='%u'
/etc/postfix/pgsql/transport.cf
----------------------------------
user=mailman
password=XXXYYYY
hosts=/run/postgresql
dbname=thetradinghall
query=SELECT transport FROM email.domainlist WHERE domain_name='%s'
3- limit read/write access
Postfix will emit a warning if group or other have write access to our pgsql files
# chown root:postfix -R /etc/postfix
# chmod 640 /etc/postfix/pgsql/*.cf
# postmap -q arnaud.gaboury pgsql:/etc/postfix/pgsql/maildir.cf
thetradinghall.com/arnaud.gaboury/
# postmap -q arnaud.gaboury pgsql:/etc/postfix/pgsql/address.cf
[email protected]
# postmap -q thetradinghall.com pgsql:/etc/postfix/pgsql/transport.cf
virtual:
Now that we have our files ready for Postfix, we still need to tell it to use these files to communicate with PostgreSQL.
Edit:
/etc/postfix/main.cf
---------------------
..............
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_mailbox_base = /storage/vmail/
transport_maps = pgsql:/etc/postfix/pgsql/transport.cf
virtual_mailbox_maps = pgsql:/etc/postfix/pgsql/maildir.cf
#virtual_mailbox_domains = pgsql:/etc/postfix/pgsql/domain.cf
virtual_transport = lmtp:unix:private/dovecot-lmtp
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
local_recipient_maps = $virtual_mailbox_maps $alias_maps
NOTE:
-
The virtual_mailbox_domains setting tells Postfix that example.com is a so-called virtual mailbox domain. It default to $virtual_mailbox_maps, thus the commented line to explictly show we took care of this variable.
-
NEVER list a virtual MAILBOX domain name as a mydestination domain!
-
The virtual_mailbox_maps parameter specifies the lookup table with mailbox (or maildir) pathnames.
-
The
/etc/aliasesfiles map a list of system username to their postfix recipient username. Run# newaliasesafter updates.
Use Telnet and journalctl to view postfix logs then correct when needed
$ telnet mail.thetradinghall.com 587
Trying 212.147.52.214...
Connected to mail.thetradinghall.com.
Escape character is '^]'.
220 mail.thetradinghall.com ESMTP Postfix (3.0.3)
EHLO thetradinghall.com
250-mail.thetradinghall.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250 SMTPUTF8
mail from:<[email protected]>
250 2.1.0 Ok
rcpt to:<[email protected]>
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
From: <[email protected]>
Subject: Test
.
250 2.0.0 Ok: queued as B71D824EA0
quit
221 2.0.0 Bye
Connection closed by foreign host
WARNING: with some mail providers like Gmail, you need to add again in the body the FROM and a Subject. In case they are missing, the email will be refused as non rfc2822 compliant.
NOTE: If you find that you are receiving 5.1.x errors while trying to send SMTP emails it may be that your mail server has either the parameter strict_rfc821_envelopes = yes or adheres strictly to the ESMTP (RFC 5321) protocols which require email addresses to be enclosed in < > as in "John Doe [email protected]".
1- Edit :
/etc/dovecot/conf.d/10-mail.conf
--------------------------------
mail_location = maildir:/storage/vmail/%d/%u
..............
mail_privileged_group = vmail
--------------------------------
2- Edit :
/etc/dovecot/conf.d/10-auth.conf
-------------------------------
....
!include auth-sql.conf.ext
#!include auth-passwdfile.conf.ext
------------------------------
3- Edit:
/etc/dovecot/conf.d/auth-sql.conf.ext
------------------------------------
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/storage/vmail/%d/%n
}
4- Edit:
NOTE: dovecot will retrieve the password from the user email adress. Thus we need to use this one as argument.
/etc/dovecot/dovecot-sql.conf.ext
----------------------------------
driver = pgsql
connect = host=/run/postgresql/ dbname=thetradinghall user=mailman password=XXXYYYY
default_pass_scheme = BLF-CRYPT
password_query = SELECT password \
FROM email.email_address WHERE email_address='%s';
5- Limit access to dovecot
# chown -R vmail:dovecot /etc/dovecot
# chmod -R o-rwx /etc/dovecot
6- Edit:
/etc/dovecot/conf.d/10-master.conf
---------------------------------
service imap-login {
inet_listener imap {
port = 0
}
inet_listener imaps {
port = 993
ssl = yes
}
......................
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
..............
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
unix_listener auth-userdb {
mode = 0600
user = vmail
#group =
}
# Auth process is run as this user.
user = dovecot
}
..................
service auth-worker {
user = vmail
}
Restart dovecot
% nslookup mail.thetradinghall.com 8.8.8.8
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: mail.thetradinghall.com
Address: 212.147.52.214
Postfix implements support for the Sendmail version 8 Milter (mail filter) protocol. This protocol is used by applications that run outside the MTA to inspect SMTP events (CONNECT, DISCONNECT), SMTP commands (HELO, MAIL FROM, etc.) as well as mail content (headers and body). All this happens before mail is queued.
The reason for adding Milter support to Postfix is that there exists a large collection of applications, not only to block unwanted mail, but also to verify authenticity (opendkim, clamav)
Amavis or more better AMaViS stands for A Mail Virus Scanner, it, well, scans for viruses and checks for spam. Amavis is a very powerful interface between Postfix and third-party programs. Those third-party applications are most commonly ClamAV for virus scanning and Spamassassin for spam filtering.
Install amavisd-new, clamav, clamav-update, clamav-server, package. It will create a amavis user and group.
- Create clamav system user and group, and add it in amavis group.
# useradd -r -s /usr/bin/nologin clamav
# usermod -G amavis clamav
- Socket is
/var/run/clamd.amavisd/clamd.sock
chown -R clamav:clamav /var/run/clamd.amavisd/
Now amavis will use ClamAV as its primary virus scanner.
Swaks is a featureful, flexible, scriptable, transaction-oriented SMTP test toolis a featureful, flexible, scriptable, transaction-oriented SMTP test tool
- Email server on Fedora
- Fedora official documentation: mail servers
- Archlinux wiki: postfix
- Ostechnix - setup Postfix/Dovecot
- Postfix dovecot on Debian, no db
- Digital Ocean: dkim and postfix
- SpamAssassin and Postfix
- Digital Ocean Spamassassin
- Linode guide: Dovecot, Postfix, MySql
- Rackspace: configure spamassassin and Postfix
- blog : installing full email server on CentOS Dovecot, Postfix, Postgresql
- Dovecot postgresql wiki
- Dovecot wiki: auth database
- Cent OS wiki
- Cent OS wiki Postfix restrictions
- Workaround setting up dovecot
- Blog about PTR record
- Postfix security
- DKIM validator
- Postfix performance tuning
- mailinabox: setup scripts for all mail services