######################################################### # Mail Server for Enterprise Installation v. 1.8 # # Anton Rahmadi, Samarinda, INDONESIA. # # 31 May 2017 # # Previous deployed version: v. 1.7b (12-2014) # # Full manual installation (highly customizable) # # Recommended Operating System: Slackware v. 14.2 # # Main Features: # # - Postfix with TLS, SASL, MySQL # # - Dovecot with imap, imaps, pop3, pop3s # # - Virtualmail (unlimited) with postfixadmin # # - Webmail with RoundCube # # - Use graciously SlackBuild to compile things # # # # Security Features: # # - Blacklist filtering # # - DNS verification and signature: DKIM, SPF # # - Antispam with Spamassassin, Postgrey, Greylist # # - MIME checks # # # # This tutorial license: # # Free for non-commercial and education # # Not free for commercial and publication purpose # # Based on mainly GPL softwares # # Postfix is released under IBM Special License # # All rights reserved # ######################################################### A little note about the guideline and the distro. This is a guideline to install Postfix, Dovecot, MySQL with Virtualmail that can serve thousands of users. In addition to the standard config, SpamAssassin, Postgrey, Greylist, DKIM, and SPF are features added to the server, fighting spams and increasing the credentials. This guideline is already at version 1.8, desgining to work with Slackware as the GNU/Linux distro. There is a reason to use the Slackware: simple, pure, stable and reliable. Easy to troubleshoot (logging is straightforward) and very little downtime are all we need. We have been using this for our mail servers since 2005. This is the one of the longest GNU/Linux servers in service beside the trusty Gentoo. Ever since Slackbuild and Slackpkg are exist, everything becomes easier, at least at the step of compiling and integrating options. **Important Notice to junior Mail Administrator** The mail server requires extra attention since it employs more programs that other servers. You need to understand SSL, TLS, and SASL as ways to secure incoming connection. You need to understand SMTP(S), IMAP(S), POP3(S), and how Postfix and Dovecot handling the queue. Spam fighting ain't easy at all. New things come pretty fast and diverse. We have seen rise, fall, integration, introduction and major revamp of programs in this business. SPF, DK, DKIM, DMARC, DNSSEC, RBLs, and spam rules are evolving. Sometime, a simple minor upgade causes disharmony. Maintaining Mail Server, you are not dealing with machine. No technical language to explain things. Simple human *readable* message, you have to deliver, since you will dealing with lots of customers with diverse knowledge and needs. Last, you need to revisit each setting at least one time within a month to review things. We have warn you and WYATB ! A. Setting up environment for Slackbuild etc 1) Design the partition It is adviseable that we need to have several partitions designed to mount with different permission as a layer of securing our system. Hence, at least we'll have this scheme: /dev/sda1 / ext4 defaults 1 1 /dev/sda3 /tmp ext4 nosuid,nodev,defaults 1 2 /dev/sda5 /var ext4 nosuid,noexec,defaults 1 2 /dev/sda6 /var/vmail ext4 nosuid,noexec,defaults 1 2 /dev/sda7 /home ext4 nosuid,noexec,defaults 1 2 2) Verify partition permission more /etc/fstab result example: /dev/sda1 / ext4 defaults 1 1 /dev/sda3 /tmp ext4 nosuid,nodev,defaults 1 2 /dev/sda6 /var/vmail ext4 nosuid,noexec,defaults 1 2 We have to make sure that /tmp and /usr/local/src are mounted without "noexec" flag. Also, we have to sure that /varmail (or whereever we put the virtualmail folder is) is mounted with "nosuid,noexec" flag. If the condition is unsatisfied, we need to change /etc/fstab and remount the partition nano /etc/fstab mount -o remount /dev/sdaX 2) Set up directories We need to prepare several directories mkdir /usr/local/src mkdir /usr/local/src/slackbuild B. Installing File Libraries 1) Requirements - Open SSL - MySQL/MariaDB We assume that Open SSL and MySQL / MariaDB from Slackware package have been installed 2) Cyrus-SASL Over the time, We preferred Cyrus-SASL over Dovecot-SASL. But, Cyrus-SASL project seems a bit inactive in the past 7 years or so. This is how we set it up (in case you need this) cd /usr/local/src/ mkdir cyrus-sasl cd cyrus-sasl Copy all required files from Slackbuild, located from this link: https://slackbuilds.org/mirror/slackware/slackware64-14.2/source/n/cyrus-sasl/ We need to make the script executable chmod 755 cyrus-sasl.SlackBuild Call the script to compile Cyrus-SASL ./cyrus-sasl.SlackBuild If no error occurred, then we may move the package from /tmp to somewhere else mv /tmp/cyrus-sasl-2.1.26*t?z /usr/local/src/slackbuild/ Installing the package with standard installpkg command installpkg /usr/local/src/slackbuild/cyrus-sasl-2.1.26-x86_64-1.txz 3) Plan and writedown UID dan GID Most problems occurred are as a result of inconsistency in permission, therefore it is important to concept and writedown UID and GID for all programs For Dovecot user: dovecot (UID: 202) group: dovecot (GID: 202) user: dovenull (UID: 248) group: dovenull (GID: 248) For Postfix user: postfix (UID: 200) group: postfix (GID: 200) group: postdrop (GID: 201) Virtual Mail user: vmail (UID: 150) group: mail (GID: 12) Directory Permission: /etc/dovecot: vmail:dovecot /var/vmail: vmail:mail /var/www/htdocs: apache:apache 4) Update file/library indexing To make sure every installation is being populated in the internal system database, we may execute the updatedb command updatedb C. Installing POP & IMAP Server 1) Add user and group for Dovecot To add user and group for Dovecot and Virtualmail, we execute these commands useradd -r -d /var/vmail -s /bin/false -u 150 -g 12 vmail mkdir /var/vmail chmod 770 /var/vmail chown vmail:mail /var/vmail groupadd -g 202 dovecot useradd -d /dev/null -s /bin/false -u 202 -g 202 dovecot groupadd -g 248 dovenull useradd -d /dev/null -s /bin/false -u 248 -g 248 dovenull 2) Install Dovecot The next step is to install Dovecot by employing Slackbuild script cd /usr/local/src/ wget -c https://slackbuilds.org/slackbuilds/14.2/network/dovecot.tar.gz tar -xzvf dovecot.tar.gz cd dovecot chmod 755 dovecot.SlackBuild wget -c https://www.dovecot.org/releases/2.2/dovecot-2.2.29.1.tar.gz Before executing the script, we need to adjust Dovecot version. The latest at the time of this article being written is version 2.2.29.1. nano dovecot.SlackBuild Search for this line and adjust accordingly VERSION=${VERSION:-2.2.29.1} Then we may execute the script to compile the Dovecot ./dovecot.SlackBuild If no error appeared, then we can move the compiled Dovecot from /tmp to somewhere else. mv /tmp/dovecot-2.2.29.1-x86_64-1_SBo.tgz /usr/local/src/slackbuild/ Installing Dovecot is as easy as installing other Slackware package installpkg /usr/local/src/slackbuild/dovecot-2.2.29.1-x86_64-1_SBo.tgz 3) Setup Dovecot Now, it is a time to setup the Dovecot, making it to use database and to listen properly cd /etc/dovecot cp -R /usr/doc/dovecot-2.2.29.1/example-config/* /etc/dovecot chown -R vmail:dovecot /etc/dovecot chmod -R o-rw /etc/dovecot To set up the database connection between Dovecot and MariaDB, edit /etc/dovecot/dovecot-sql.conf.ext and make sure you set the following options: driver = mysql connect = host=/var/run/mysql/mysql.sock dbname=mail user=mail password=password-here default_pass_scheme = SHA512-CRYPT password_query = \ SELECT username as user, password, '/var/vmail/%d/%n' as \ userdb_home, 'maildir:/var/vmail/%d/%n' as userdb_mail, \ 150 as userdb_uid, 12 as userdb_gid \ FROM mailbox WHERE username = '%u' AND active = '1' user_query = \ SELECT '/var/vmail/%d/%n' as home, 'maildir:/var/vmail/%d/%n' \ as mail, 150 AS uid, 12 AS gid, \ concat('dirsize:storage=', quota) AS quota \ FROM mailbox WHERE username = '%u' AND active = '1' The next is to edit /etc/dovecot/conf.d/10-auth.conf disable_plaintext_auth = yes auth_mechanisms = plain login #!include auth-system.conf.ext !include auth-sql.conf.ext To tell Dovecot where the email is stored in the filesystem, change the UID in these lines in /etc/dovecot/conf.d/10-mail.conf mail_location = maildir:/var/vmail/%d/%n mail_uid = vmail mail_gid = mail first_valid_uid = 150 last_valid_uid = 150 Edit /etc/dovecot/conf.d/10-master.conf to set up user, group, and mode in the unix_listener auth-userdb section of the service auth. Also We need to set up unix listener in that configuration file. service auth { unix_listener auth-userdb { mode = 0666 user = vmail group = mail } } unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix } To enable SSL, you may use Gerardo's instruction located in the reference section of this tutotial. 4) Start the Dovecot Now, we may start the dovecot chmod 755 /etc/rc.d/rc.dovecot /etc/rc.d/rc.dovecot start 5) Look for error(s) Pay attenttion to any error produced by dovecot tail -f /var/log/maillog D. Installing Mail Server 1) Add user and group for Postfix Postfix requires a user and two groups to run properly groupadd -g 200 postfix useradd -u 200 -d /dev/null -s /bin/false -g postfix postfix groupadd -g 201 postdrop 2) Install Postfix We may use SlackBuild to compile the Postfix with Dovecot and MySQL enabled cd /usr/local/src wget -c https://slackbuilds.org/slackbuilds/14.2/network/postfix.tar.gz tar -xzvf postfix.tar.gz cd postfix chmod 755 postfix.SlackBuild wget -c http://cdn.postfix.johnriley.me/mirrors/postfix-release/official/postfix-3.2.0.tar.gz nano postfix.SlackBuild To adjust version, SASL, and database, we may edit these lines VERSION=${VERSION:-3.2.0} SASL=${SASL:-dovecot} DATABASE=${DATABASE:-mysql} Then, we may proceed with compilation ./postfix.SlackBuild We move the package to somewhere else mv /tmp/postfix-3.2.0-x86_64-1_SBo.tgz /usr/local/src/slackbuild/ The we can install the package installpkg /usr/local/src/slackbuild/postfix-3.2.0-x86_64-1_SBo.tgz 3) Setup Postfix Admin Several files need to be configured to enable virtual mail function a) /etc/postfix/mysql_virtual_alias_domainaliases_maps.cf user = mail password = mailpassword hosts = localhost dbname = mail query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' AND alias.address=concat('%u', '@', alias_domain.target_domain) AND alias.active = 1 b) /etc/postfix/mysql_virtual_alias_maps.cf user = mail password = mailpassword hosts = localhost dbname = mail table = alias select_field = goto where_field = address additional_conditions = and active = '1' c) /etc/postfix/mysql_virtual_domains_maps.cf user = mail password = mailpassword hosts = localhost dbname = mail table = domain select_field = domain where_field = domain additional_conditions = and backupmx = '0' and active = '1' d) /etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf user = mail password = mailpassword hosts = localhost dbname = mail query = SELECT maildir FROM mailbox, alias_domain WHERE alias_domain.alias_domain = '%d' AND mailbox.username=concat('%u', '@', alias_domain.target_domain ) AND mailbox.active = 1 e) /etc/postfix/mysql_virtual_mailbox_maps.cf user = mail password = mailpassword hosts = localhost dbname = mail table = mailbox select_field = CONCAT(domain, '/', local_part) where_field = username additional_conditions = and active = '1' f) /etc/postfix/main.cf #Host Configuration myhostname = mail.example.org myorigin = /etc/hostname inet_interfaces = all mynetworks = 127.0.0.0/24 [::ffff:127.0.0.0]/104 [::1]/128 alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases smtpd_banner = $myhostname ESMTP $mail_name biff = no append_dot_mydomain = no #SASL Configuration smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes broken_sasl_auth_clients = no smtpd_sasl_security_options = noanonymous smtpd_sasl_local_domain = smtpd_sasl_authenticated_header = yes #Delay and Error delay_warning_time = 4h maximal_queue_lifetime = 4d minimal_backoff_time = 1000s maximal_backoff_time = 8000s smtp_helo_timeout = 60s smtpd_recipient_limit = 16 smtpd_soft_error_limit = 3 smtpd_hard_error_limit = 12 #UCE Restriction smtpd_helo_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, #enable this line once we have Postgrey installed in the system #check_policy_service unix:/var/run/postgrey/postgrey.sock, permit smtpd_data_restrictions = reject_unauth_pipelining smtpd_relay_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, #enable this line once we have Postgrey installed in the system #check_policy_service unix:/var/run/postgrey/postgrey.sock, permit smtpd_helo_required = yes smtpd_delay_reject = yes disable_vrfy_command = yes mailbox_size_limit = 0 recipient_delimiter = + #Virtualmail configuration #pay attention to permission in these lines! virtual_mailbox_base = /var/vmail virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf, mysql:/etc/postfix/mysql_virtual_mailbox_domainaliases_maps.cf virtual_uid_maps = static:150 virtual_gid_maps = static:12 virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/mysql_virtual_alias_domainaliases_maps.cf virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf #Transport virtual_transport = dovecot[server] dovecot_destination_recipient_limit = 1 #Server Signature #enable these two lines, once we set up DKIM signing #non_smtpd_milters=unix:/var/run/opendkim/opendkim.sock #smtpd_milters=unix:/var/run/opendkim/opendkim.sock #Antivirus #enable this line, once we set up Amavis antivirus #content_filter = amavis-forward:unix:amavis/amavisd.sock g) /etc/postfix/master.cf #Submission port (587) submission inet n - - - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_enforce_tls=may -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject -o smtpd_sasl_tls_security_options=noanonymous #SMTP Secure smtps inet n - - - - smtpd -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_tls_auth_only=may -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject -o smtpd_sasl_security_options=noanonymous,noplaintext -o smtpd_sasl_tls_security_options=noanonymous #Dovecot Local Delivery dovecot unix - n n - - pipe flags=DRhu user=vmail:mail argv=/usr/libexec/dovecot/dovecot-lda -d $(recipient) To use TLS and SSL, please refer to Gerardo's instruction, located in the reference section. 4) Set up database Log in as root to mysql and create the database, mysql -u root -p Then execute command to create database while in mysql console, you may change the password CREATE DATABASE mail; GRANT ALL PRIVILEGES ON mail.* TO "mail"@"localhost" \ IDENTIFIED BY "password-here*"; FLUSH PRIVILEGES 5) Set up Postfix Admin To enable each user to manage their email preference, we need to install Postfix Admin. The current version is 3.0.2. cd /var/www/htdocs/ wget -c http://softlayer-dal.dl.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-3.0.2/postfixadmin-3.0.2.tar.gz tar -xzf postfixadmin-3.0.2.tar.gz mv postfixadmin-3.0.2 postfixadmin chown -R apache:apache postfixadmin cd postfixadmin Edit the config.local.php, you may change the password as well $CONF['configured'] = true; $CONF['database_type'] = 'mysql'; $CONF['database_host'] = 'localhost:/var/run/mysql/mysql.sock'; $CONF['database_user'] = 'mail'; $CONF['database_password'] = 'password-here*'; $CONF['database_name'] = 'mail'; $CONF['domain_path'] = 'NO'; $CONF['domain_in_mailbox'] = 'YES'; $CONF['encrypt'] = 'dovecot:SHA512-CRYPT'; $CONF['dovecotpw'] = "/usr/bin/doveadm pw"; Then, to complete the setup, visit http://localhost/postfixadmin/setup.php to generate a setup password to use in config.local.php 6) Fix the permission It is required to recheck permission in the setting. Errors are normaly produced due to invalid credential being used to access any configuration files or directory cp /etc/dovecot/dovecot.conf{,.bk} doveconf -n > /etc/dovecot/dovecot.conf chmod 644 /etc/dovecot/dovecot.conf usermod -G dovecot -a apache 7) Start the Postfix After installation, we may start the Postfix chmod 755 /etc/rc.d/rc.postfix /etc/rc.d/rc.postfix start 8) Look for error(s) Any error produced will appear in the log file tail -f /var/log/maillog 9) Test the mail We may test wether port SMTP, SMTPS, and Submission are ready to accept connection. This is an example telnet localhost 25 You may use Internet resources to do manual emailing with telnet E. Setting-Up Some Hurdles 1) Tune Up Postfix UCE Based on our test from diverse users, we tune up the Postfix UCE rules in /etc/postfix/main.cf smtpd_helo_restrictions = permit_sasl_authenticated, permit_mynetworks, #Exception added to allow blacklisting and whitelisting #based on URL/email check_helo_access hash:/etc/postfix/helo_access, #based on IP check_client_access cidr:/etc/postfix/client_access, #Disallow open relay reject_unauth_pipelining, #Disabled due to Outlook client compatibility #reject_invalid_hostname, #reject_non_fqdn_hostname, reject_unauth_destination, permit smtpd_client_restrictions = permit_mynetworks, #Selectively block suspected leaked user password from client (not webmail) #check_sender_access hash:/etc/postfix/temp_banned_login, permit_sasl_authenticated, #Exception added to allow blacklisting and whitelisting check_sender_access hash:/etc/postfix/sender_access, check_client_access cidr:/etc/postfix/client_access, #Disallowed due to Outlook compatibility #reject_invalid_hostname, #reject_unknown_client, #Internet is not a sane place, we need some compromise with others #reject_rbl_client xyuhnncdbtth.50.207.31.103.dnsbl.httpbl.org, #reject_rbl_client dnsbl-2.uceprotect.net, #reject_rbl_client dnsbl-3.uceprotect.net, #reject_rbl_client ips.backscatterer.org, #reject_rbl_client cbl.abuseat.org, reject_rbl_client dnsbl.sorbs.net, reject_rbl_client bl.spamcop.net, reject_rbl_client xbl.spamhaus.org, reject_rbl_client sbl.spamhaus.org, permit smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, #Use this line if sender_access is enabled check_sender_access hash:/etc/postfix/sender_access, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain, reject_unauth_destination, #Disabled due to Outlook compatibility #reject_invalid_hostname, reject_unauth_pipelining, reject_multi_recipient_bounce, #Reject from myself reject_authenticated_sender_login_mismatch, reject_unauthenticated_sender_login_mismatch, #Spammers' IP #need some tune up, world is not habitated by sane people only #Some are overly sane too, then we need to compromise #reject_rbl_client xyuhnncdbtth.50.207.31.103.dnsbl.httpbl.org, reject_rbl_client dnsbl-3.uceprotect.net, #reject_rbl_client ips.backscatterer.org, reject_rbl_client dnsbl.sorbs.net, reject_rbl_client cbl.abuseat.org, reject_rbl_client xbl.spamhaus.org, reject_rbl_client bl.spamcop.net, reject_unverified_sender, #Enable Policyd check_policy_service inet:127.0.0.1:10023, permit 2) Setup Postfix Reject Block List Edit the /etc/postfix/main.cf to add RBL servers. We need to put these lines before permit in smtpd_client_restrictions and smtpd_recipient_restrictions directives. #Spammers' IP #need some tune up, world is not habitated by sane people only #Some are overly sane too, then we need to compromise #reject_rbl_client xyuhnncdbtth.50.207.31.103.dnsbl.httpbl.org, reject_rbl_client dnsbl-3.uceprotect.net, #reject_rbl_client ips.backscatterer.org, reject_rbl_client dnsbl.sorbs.net, reject_rbl_client cbl.abuseat.org, reject_rbl_client xbl.spamhaus.org, reject_rbl_client bl.spamcop.net, reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl, reject_rbl_client b.barracudacentral.org 3) Setup whitelist and blacklist Firstly, we need to create sender_access cd /etc/postfix nano sender_access Mileage will vary to put any white/black list server here Allowing groups, since yahoogroups sending with one time use email address yahoogroups.com OK groups.yahoo.com OK returns.groups.yahoo.com OK listserv.ait.ac.th OK mailinglist battlestar.sorbs.net OK mail.lkpp.go.id OK hanmail.net REJECT spam! sbmptn.or.id OK no-hostname bappenas.go.id OK no-hostname Then, we need to make this into a hashed data postmap sender_access Reload the Postfix, once this configuration is changed postfix reload The same configuration may be added for recipient_access, envelope_access, client_access 4) Setup header and MIME Content Check #mime_checks mime_header_checks = regexp:/etc/postfix/mime_checks #header_checks header_checks = regexp:/etc/postfix/header_checks 5) Setup mime check files First, mime_checks file should be created cd /etc/postfix nano mime_checks The content may be different from server to server /^\s*Content-(Disposition|Type).*name\s*=\s*"?(.+\.(ad[ep]|asd|ba[st]|bhx|b64|c[ho]m|cmd|cpl|crt|dbx|dll|exe|hlp|hqx|hta|in[fs]|isp|js|jse|lnk|md[etw]|mim|ms[cipt]|nws|ocx|ops|pcd|pi|pif|prf|reg|scf|scr|sct|sh[bms]|swf|uu|uue|vb|vb[esx]|vxd|wab|ws[cfh]))"?\s*$/ REJECT *** FOR SECURITY REASONS, ".$3" FILETYPES ARE AUTOMATICALLY REJECTED BY THIS SERVER, "$2" WAS REJECTED AS IT MAY CONTAIN VIRUSES *** Then, we need to hash the file postmap mime_checks Reload the postfix 6) Setup header check files Again, the experience may be different from server to server. Here, we create header_checks cd /etc/postfix nano header_checks The content from one of our servers #### Header checks file #### header_checks = regexp:/etc/postfix/header_checks #### Checks are done in order, top to bottom. #### Null Senders #the first line will generate warning -- IGNORE it /^Return-Path: <>/ REJECT no third-party DSNs /^From:.*MAILER-DAEMON/ REJECT no third-party DSNs #### Remove the following from the header to protect internal lans #/^Received:.*.internal.lan/ IGNORE #### non-RFC Compliance headers /[^[:print:]]{7}/ REJECT 2047rfc /^.*=20[a-z]*=20[a-z]*=20[a-z]*=20[a-z]*/ REJECT 822rfc1 /(.*)?\{6,\}/ REJECT 822rfc2 /(.*)[X|x]\{3,\}/ REJECT 822rfc3 #### Unreadable Language Types? -- NON-acsii un-printable /^Subject:.*=\?(GB2312|big5|euc-kr|ks_c_5601-1987|koi8)\?/ REJECT NotReadable1 /^Content-Type:.*charset="?(GB2312|big5|euc-kr|ks_c_5601-1987|koi8)/ REJECT NotReadable2 #### Hidden Word Subject checks /^Subject:.* / REJECT TooManySpaces /^Subject:.*r[ _\.\*\-]+o[ _\.\*\-]+l[ _\.\*\-]+e[ _\.\*\-]+x/ REJECT NoHiddenWords1 /^Subject:.*p[ _\.\*\-]+o[ _\.\*\-]+r[ _\.\*\-]+n/ REJECT NoHiddenWords2 #### Do not accept these types of attachments /^Content-(Type|Disposition):.*(file)?name=.*\.(bat|com|exe)/ REJECT Bad Attachment .${3} /^Received:/ IGNORE /^User-Agent:/ IGNORE /^X-Mailer:/ IGNORE /^X-Originating-IP:/ IGNORE /^x-cr-[a-z]*:/ IGNORE /^Thread-Index:/ IGNORE Then, we need to hash the file postmap header_checks Reload the postfix F. Installing Signatures A mail server should at least have one or other way of DNS signatures to verify that it is a qualified one to send mail. This verification can be in the form of PTR, SPF, DK, DKIM, and/or DNSSEC. Without any of these, any spam fighting engine may mark the server as a bogus mail server or spammer. 1) Setup PTR The difficulty of setting up PTR is, unless you have a DNS server or ISP that let you do it yourself, you need to contact you ISP to set it up for you. This is not a possible solution for shared host, dynamic IP, or small company that is not renting a block of IPs. 2) Setup SPF The second available solution is to have a SPF record. Microsoft Exchange, in particular, support SPF verification. We need to setup SPF record in our domain record to let others know that an IP is specified for mailserver, while other IPs are not. This section should be inserted into TXT record of an IP. "v=spf1 a:your.domain.name +mx ip4:[my_ip_address]/32 -all" To check whether a designated IP is qualified for a mail server, we can utilize dig, i.e. dig @dns0.zoneedit.com email.unmul.ac.id txt The specified domain.name.server will then return TXT record, i.e. ... ;; QUESTION SECTION: ;email.unmul.ac.id. IN TXT ;; ANSWER SECTION: email.unmul.ac.id. 7200 IN TXT "v=spf1 a mx -all" ... A lengthy explanation about this can be found in http://openspf.org 3) Install DKIM DKIM is a solution offered by community via OpenDKIM.org. Normally Google recognizes it, while DK is recognized by Yahoo. Firstly, we need to setup user and group groupadd -g 305 opendkim useradd -r -u 305 -g opendkim -d /var/run/opendkim/ -s /sbin/nologin \ -c "OpenDKIM Milter" opendkim We need to satisfy the library required for OpenDKIM cd /usr/local/src wget -c https://slackbuilds.org/slackbuilds/14.1/libraries/libbsd.tar.gz tar -xzvf libbsd.tar.gz cd libbsd chmod 755 libbsd.SlackBuild wget -c http://libbsd.freedesktop.org/releases/libbsd-0.7.0.tar.xz Install the libbsd ./libbsd.SlackBuild Once everything is compiled, we can move the package to somewhere else mv /tmp/libbsd-0.7.0-x86_64-1_SBo.tgz /usr/local/src/slackbuild Then we can execute the installpkg installpkg /usr/local/src/slackbuild/libbsd-0.7.0-x86_64-1_SBo.tgz Now, we need to download Slackbuild script for OpenDKIM cd /usr/local/src wget -c https://slackbuilds.org/slackbuilds/14.1/network/OpenDKIM.tar.gz tar -xzvf OpenDKIM.tar.gz cd opendkim chmod 755 opendkim.SlackBuild wget -c http://downloads.sourceforge.net/opendkim/opendkim-2.10.3.tar.gz We need to see the script to adjust the info ./opendkim.SlackBuild Install the libbsd ./opendkim.SlackBuild Once everything is compiled, we can move the package to somewhere else mv /tmp/opendkim-2.10.3-x86_64-1_SBo.tgz /usr/local/src/slackbuild Then we can execute the installpkg installpkg /usr/local/src/slackbuild/opendkim-2.10.3-x86_64_1_SBo.tgz To set up DKIM, we can edit /etc/opendkim.conf nano /etc/opendkim.conf Change the ownership of the config folder chown opendkim:opendkim /etc/opendkim Then we can start the daemon chmod /etc/rc.d/rc.dkim /etc/rc.d/rc.dkim start Upon the first start, the rc.dkim will create automatic key and stored it in /etc/opendkim/keys file. We may copy the key and put it in our TXT section of our DNS record. more /etc/opendkim/keys We need to create a Socket to DKIM sign of any outgoing mail, the first step is to create a spool directory for opendkim mkdir /var/spool/postfix/opendkim chown opendkim:postfix /var/spool/postfix/opendkim Then, we change the config at /etc/opendkim.conf, enabling opendkim to work on a socket. We unmark this line in that file. SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock" The last step is to edit /etc/postfix/main.cf nano /etc/postfix/main.cf Adding these line will force Postfix to DKIM sign any email prior to sending it to the Internet #Milter configuration milter_protocol = 6 smtpd_milters = local:/opendkim/opendkim.sock non_smtpd_milters = local:/opendkim/opendkim.sock Sample of TXT query from dig ;; QUESTION SECTION: ;email.unmul.ac.id. IN TXT ;; ANSWER SECTION: email.unmul.ac.id. 7200 IN TXT "google-site-verification=RbBKGHEntw7ZZ_aqo0kLDiCrDbdiRv6alIF7yI2irT8" More info can be obtained from http://opendkim.org G. Installing Postgrey and Greylist 1) Install Postgrey First, we need to satisfy Perl modules cpan -i Net::Server IO::Multiplex BerkeleyDB Berkeley_DB We can utilize a SlackBuild from this link as a basis of installing Postgrey https://slackbuilds.org/repository/14.1/network/postgrey/ Then we can download the latest source of Postgrey wget -c http://postgrey.schweikert.ch/pub/postgrey-1.37.tar.gz The installation procedure is relatively easy. After installation, we can enable Postgrey: chmod 755 /etc/rc.d/rc.postgrey /etc/rc.d/rc.postgrey start To integrate Postgrey into Postfix, we need to add this line into /etc/postfix/main.cf before permit at smtpd_recipient_restrictions #enable this line once we have Postgrey installed in the system #check_policy_service unix:/var/run/postgrey/postgrey.sock, 2) Install Greylist We can utilize a Slackbuild from this link as a basis of installing greylist https://slackbuilds.org/repository/14.2/network/milter-greylist/ Then, we can download the latest source of greylist https://ftp.espci.fr/pub/milter-greylist/milter-greylist-4.6.2.tgz To integrate greylist into Postfix, we can add this line into /etc/postfix/main.cf before permit at smptd_recipient_restrictions #Enable Policyd check_policy_service inet:127.0.0.1:10023, H. Installing Anti-Spam 1) Set automatic installation for Perl modules prerequisite: cpan o conf prerequisites_policy follow o conf commit quit 2) Install required Perl modules for SpamAssassin: cpan -i Archive::Tar Digest::SHA Net::DNS Net::DNS::Resolver::Programmable \ Mail::SPF Geo::IP Net::CIDR::Lite IO::Socket::IP IP::Country Net::Ident \ Net::Patricia IO::Socket::INET6 Compress::Zlib Mail::DKIM LWP::UserAgent \ HTTP::Date Encode::Detect ExtUtils::MakeMaker NetAddr::IP \ Mail::SpamAssassin::Plugin::Razor2 Razor2::Client::Agent IO::Socket::SSL \ DBI Sys::Syslog DBD::File 3) Use the Slackbuild for SpamAssassin cd /usr/local/src wget -c https://slackbuilds.org/slackbuilds/14.2/network/spamassassin.tar.gz tar -xzvf spamassassin.tar.gz cd spamassassin wget -c http://www.eu.apache.org/dist/spamassassin/source/Mail-SpamAssassin-3.4.1.tar.bz2 chmod 755 spamassassin.SlackBuild Before executing SlackBuild script, we may adjust the VERSION line accordingly ./spamassassin.SlackBuild If everything satisfied (normally, any error produce as a result of incomplete Perl modules or dependence), then we may proceed to install the package mv /tmp/spamassassin-*.t?z /usr/local/src/slackbuild/. pkgtool install /usr/local/src/slackbuild/spamassassin-*.t?z 4) Download SpamAssassin rules To update the spamassassin rules, we may execute sa-update sa-update & 5) Activate SpamAssassin now and when the server starts Activation of rc.spamd is easy chmod 755 /etc/rc.d/rc.spamd /etc/rc.d/rc.spamd start It is required to look for any error message produced before we proceed to next installation 6) Look for spawned service We may check wheter spamd is spawned successfuly ps auwx | grep spamd We may get these lines in return root 27137 2.4 2.0 184208 81864 ? Ss 06:13 0:01 /usr/bin/spamd -d --pidfile=/var/run/spamd.pid root 27139 0.0 1.8 184208 76272 ? S 06:13 0:00 spamd child root 27140 0.0 1.8 184208 76332 ? S 06:13 0:00 spamd child root 27143 0.0 0.0 11672 2164 pts/1 S+ 06:14 0:00 grep spamd When we see this, then everything is (hopefully) fine! Also, check for any error message tail -f /var/log/messages 7) Set autoupdate for rules Spam world is messy, therefore leave it to those who are expert. We need to update SpamAssassin rules regularly, then, we modify cron crontab -e To update the rule every month at 00.00 AM, we need to add this line (use "i" to insert) : 0 0 0 * * sa-update & Escape and Shift-ZZ to save and close. J. Setting up webmail application TBA K. Hardening the server 1) Update and Upgrade Package Find closest mirrors in our location, and uncoment that in the /etc/slackpkg/mirror nano /etc/slackpkg/mirrors Our server uses ones that are located in Indonesia # INDONESIA (ID) http://kambing.ui.ac.id/slackware/slackware64-14.2/ http://repo.ukdw.ac.id/slackware/slackware64-14.2/ Blacklist any SlackBuild (SBo) packages, as we need to maintain them independently nano /etc/slackpkg/blacklist Add these following lines to leave custom packages untouched [0-9]+_SBo [0-9]+[0-9]+alien [0-9]+compat32 Then, we can command the server to automatically update and upgrade things slackpkg update slackpkg upgrade-all Keep any existing configuration, so that we can review the new config brought by the upgraded packages later. 2) Setup Firewall For Email server purpose, it is straightforward configuration. We need only to allow several ports: TCP 80, 443 for webmail and website TCP 25, 110, 143, 465, 587, 995 for email server TCP 22 for SSH TCP and UDP 53 for DNS These lines are generated via iptables-save *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] :LOGME - [0:0] :TRUSTED - [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 995 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 465 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 587 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 143 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT -A INPUT -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 110 -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m state --state NEW -j TRUSTED -A OUTPUT -p icmp -m state --state INVALID -j DROP -A LOGME -p icmp -m limit --limit 1/min -j LOG --log-prefix "firewall: " --log-level 5 -A LOGME -p tcp -m limit --limit 1/min -j LOG --log-prefix "firewall: " --log-level 5 -A LOGME -p udp -m limit --limit 1/min -j LOG --log-prefix "firewall: " --log-level 5 -A TRUSTED -d [my_ip]/32 -p icmp -m icmp --icmp-type 8 -m limit --limit 2/sec --limit-burst 10 -j ACCEPT -A TRUSTED -j LOGME -A TRUSTED -d [my_ip]/32 -p icmp -m icmp --icmp-type 8 -j ACCEPT -A TRUSTED -p icmp -j DROP -A TRUSTED -j REJECT --reject-with icmp-port-unreachable COMMIT We save this in a file, say, in /etc/saved_iptable.rules, then may restore this rule periodically with cron 0 * * * * iptables-restore < /etc/saved_iptable.rules & 3) Hardening SSHD To avoid SSH bruteforce attack, we may add these lines in /etc/ssh/sshd_config # Authentication: PermitRootLogin no MaxAuthTries 6 MaxSessions 10 Then restart the SSH server /etc/rc.d/rc.sshd restart 4) Install Fail2ban TBA References: a) https://gerardozamudio.mx/2015/04/25/slackware-mail-server-with-mysql-postfix-and-dovecot/ or b) https://www.digitalocean.com/community/tutorials/how-to-configure-a-mail-server-using-postfix-dovecot-mysql-and$ c) https://help.directadmin.com/item.php?id=36 d) https://help.ubuntu.com/community/IptablesHowTo e) https://www.linode.com/docs/email/postfix/configure-spf-and-dkim-in-postfix-on-debian-8