Skip to main content

How to Secure Postfix/Dovecot on CWP Email Server on CentOS 7?

At first I would like thank to CWP team for their great effort at $11.99. It has corporate mail features better than Cpanel and others. BTW It's my personal opinion. CWP team has changes many options on Postfix and Dovecot Configuration. It is very important to secure Postfix & Dovecot for Production server that will never expose your internal office or user home network. I did some little research and studies a lot to learn Postfix & Dovecot configuration. Lets Explain my scenario: 

I have a VPS and it has two IPs. Both IP has valid PTR records. You must configure a valid FQDN for your IPs. My Details are below: 

My Primary Domain: rubelhossain.com 
Server FQDN : mx1.rubelhossain.com  ---  60.141.190.140  (IP for Shared Hosting)
Sub-Domain   : mx2.rubelhossain.com  ---  60.141.190.142  (IP for sending Outgoing Email)

Now build your Mail Server with the following options that mentioned in below snapshot

How to Rebuild CWP Email Server?

You can follow the link to Build your own CWP Mail Server How to Build Postfix + Dovecot Mail Server with Anti-Spam Solutions on CWP Server? Here I used Policyd server that enables hourly rate limiting per domain.

This is also very important to publish DNS records such as A, SPF, MX. DKIM & DMARC records. It is better to use cloudflare DNS for your primary domain. I used Cloudflare for many reasons like as DDOS protection, very quick DNS Propagation & If you have any issues to Configure your DNS, check the following Tutorial :

Now open your postfix main configuration file and use the following :

# vi  /etc/postfix/main.cf

# postfix config file

# uncomment for debugging if needed
#soft_bounce=yes

# postfix main
mail_owner = postfix
setgid_group = postdrop
delay_warning_time = 4

smtp_address_preference = ipv4
inet_protocols = ipv4
#smtp_bind_address = 60.141.190.140

# postfix paths
html_directory = no
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
queue_directory = /var/spool/postfix
sendmail_path = /usr/sbin/sendmail.postfix
newaliases_path = /usr/bin/newaliases.postfix
mailq_path = /usr/bin/mailq.postfix
manpage_directory = /usr/share/man

# network settings
inet_interfaces = all
mydomain = rubelhossain.com
myhostname = mx1.rubelhossain.com
mynetworks = $config_directory/mynetworks

mydestination = $myhostname, localhost.$mydomain, localhost
#mydestination = $myhostname = mx1.rubelhossain.com
relay_domains = proxy:mysql:/etc/postfix/mysql-relay_domains_maps.cf

# mail delivery
recipient_delimiter = +

# mappings
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

#transport_maps = hash:/etc/postfix/transport
transport_maps = regexp:/etc/postfix/transport.microsoft,
		 hash:/etc/postfix/transport

#header_checks = pcre:/etc/postfix/header_checks
header_checks = regexp:/etc/postfix/header_checks

body_checks = regexp:/etc/postfix/body_checks
#mime_header_checks = regexp:/etc/postfix/block_attachments
#local_recipient_maps =

# virtual setup
virtual_alias_maps = 	proxy:mysql:/etc/postfix/mysql-virtual_alias_default_maps.cf, 
			proxy:mysql:/etc/postfix/mysql-virtual_alias_maps.cf, 
			regexp:/etc/postfix/virtual_regexp
						
virtual_mailbox_base = /var/vmail

virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains_maps.cf
virtual_mailbox_maps = 	proxy:mysql:/etc/postfix/mysql-virtual_mailbox_maps.cf, 
			proxy:mysql:/etc/postfix/mysql-virtual_alias_pipe_maps.cf

virtual_minimum_uid = 101
#virtual_uid_maps = static:101
#virtual_gid_maps = static:12
#virtual_transport = dovecot

virtual_uid_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_uid_maps.cf
virtual_gid_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailbox_gid_maps.cf

#LMTP For Local Delivery 
virtual_transport = lmtp:unix:private/dovecot-lmtp

dovecot_destination_recipient_limit = 1

# debugging
debug_peer_level = 2
debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
		 xxgdb $daemon_directory/$process_name $process_id & sleep 5

		 
#For Cyrus SASL
#smtpd_sasl_authenticated_header = no
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous

		 
# authentication
smtpd_sasl_local_domain = $myhostname
#smtpd_sasl_local_domain = $myhostname = mx1.rubelhossain.com
broken_sasl_auth_clients = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth

# tls config
smtp_use_tls = yes
smtpd_use_tls = yes
smtp_tls_security_level = may
smtpd_tls_security_level = may
#smtp_tls_note_starttls_offer = yes


# only offer authentication after STARTTLS
#N.B:Disallow plain login( if you use this roundcube will not send mail )
#But outlook , thunderbird can send email
#smtpd_tls_auth_only = yes


# Request client certificate
#smtpd_tls_ask_ccert = yes
smtpd_tls_loglevel = 1
#smtp_tls_loglevel = 1

smtpd_tls_received_header = yes
#smtp_tls_received_header = yes


#smtp_tls_session_cache_timeout = 3600s
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom

smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
#smtpd_tls_session_cache_database = btree:$data_directory/smtpd_tls_session_cache

# Add FQDN/Hostname SSL
smtpd_tls_key_file = /etc/pki/tls/private/hostname.key
smtpd_tls_cert_file = /etc/pki/tls/certs/hostname.bundle

