ASCII Smiley Face Daniel Dickinson Mini Headshot
The C Shore

Yet Another Backup MX HOWTO

Version 0.9.3

Note

This is currently in ‘recipe’ format and doesn’t explain why or go into depth. Future plan for this doc is to be more detailed in those areas.

What you get

  • Backup MX
    • SMTP for incoming mail with queuing and forwarding to primary MX when it is available.
  • Security

    • STARTTLS SSL when possible.
    • Only relay mail who destination is the Primary MX.
    • Avoid being a backscatter source
      • NB: Assumes your primary MX accepts all mail for the domains it services (i.e. no bounces after queueing)
    • RBL antispam measures
    • Incoming DKIM, DMARC, and SPF (check if others’ mail is spoofed)
    • Outgoing DKIM, DMARC, and SPF (reducing opportunities for others to spoof us, if other servers check for these).
    • Use Let’s Encrypt HTTPS certificates from web server
  • Admin

    • Some attack reduction and blocking
    • Some stats

Not in this document

Future work

  • DNSSEC in order to enable DANE

Out of Scope (i.e. Lots of Other Documentation Sources for These)

  • Initial host/instance setup
  • General admin utilities and convenience setup

Prerequisites

  • An internet accessible host with static IP (and no history of abuse)
    • NB This is a pretty much a hard requirement for a backup mx because we want to be sure to receive all mail that the primary would receive.
  • DNS Service (such as dyn.com, self-hosted, etc)
  • For this HOWTO: CentOS 7, 2 GiB RAM, 10 GiB HD (e.g. virtual HD)
  • Repos
    • Defaults + EPEL (to install epel do yum install epel-release)
  • Let’s Encrypt certificate and renewal mechanism (e.g. such as described in Yet Another Web Server HOWTO).

Packages

The following packages need to be installed for this setup (e.g. yum install package1 package2 ...)

Admin Tools

  • policycoreutils
  • policycoreutils-python

Mail Server

  • postfix

Antispam and Antispoofing

  • opendkim
  • opendmarc

Virus Detection / Filtering

  • clamav
  • clamav-scanner
  • clamav-scanner-systemd
  • clamav-milter
  • clamav-update

Stats

  • awstats

Attack Detection / Blocking

  • fail2ban
  • fail2ban-firewalld
  • fail2ban-server

First Steps

  1. Configure networking,admin users etc for your host/instance
  2. (Optional) Install your preferred admin/monitoring utilities etc.
  3. Install “Admin Tools” listed above
  4. Add ‘EPEL’ repository listed above

Mail Server Configuration

Prerequisites: Let’s Encrypt certificate for mail2.example.com

SMTP (Inbound/Outbound)

  1. Install main “Mail Server” packages above
  2. Edit /etc/postfix/main.cf

    1. Set myhostname to your host’s hostname (e.g. myhostname = mail2.example.com)
    2. Set myorigin to $mydomain
    3. Set mydestination to localhost.$mydomain, localhost.localdomain, localhost
    4. Use unknown_local_recipient_reject_code = 550
    5. Set mynetworks_style to host
    6. Set ‘relay_domains’ to ‘‘ (e.g. relay_domains = example.com www.example.com)
    7. Set relayhost = [<primary_mx>] (e.g. relayhost = [mail.example.com]).
    8. Set relay_recipient_maps =
    9. Set

      smtpd_relay_restrictions =
          reject_invalid_hostname,
          reject_unknown_recipient_domain,
          permit_mynetworks,
          reject_unauth_destination
      
      smtpd_recipient_restrictions =
          reject_invalid_hostname,
          reject_unverified_recipient,
          permit_mynetworks,
          reject_rbl_client zen.spamhaus.org,
          permit
      
      smtpd_data_restrictions = reject_unauth_pipelining
      
    10. Comment out home_mailbox

    11. Comment out mail_spool_directory

    12. Comment out mailbox_command

    13. Comment out smtpd_banner

    14. Set

        smtpd_tls_cert_file = /etc/letsenrypt/live/mail2.example.com/fullchain.pem
        smtpd_tls_key_file = /etc/letsencrypt/live/mail2.example.com/privkey.pem
        smtpd_tls_security_level = may
        smtp_tls_cert_file = /etc/letsenrypt/live/mail2.example.com/fullchain.pem
        smtp_tls_key_file = /etc/letsencrypt/live/mail2.example.com/privkey.pem
        smtp_tls_security_level = may
        smtpd_tls_auth_only = yes
      

DNS Setup

  • For IPv4 make sure you have DNS A records for you mail host e.g. mail2.example.com points to 3.48.28.88 (note this should not be a CNAME for the configuration in this HOWTO).
  • Also make sure reverse DNS entries are present: This is usually a service provided by your hosting provider (since they own the IP block and you can’t setup IP -> Name records without them) or ISP (if hosting on static IPs on an ISP that allows mail hosting on your own hardware).
  • Likewise for DNS for ipv6 if you support it (AAAA records in that case).
  • Assuming you already have an MX record for your primary MX, with priority < 20, create an an second DNS MX type entry for your domain (e.g. example.com) with contents 20 mail2.example.com.. If you have any addiitnal backup MXes, repeat, replacing the 20 with larger numbers (e.g. 30, 40, …). The number represents the priority for remote mail hosts sending mail to your domain, with lower numbers being higher priority (earlier in the ordering of hosts).
  • The details depend on the DNS provider or server you are using.

Virus Detection / Filtering

NB: To avoid becoming a backscatter source it is important that your Backup MX does not accept mail your Primary MX does not. That means using the Antivirus/Antispam measures as in your primary MX, for the same users.

SELinux Tweaks

  1. Create a file clamavmilter.te (e.g. in /root) as below

     module clamavmilter 1.0;
    
     require {
         type antivirus_t;
         type milter_port_t;
         class tcp_socket { name_bind };
     }
    
     #============= antivirus_t ==============
     allow antivirus_t milter_port_t:tcp_socket name_bind; 
    
    1. Execute checkmodule -M -m clamavmilter.te -o clamavmilter.mod
    2. Perform semodule_package -o clamavmilter.pp -m clamavmilter.mod
    3. Run semodule -i clamavmilter.pp

Antivirus Mail Filter (Milter)

  1. Install “Virus Detection / Filtering” packages from the list earlier in this document.
  2. Edit /etc/clamd.d/scan.conf with the following (in addition to defaults)
    1. Comment out Example
    2. LogFacility LOG_MAIL
    3. LocalSocket /var/run/clamd.scan/clamd.sock
    4. LocalSocketGroup virusgroup
    5. LocalSocketMode 660
    6. FixStateSocket yes
    7. ExitOnOOM yes
  3. And setsebool -P antivirus_use_jit on
  4. Execute systemctl enable clamd@scan && systemctl restart clamd@scan
  5. Edit /etc/mail/clamav-milter.conf with the following (in addition to defaults)
    1. Comment out Example
    2. MilterSocket inet:8894@localhost
    3. ClamdSocket unix:/var/run/clamd.scan/clamd.sock
    4. OnInfected Reject
    5. AddHeader Add
    6. LogFacility LOG_MAIL
    7. LogInfected Basic
    8. SupportMultipleRecipients yes
  6. Run semanage port --add -t milter_port_t -p tcp 8894
  7. Perform systemctl enable clamav-milter && systemctl restart clamav-milter
  8. To /etc/postfix/main.cf add

       smtpd_milters = inet:localhost:8894
       milter_default_action = tempfail
    
  9. Do postfix reload