# rules restrictions
smtpd_client_restrictions =
smtpd_helo_restrictions =
smtpd_sender_restrictions =
smtpd_recipient_restrictions = check_policy_service inet:127.0.0.1:10031, 
				permit_sasl_authenticated, 
				permit_mynetworks, 
				check_client_access hash:/etc/postfix/sender_whitelist, 
				check_client_access hash:/etc/postfix/sender_blacklist, 
				reject_unauth_destination, 
				reject_non_fqdn_sender, 
				reject_non_fqdn_recipient, 
				reject_unknown_recipient_domain, 
				reject_rbl_client zen.spamhaus.org, 
				reject_rbl_client b.barracudacentral.org,
				reject_rbl_client bl.spamcop.net 
				
smtpd_helo_required = yes
unknown_local_recipient_reject_code = 550
disable_vrfy_command = yes
smtpd_data_restrictions = reject_unauth_pipelining

# Email Size Limit
# email size limit ~20Meg
message_size_limit = 204800000
mailbox_size_limit = 2048000000

# Limit 500 emails per hour per email address
anvil_rate_time_unit = 3600s
smtpd_client_message_rate_limit = 500 

# Vacation Scripts
vacation_destination_recipient_limit = 1
recipient_bcc_maps = proxy:mysql:/etc/postfix/mysql-virtual_vacation.cf

#In order to integrate OpenDKIM
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
milter_protocol = 2


#Relay
smtp_sasl_security_options = noanonymous
#smtp_sender_dependent_authentication = yes
#sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
header_size_limit = 4096000 

#remove outgoing header
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks

#Bots & Zombies Protection with Postscreen
postscreen_access_list = permit_mynetworks cidr:/etc/postfix/postscreen_access.cidr
postscreen_blacklist_action = drop
#Default = ignore or use # before the line
postscreen_greet_action = drop
#postscreen_greet_action = enforce

compatibility_level = 2
tls_server_sni_maps = hash:/etc/postfix/vmail_ssl.map

#relayhost = [107.152.xxx.204]

N.B: You should check carefully each configuration line and must replace my domain and server FQDN as well as Server IP.
Here I used Postscreen. Postscreen is an additional Anti-Spam strategy at the MTA level. The postscreen daemon provides protection against mail server overload. One postscreen process handles multiple inbound SMTP connections and decides which clients may talk to a Postfix SMTP server process. 

In a typical scenario, good connections, bots and zombies talk with postscreen. Postscreen does basic checks and denies the connection if the message is from a bot or zombie. If the connection is not in the temporary whitelist, postscreen will pass the email to the local anti-SPAM and anti-virus engines, which can accept it or deny it as usual.

Bots and Zombies Protection with Postscreen: Open postfix master file /etc/postfix/master.cf with your favorite editor and comment out line 10 and add those lines 11 to 14
      5 # ***** Unused items removed *****
      6 # ==========================================================================
      7 # service type  private unpriv  chroot  wakeup  maxproc command + args
      8 #               (yes)   (yes)   (yes)   (never) (100)
      9 # ==========================================================================
     10 #smtp      inet  n       -       n       -       -       smtpd
     11 smtp      inet  n       -       y       -       1       postscreen
     12 smtpd     pass  -       -       y       -       -       smtpd
     13 dnsblog   unix  -       -       y       -       0       dnsblog
     14 tlsproxy  unix  -       -       y       -       0       tlsproxy
     15   -o content_filter=smtp-amavis:127.0.0.1:10024
     16   -o receive_override_options=no_address_mappings
 
Now whitelist your server IP and loopback network IP in Postscreen & don't forget to use postmap command 
# vi /etc/postfix/postscreen_access.cidr

#permit my own IP addresses
60.141.190.140/32               permit
60.141.190.142/32               permit
127.0.0.0/8                     permit
127.0.0.1/32                    permit
45.67.229.43/32                 reject
As you can remember I have two IP's, One for shared hosting and another for outgoing email sending. Now I want to fix outgoing IP. Open postfix master file /etc/postfix/master.cf with your favorite editor and add the line  -o smtp_bind_address=60.141.190.142  as below 
     44 smtp      unix  -       -       n       -       -       smtp
     45         -o smtp_bind_address=60.141.190.142
     46 # When relaying mail as backup MX, disable fallback_relay to avoid MX loops
     47 relay     unix  -       -       n       -       -       smtp
     48         -o smtp_bind_address=60.141.190.142
     49         -o fallback_relay=
     50 #       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
     51 showq     unix  n       -       n       -       -       showq
Add Hostname SSL to Dovecot configuration file : vi /etc/dovecot/dovecot.conf 
ssl = yes
ssl_cert = < /etc/pki/tls/certs/hostname.bundle
ssl_key = < /etc/pki/tls/private/hostname.key
ssl_verify_client_cert = no
Also enable dovecot log and Dovecot SNI support to Dovecot configuration file
log_path = /var/log/dovecot.log
info_log_path = /var/log/dovecot-info.log
debug_log_path = /var/log/dovecot-debug.log
mail_debug=no

!include_try /etc/dovecot/sni.conf
Don't forget to add postmaster address in Dovecot configuration file
 protocol lda {
        #mail_plugins = sieve
        mail_plugins = quota sieve
        postmaster_address = postmaster@rubelhossain.com
}
Now restart postfix and dovecot services. Check all incoming & outgoing are properly functioning. If you have any issues , Feel free to share.

Comments