Antispam / Antispoofing

  1. Install “Antispam / Antispoofing” packages from list earlier in this document.
  2. Edit /etc/opendkim.conf such that the following are set (in addition to defaults):
    1. ReportAddress "Example.com Postmaster" <postmaster@example.com>
    2. QueryCache yes
  3. Perform systemctl enable opendkim && systemctl start opendkim
  4. Add the following script as /etc/cron.daily/opendmarc_public_suffix_list and make it executable.

        #!/bin/sh
    
        /usr/bin/wget -q -N -P /etc/opendmarc https://publicsuffix.org/list/effective_tld_names.dat
        /bin/chown opendmarc:opendmarc /etc/opendmarc/effective_tld_names.dat
    
    1. Edit /etc/opendmarc.conf such that the following are set (in addition to defaults):
      1. AuthservID HOSTNAME
      2. Autorestart true
      3. AutorestartRate 3/1m
      4. PublicSuffixList /etc/opendmarc/effective_tld_names.dat
      5. SyslogFacility mail
    2. Run systemctl enable opendmarc && systemctl start opendmarc
    3. To /etc/postfix/main.cf add (assuming also doing antivirus above)

      smtpd_milters = inet:localhost:8894 inet:localhost:8891 inet:localhost:8893
      non_smtpd_milters = inet:localhost:8891 inet:localhost:8893
      milter_default_action = tempfail
      
    4. Do postfix reload

Firewall: Allow SMTP

  1. Execute the following:

      firewall-cmd --permanent --add-service smtp
      firewall-cmd --complete-reload
    

Stats Configuration

Prerequisites: AWStats non-CGI setup such as the one described in Yet Another Web Server HOWTO

AWStats Configuration

  1. In /etc/awstats

    1. For mail server (SMTP) log stats

      1. cp awstats.localhost.localdomain.conf awstats.mail2.conf
      2. Set LogFile="/usr/share/awstats/tools/maillogconvert.pl standard < /var/log/maillog |
      3. Set LogType=M
      4. Set the following:

        LogFormat="%time2 $email %email_r %host %host_r %method %url %code %bytesd"
        LevelForBrowsersDetection=0
        LevelForOSDetection=0
        LevelForRefererAnalyze=0
        LevelForRobotsDetection=0
        LevelForWormsDetection=0
        LevelForSearchEnginesDetection=0
        LevelForFileTypesDetection=0
        ShowMenu=1
        ShowSummary=HB
        ShowMonthStats=HB
        ShowDaysOfMonthStats=HB
        ShowDaysOfWeekStats=HB
        ShowHoursStats=HB
        ShowDomainsStats=0
        ShowHostsStats=HBL
        ShowAuthenticatedUsers=0
        ShowRobotsStats=0
        ShowEMailSenders=HBML
        ShowEMailReceivers=HBML
        ShowSessionsStats=0
        ShowPagesStats=0
        ShowFileTypesStats=0
        ShowFileSizesStats=0
        ShowBrowsersStats=0
        ShowOSStats=0
        ShowOriginStats=0
        ShowKeyphrasesStats=0
        ShowKeywordsStats=0
        ShowMiscStats=0
        ShowHTTPErrorsStats=0
        ShowSMTPErrorsStats=1
        SiteDomain=mail2.example.com
        
        1. Comment out DirIcons=/awstatsicons

Cron Configuration

  1. To /etc/cron.hourly/awstats, add:

      /usr/share/awstats/tools/awstats_buildstaticpages.pl -config=mail2 -update -configdir="/etc/awstats" -awstatsprog="/usr/share/awstats/wwwroot/cgi-bin/awstats.pl -dir=/var/www/vhosts/mail2.example.com/awstats" >/dev/null
    
  2. And for full stats for the entire year, to /etc/cron.daily/awstats, add:

      /usr/share/awstats/tools/awstats_buildstaticpages.pl -config=mail2 -update -month=all -configdir="/etc/awstats" -awstatsprog="/usr/share/awstats/wwwroot/cgi-bin/awstats.pl -dir=/var/www/vhosts/mail2.example.com/awstats-year" >/dev/null
    

Attack Detection/Blocking

  1. To /etc/fail2bain/jail.conf add the following:

      [postfix]
      enabled = true
    
      [postfix-rbl]
      enabled = true
    
  2. And finally execute systemctl enable fail2ban && systemctl start fail2ban