Table of Contents

Zimbra Mail Server

https://www.howtoforge.com/zimbra-collaboration-suite-open-source-edition-on-centos

In this tutorial I use the hostname mail.geekdept.com with the IP address of 192.168.0.45 and a gateway of 192.168.0.1. These settings should be replaced with the appropriate hostname and IP address for your setting.

Install CentOS 8 (Mail)

Set your static IPv4 IP, Netmask, Gateway and DNS (if you want to authenticate against Active Directory securely via LDAPS you should have internal DNS servers already, use these). Set your hostname to your FQDN (where outside devices will know to send your E-Mail to). Set your time zone, enable NTP. Software selection should be set to minimal. Partitioning: 1GB /boot on XFS 10GB / on XFS 4GB SWAP Remaining GB /opt on XFS Start the install and set the root password.

Initial Setup (Mail)

Update and install vim
dnf update && dnf install vim
Create sudo User + Disable root SSH Access
useradd sudo_username && passwd sudo_username
Add user to wheel group for sudo privileges
usermod -aG wheel sudo_username

Log out of root and into newly created account.

Disable root login over SSH
sudo vim /etc/ssh/sshd_config

Add/change the line to:

PermitRootLogin no
Restart SSHD
sudo systemctl restart sshd
Install required packages
sudo dnf install tar perl rsyslog wget nc libidn dnsmasq bind-utils unzip sysstat net-tools bzip2 spax
Configure FirewallD
sudo systemctl enable firewalld
sudo systemctl start firewalld
sudo firewall-cmd --permanent --zone=public --add-port=25/tcp
sudo firewall-cmd --permanent --zone=public --add-port=80/tcp
sudo firewall-cmd --permanent --zone=public --add-port=443/tcp
sudo firewall-cmd --permanent --zone=public --add-port=587/tcp
sudo firewall-cmd --permanent --zone=public --add-port=993/tcp
sudo firewall-cmd --permanent --zone=public --add-port=995/tcp
sudo firewall-cmd --permanent --zone=public --add-port=7071/tcp

For Proxy Server Access

sudo firewall-cmd --permanent --zone=public --add-port=514/udp
sudo firewall-cmd --permanent --zone=public --add-port=3443/tcp
sudo firewall-cmd --permanent --zone=public --add-port=7072/tcp
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
sudo firewall-cmd --permanent --zone=public --add-port=8443/tcp
sudo firewall-cmd --permanent --zone=public --add-port=7995/tcp
sudo firewall-cmd --permanent --zone=public --add-port=7993/tcp
sudo firewall-cmd --permanent --zone=public --add-port=389/tcp
sudo firewall-cmd --permanent --zone=public --add-port=11211/tcp
sudo firewall-cmd --permanent --zone=public --add-port=686/tcp

sudo firewall-cmd --reload
sudo systemctl daemon-reload
Configure Swappiness/Disable IPV6

Set the swappiness to reduce disk writing unless necessary (note: vm.swappiness=0 will turn off swap file where vm.swappiness=1 will only use swap in out of memory occasions; we'll use vm.swappiness=1). Also we will disable IPV6.

sudo vim /etc/sysctl.conf

Add/modify the lines:

vm.swappiness = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
Enable DNSmasq
sudo systemctl enable dnsmasq
sudo systemctl start dnsmasq
Configure Network Interface
sudo vim /etc/sysconfig/network-scripts/ifcfg-enp1s0

Remove anything with DNS1, DNS2 and IPV6 then add the line:

DNS1="127.0.0.1"
Restart Network Services
sudo nmcli connection reload && sudo systemctl restart NetworkManager
Disk Settings

FSTRIM is useful for SSDs or virtual disk images, enable anyway as it won't hurt.

sudo systemctl enable fstrim.timer
sudo systemctl start fstrim.timer

Check status of timer by showing systemd timers:

systemctl list-timers

Check trim support by:

lsblk --discard

Stop writing a timestamp every time a file is accessed Edit the /etc/fstab file and replace all the defaults strings by defaults,noatime.

sudo vim /etc/fstab

For example:

/dev/mapper/rhel-root   /         xfs     defaults        1 1

becomes:

/dev/mapper/rhel-root   /         xfs     defaults,noatime,dirsync        1 1

This completes the base installation of CentOS. On the next page we will setup Split DNS which is essential for ZCS. Go ahead and reboot, and fill up that coffee cup.

Configure Split DNS (Mail)

Setting up DNSMasq instead of BIND for bulletproof internal DNS resolution (SplitDNS) This guide will guide you through the setup of DNSMasq in order to achieve the following: - When the Zimbra server performs a DNS query for the A record of the Public Service Hostname of one of the hosted domains, answer with the LAN IP of the server itself. - When the Zimbra server performs a DNS query for the MX record of one of the hosted domains, answer with the LAN IP of the server itself. - When the Zimbra server performs any other DNS query, let another DNS server manage it. - Let DNSMasq only bind to the interface it's using so that other DNS servers can be ran on the server is needed.

Why DNSMasq instead of BIND? One word: SIMPLICITY. BIND is a full-fledged DNS server that can perform the roles of both an Authoritative and a Recursive nameserver, but chances are that you don't need this, as you probably already have an authoritative server for your domain - for example the one of your domain Registrar or a local Active Directory server - and one or more Recursive nameservers either internal, provided by your ISP or by a dedicated DNS service such as OpenDNS. So why using it when DNSMasq, a lightweight DNS forwarder, can let you achieve a Split DNS situation in a much easier way?

Our Example Environment: 192.168.0.45 is the LAN ip of your server
mail.domain.com is the hostname of the server
domain.com is the main mail domain
domain2.com is an additional mail domain
8.8.8.8 and 8.8.4.4 are the DNS servers you want to use (in this case, Google's public DNS servers, or use your internal DNS servers as noted at the start of the document…)

Edit hosts File
sudo vim /etc/hosts

Remove any IPV6 lines and add the line for your FQDN and private IP as shown in example below:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
192.168.0.45   mail.domain.com mail
Configure Resolver

To have the host resolve through dnsmasq, you have to set your localhost (127.0.0.1) as the nameserver.

sudo vim /etc/resolv.conf

Set your search domain and localhost nameserver:

search domain.com
nameserver 127.0.0.1
Configure DNSMasq

DNSMasq will bind on the local address to answer DNS queries.

We'll instruct DNSMasq to answer just some queries and in the way we want, while all other queries will be forwarded to external DNS servers. Set your nameservers(server) that will be used for external DNS queries, if using AD authentication use the DNS servers of the AD domain:

sudo vim /etc/dnsmasq.conf 

The file is quite large, I'll only write the config elements relevant to this guide. Add/modify the following lines, be sure to use your AD DNS servers if in use:

server=8.8.8.8
server=8.8.4.4
#except-interface=lo
listen-address=127.0.0.1
bind-interfaces
domain=domain.com

This sets up DNSMasq to listen on the local IP address and to only bind on the interface it's listening on. Also, it forces to answer any A-record DNS requests for mail.domain.com with the LAN IP. This is a “naive” trick that allows you to provisionally use the same hostname on two servers without any issues of sort.

In the same file (/etc/dnsmasq.conf), add one line like the following for each domain on your server:

mx-host=domain.com,mail.domain.com,10

This line instructs DNSMasq to always return “mail.domain.com” as the MX record for your domains which, if your /etc/hosts file is correctly configured will always point to the local server.

Restart DNSMasq and Check
sudo systemctl restart dnsmasq

and check that returns the local hostname/address:

dig mx domain.com

Example:

[root@mail ~]# dig mx domain.com

; <<>> DiG 9.9.4-RedHat-9.9.4-29.el7_2.2 <<>> mx domain.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57740
;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;domain.com.                  IN      MX

;; ANSWER SECTION:
domain.com.           0       IN      MX      10 mail.domain.com.

;; ADDITIONAL SECTION:
mail.domain.com.      0       IN      A       192.168.0.45

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Feb 18 14:16:12 PST 2016
;; MSG SIZE  rcvd: 79

Also, make sure that the server can correctly resolve any other IP, try pinging some public websites to verify.

Install Zimbra (Mail)

Download Zimbra from: https://www.zimbra.com/downloads/zimbra-collaboration-open-source/

try using this to bypass the form mailer: https://www.zimbra.com/try/zimbra-collaboration-open-source/thank-you/

wget the Installer
wget http://current.zimbra.url.and.package.tgz

Next untar, change into the directory of the installer and run the installer.

tar xvzf zcs…
cd zcs…
./install.sh

The output should look something like:

Checking for existing installation...
    zimbra-drive...NOT FOUND
    zimbra-imapd...NOT FOUND
    zimbra-patch...NOT FOUND
    zimbra-license-tools...NOT FOUND
    zimbra-license-extension...NOT FOUND
    zimbra-network-store...NOT FOUND
    zimbra-network-modules-ng...NOT FOUND
    zimbra-chat...NOT FOUND
    zimbra-talk...NOT FOUND
    zimbra-ldap...NOT FOUND
    zimbra-logger...NOT FOUND
    zimbra-mta...NOT FOUND
    zimbra-dnscache...NOT FOUND
    zimbra-snmp...NOT FOUND
    zimbra-store...NOT FOUND
    zimbra-apache...NOT FOUND
    zimbra-spell...NOT FOUND
    zimbra-convertd...NOT FOUND
    zimbra-memcached...NOT FOUND
    zimbra-proxy...NOT FOUND
    zimbra-archiving...NOT FOUND

Select Y for the license agreement and hit enter.

Next you need to select the packages to install. Select Y or N as indicated below.

Use Zimbra's package repository [Y]
Install zimbra-ldap [Y]
Install zimbra-logger [Y]
Install zimbra-mta [Y]
Install zimbra-dnscache [N] (remember to select No)
Install zimbra-snmp [Y]
Install zimbra-store [Y]
Install zimbra-apache [Y]
Install zimbra-spell [Y]
Install zimbra-memcached [Y]
Install zimbra-proxy [Y]
Install zimbra-drive [N] (remember to select No)
Install zimbra-imapd (BETA - for evaluation only) [N] (remember to select No)
Install zimbra-chat [N] (remember to select No)

The system will be modified. Continue? [N] Y 

You might get “DNS ERROR resolving MX for mail.domain.com…. Change domain name?” Say NO. This is likely because your public mx record is different from that of the one you setup in dnsmasq… I think.

Once the install is finished you are presented with the Main Menu. It looks like this:

Main menu

   1) Common Configuration:
   2) zimbra-ldap:                             Enabled
   3) zimbra-logger:                           Enabled
   4) zimbra-mta:                              Enabled
   5) zimbra-snmp:                             Enabled
   6) zimbra-store:                            Enabled
        +Create Admin User:                    yes
        +Admin user to create:                 admin@maila.domain.com
******* +Admin Password                        UNSET
        +Anti-virus quarantine user:           virus-quarantine.j_fhj6nf@maila.domain.com
        +Enable automated spam training:       yes
        +Spam training user:                   spam._pitqlww8@maila.domain.com
        +Non-spam(Ham) training user:          ham.usmf9z9om@maila.domain.com
        +SMTP host:                            maila.domain.com
        +Web server HTTP port:                 8080
        +Web server HTTPS port:                8443
        +Web server mode:                      https
        +IMAP server port:                     7143
        +IMAP server SSL port:                 7993
        +POP server port:                      7110
        +POP server SSL port:                  7995
        +Use spell check server:               yes
        +Spell server URL:                     http://maila.domain.com:7780/aspell.php
        +Enable version update checks:         TRUE
        +Enable version update notifications:  TRUE
        +Version update notification email:    admin@maila.domain.com
        +Version update source email:          admin@maila.domain.com
        +Install mailstore (service webapp):   yes
        +Install UI (zimbra,zimbraAdmin webapps): yes

   7) zimbra-spell:                            Enabled
   8) zimbra-proxy:                            Enabled
   9) Default Class of Service Configuration:
   s) Save config to file
   x) Expand menu
   q) Quit

Address unconfigured (**) items  (? - help)

Notice the asterisks next to the Admin Password. You need to set the Admin Password before you complete the install. To do this enter 6 at the prompt and hit enter then 4 and enter. You will be prompted to change the password. After you change the password hit r which will take you back to the previous menu. Enter a at the prompt to save the configuration.

Misc Post Setup (Mail)

Now do the following steps to run the server properly.

Configure Rsyslog
sudo vim /etc/rsyslog.conf

Uncomment these two lines:

module(load="imudp") # needs to be done just once
input(type="imudp" port="514")
Enable and Restart the Rsyslogd Service
sudo systemctl enable rsyslog
sudo systemctl restart rsyslog
Resetup Zimbra Syslog
sudo /opt/zimbra/libexec/zmsyslogsetup
Update Zimbra Auth Keys and Restart Services
sudo su - zimbra
zmupdateauthkeys
zmcontrol restart
zmcontrol status
Enable HTTPS only for Web UI
zmtlsctl https
zmcontrol restart
exit
Set SELinux Context for Init Script
sudo chcon system_u:object_r:initrc_exec_t:s0 /etc/init.d/zimbra
SeLinux for logs

https://forums.zimbra.org/viewtopic.php?t=68186

sudo semanage fcontext -a -t var_log_t "/opt/zimbra/log(/.*)?"
sudo restorecon -Rv /opt/zimbra/log
Disable Exposing Zimbra Info

https://www.basvanbeek.nl/linux/prevent-zimbra-from-sending-x-mailer-x-originating-ip-headers/

zmprov mcf zimbraSmtpSendAddMailer FALSE;
zmprov mcf zimbraSmtpSendAddOriginatingIP FALSE;
Prevent Google/etc from indexing your Zimbra server

https://www.basvanbeek.nl/miscellaneous/how-to-prevent-zimbra-from-being-indexed-by-google/

zmprov mcf zimbraMailKeepOutWebCrawlers TRUE +zimbraResponseHeader "X-Robots-Tag: noindex"
Set Message and Attachment Size Limits

https://aarvik.dk/how-to-fix-imap-bad-maximum-literal-size-exceeded-in-zimbra/index.html

zmprov modifyConfig zimbraFileUploadMaxSize 52428800
zmprov modifyConfig zimbraImapMaxRequestSize 52428800
zmprov modifyConfig zimbraMailContentMaxSize 52428800
zmprov modifyConfig zimbraMtaMaxMessageSize 52428800
zmprov mc default zimbraMailHighlightObjectsMaxSize 400
postfix reload
zmcontrol restart
Whitelist your local networks for DoSFilter

I use Z-PUSH, Outlook, Blackberry mail , iOS mail and the webclient; issue with Z-PUSH not syncing deleted items and errors in Web UI were fixed by whitelisting my local network (which includes the IPs of all inside clients, proxy servers and z-push servers.

zmprov mcf +zimbraHttpThrottleSafeIPs 10.100.0.0/16

The installation is complete and you are all set to access the administrative web interface.

You can access the admin web interface by going to https://mail.domain.com:7071

The best place to start is with domains. Right now you most likely have a domain like mail.geekdept.com. You are going to want people to send email to geekdept.com. So click on domains and add that domain to the list.

Install CentOS 8 (Proxy)

Set your static IPv4 IP, Netmask, Gateway and DNS (if you want to authenticate against Active Directory securely via LDAPS you should have internal DNS servers already, use these). Set your hostname to your FQDN (where users will go to access their webmail). Set your time zone, enable NTP. Software selection should be set to minimal. Partitioning: 1GB /boot on XFS 10GB / on XFS 4GB SWAP Start the install and set the root password.

Update and install vim
dnf update && dnf install vim
Create sudo User + Disable root SSH Access
useradd sudo_username && passwd sudo_username
Add user to wheel group for sudo privileges
usermod -aG wheel sudo_username

Log out of root and into newly created account.

Disable root login over SSH
sudo vim /etc/ssh/sshd_config

Add/change the line to:

PermitRootLogin no
Restart SSHD
sudo systemctl restart sshd
Install required packages
sudo dnf install tar perl-core rsyslog wget nc libidn bind-utils unzip sysstat net-tools bzip2
Configure FirewallD
sudo systemctl enable firewalld
sudo systemctl start firewalld
sudo firewall-cmd --permanent --zone=public --add-port=80/tcp
sudo firewall-cmd --permanent --zone=public --add-port=443/tcp
sudo firewall-cmd --permanent --zone=public --add-port=993/tcp
sudo firewall-cmd --permanent --zone=public --add-port=995/tcp
sudo firewall-cmd --permanent --zone=public --add-port=7071/tcp
sudo firewall-cmd --permanent --zone=public --add-port=514/udp

sudo firewall-cmd --reload
sudo systemctl daemon-reload
Configure Swappiness/Disable IPV6

Set the swappiness to reduce disk writing unless necessary (note: vm.swappiness=0 will turn off swap file where vm.swappiness=1 will only use swap in out of memory occasions; we'll use vm.swappiness=1). Also we will disable IPV6.

sudo vim /etc/sysctl.conf

Add/modify the lines:

vm.swappiness = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
Disk Settings

FSTRIM is useful for SSDs or virtual disk images, enable anyway as it won't hurt.

sudo systemctl enable fstrim.timer
sudo systemctl start fstrim.timer

Check status of timer by showing systemd timers:

systemctl list-timers

Check trim support by:

lsblk --discard

Stop writing a timestamp every time a file is accessed Edit the /etc/fstab file and replace all the defaults strings by defaults,noatime.

sudo vim /etc/fstab

For example:

/dev/mapper/rhel-root   /         xfs     defaults        1 1

becomes:

/dev/mapper/rhel-root   /         xfs     defaults,noatime,dirsync        1 1
Configure hosts File

Our Example Environment:
192.168.0.45 is the LAN ip of your server
192.168.0.46 is the LAN ip of your proxy server
mail.domain.com is the hostname of the server
webmail.domain.com is the hostname of the proxy server
domain.com is the main mail domain
domain2.com is an additional mail domain
8.8.8.8 and 8.8.4.4 are the DNS servers you want to use (in this case, Google's public DNS servers)

sudo vim /etc/hosts

Remove IPV6 line and add the 2 entries, 1 for the proxy server and one for the mail server:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
192.168.0.45   mail.domain.com mail
192.168.0.46   webmail.domain.com webmail

Note: be sure to add the Proxy server domain and IP in all the other Zimbra server /etc/hosts files.

Install Zimbra (Proxy)

Download Zimbra from: https://www.zimbra.com/downloads/zimbra-collaboration-open-source/

try using this to bypass the form mailer: https://www.zimbra.com/try/zimbra-collaboration-open-source/thank-you/

wget the Installer
wget http://current.zimbra.url.and.package.tgz

Next untar, change into the directory of the installer and run the installer.

tar xvzf zcs…
cd zcs…
./install.sh

The output should look something like:

Checking for existing installation...
    zimbra-drive...NOT FOUND
    zimbra-imapd...NOT FOUND
    zimbra-patch...NOT FOUND
    zimbra-license-tools...NOT FOUND
    zimbra-license-extension...NOT FOUND
    zimbra-network-store...NOT FOUND
    zimbra-network-modules-ng...NOT FOUND
    zimbra-chat...NOT FOUND
    zimbra-talk...NOT FOUND
    zimbra-ldap...NOT FOUND
    zimbra-logger...NOT FOUND
    zimbra-mta...NOT FOUND
    zimbra-dnscache...NOT FOUND
    zimbra-snmp...NOT FOUND
    zimbra-store...NOT FOUND
    zimbra-apache...NOT FOUND
    zimbra-spell...NOT FOUND
    zimbra-convertd...NOT FOUND
    zimbra-memcached...NOT FOUND
    zimbra-proxy...NOT FOUND
    zimbra-archiving...NOT FOUND

Select Y for the license agreement and hit enter.

Next you need to select the packages to install. Select Y or N as indicated below.

Use Zimbra's package repository [Y]
Install zimbra-ldap [N]
Install zimbra-logger [N]
Install zimbra-mta [N]
Install zimbra-dnscache [N] (remember to select No)
Install zimbra-snmp [N]
Install zimbra-store [N]
Install zimbra-apache [N]
Install zimbra-spell [N]
Install zimbra-memcached [Y]
Install zimbra-proxy [Y]
Install zimbra-drive [N] (remember to select No)
Install zimbra-imapd (BETA - for evaluation only) [N] (remember to select No)
Install zimbra-chat [N] (remember to select No)

The system will be modified. Continue? [N] Y 
Retrieve Zimbra LDAP master URL and Password

To connect the Proxy install to the Mail Server you will need to know the LDAP url and password. http://platonic.techfiz.info/2014/03/retrieve-zimbra-ldap-master-url/

Do this in the main Zimbra server:

sudo su – zimbra
zmlocalconfig -s zimbra_ldap_password ldap_master_url

For the url, just use the domain name, not the ldaps and 389 at the end; eg: only mail.domain.com.

The same command might reveal the admin password too. You can also use the following commands to retrieve the ldap admin password:

zmlocalconfig -s | grep ldap_amavis_password
zmlocalconfig -s | grep ldap_nginx_password
zmlocalconfig -s | grep ldap_postfix_password
zmlocalconfig -s | grep ldap_replication_password
zmlocalconfig -s | grep ldap_root_password
zmlocalconfig -s | grep zimbra_ldap_password
Secure Zimbra Interserver Communication

Make sure ALL servers use secure communications between one another (i.e run these commands on ALL Zimbra installs and Proxy, etc): https://wiki.zimbra.com/wiki/TLS/STARTTLS_Localconfig_Values

zmlocalconfig -e zimbra_require_interprocess_security=1
zmlocalconfig -e ldap_starttls_supported=1
zmlocalconfig -e ldap_starttls_required=true

Misc Post Setup (Proxy)

Now do the following steps to run the server properly.

Configure Rsyslog
sudo vim /etc/rsyslog.conf

Uncomment these two lines:

module(load="imudp") # needs to be done just once
input(type="imudp" port="514")
Enable and Restart the Rsyslogd Service
sudo systemctl enable rsyslog
sudo systemctl restart rsyslog
Resetup Zimbra Syslog
sudo /opt/zimbra/libexec/zmsyslogsetup
Update Zimbra Auth Keys and Restart Services
sudo su - zimbra
zmupdateauthkeys
zmcontrol restart
zmcontrol status
Enable HTTPS only for Web UI
zmtlsctl https
zmcontrol restart
exit
Set SELinux Context for Init Script
sudo chcon system_u:object_r:initrc_exec_t:s0 /etc/init.d/zimbra
SeLinux for logs

https://forums.zimbra.org/viewtopic.php?t=68186

sudo semanage fcontext -a -t var_log_t "/opt/zimbra/log(/.*)?"
sudo restorecon -Rv /opt/zimbra/log
Fix Logging Issue for DoS Filter

https://wiki.zimbra.com/wiki/How_to_fix_multiple_OIP_logging_issue

I was seeing a lot of

Ignoring malformed remote address 99.99.99.99, 10.49.100.22

in my zmmailboxd.out

Run this on the proxy server

sed -i 's/$proxy_add_x_forwarded_for/$http_x_forwarded_for/g' /opt/zimbra/conf/nginx/templates/*
zmproxyctl restart

The installation is complete and you are all set to access the web interface.

You can access the admin web interface by going to https://webmail.domain.com

Install CentOS 7 (Z-PUSH)

CentOS 7 is used instead of 8 since there is no Z-PUSH repo for 8 yet.

Set your static IPv4 IP, Netmask, Gateway and DNS (if you want to authenticate against Active Directory securely via LDAPS you should have internal DNS servers already, use these). Set your hostname to your FQDN (set this to autodiscover.domain.com). Set your time zone, enable NTP. Software selection should be set to minimal. Partitioning:
1GB /boot on XFS
10GB / on XFS
4GB SWAP
Start the install and set the root password.

https://wiki.z-hub.io/display/ZP/Installation

Initial Setup (Z-PUSH)

Update and install vim
yum update && yum install vim
Create sudo User + Disable root SSH Access
useradd sudo_username && passwd sudo_username
Add user to wheel group for sudo privileges
usermod -aG wheel sudo_username

Log out of root and into newly created account.

Disable root login over SSH
sudo vim /etc/ssh/sshd_config

Add/change the line to:

PermitRootLogin no
Restart SSHD
sudo systemctl restart sshd
Install Z-PUSH Repo
sudo vim /etc/yum.repos.d/z-push.repo

Add the following:

[z-push]
name=Z-Push noarch Enterprise Linux 7 - $basearch
baseurl=http://repo.z-hub.io/z-push:/final/RHEL_7
failovermethod=priority
enabled=1
gpgcheck=0
Install Remi PHP 7.4 Repo
sudo yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo yum install yum-utils
sudo yum-config-manager --enable remi-php74
Install required packages
sudo yum install z-push-common z-push-config-apache z-push-autodiscover z-push-backend-carddav wget vim mod_ssl z-push-ipc-sharedmemory php-cli php-soap php-process php-mbstring php
Configure FirewallD
sudo firewall-cmd --permanent --zone=public --add-port=80/tcp
sudo firewall-cmd --permanent --zone=public --add-port=443/tcp
sudo firewall-cmd --reload
sudo systemctl daemon-reload
Configure Swappiness/Disable IPV6

Set the swappiness to reduce disk writing unless necessary (note: vm.swappiness=0 will turn off swap file where vm.swappiness=1 will only use swap in out of memory occasions; we'll use vm.swappiness=1). Also we will disable IPV6.

sudo vim /etc/sysctl.conf

Add/modify the lines:

vm.swappiness = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
Disk Settings

FSTRIM is useful for SSDs or virtual disk images, enable anyway as it won't hurt.

sudo systemctl enable fstrim.timer
sudo systemctl start fstrim.timer

Check status of timer by showing systemd timers:

systemctl list-timers

Check trim support by:

lsblk --discard

Stop writing a timestamp every time a file is accessed Edit the /etc/fstab file and replace all the defaults strings by defaults,noatime.

sudo vim /etc/fstab

For example:

/dev/mapper/rhel-root   /         xfs     defaults        1 1

becomes:

/dev/mapper/rhel-root   /         xfs     defaults,noatime,dirsync        1 1

Configure hosts File

Our Example Environment: 192.168.0.45 is the LAN ip of your server
192.168.0.46 is the LAN ip of your proxy server
192.168.0.47 is the LAN ip of your ZPUSH server
mail.domain.com is the hostname of the server
webmail.domain.com is the hostname of the proxy server
autodiscover.domain.com is the hostname of the ZPUSH server
domain.com is the main mail domain
domain2.com is an additional mail domain
8.8.8.8 and 8.8.4.4 are the DNS servers you want to use (in this case, Google's public DNS servers)

sudo vim /etc/hosts

Remove IPV6 line and add the 2 entries, 1 for the proxy server and one for the mail server:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
192.168.0.45   mail.domain.com mail
192.168.0.46   webmail.domain.com webmail
192.168.0.47   autodiscover.domain.com autodiscover

Note: be sure to add the Proxy server and ZPUSH server domainnames and IPs in all the other Zimbra server /etc/hosts files.

Apache and Zimbra Backend (Z-PUSH)

Configure Apache
sudo systemctl enable httpd
sudo systemctl start httpd
####sudo chown -R apache: /usr/share/z-push
####sudo chmod 755 /var/lib/z-push /var/log/z-push
sudo chown apache:apache /var/lib/z-push /var/log/z-push
sudo chcon -R -t httpd_sys_rw_content_t /var/lib/z-push
sudo chcon -R -t httpd_sys_rw_content_t /var/log/z-push
sudo rm /etc/httpd/conf.d/welcome.conf
Disable Default Published Apache Directory
sudo vim /etc/httpd/conf/httpd.conf

Set the following Directory statements with only the following options:

DocumentRoot "/var/www/html"

<Directory "/var/www">
    AllowOverride None
    Require all denied
    Options None
</Directory>

<Directory "/var/www/html">
    AllowOverride None
    Require all denied
    Options None
</Directory>

<Directory "/var/www/cgi-bin">
    AllowOverride None
    Require all denied
    Options None
</Directory>
Configure Z-PUSH
sudo vim /usr/share/z-push/config.php

Find the backend provider initialization - and replace with Zimbra - as follows:

    define('BACKEND_PROVIDER', ‘BackendZimbra');
  define('TIMEZONE', ‘America/Los_Angeles');
  define('PROVISIONING', false);
Configure Z-PUSH Autodiscover

https://wiki.z-hub.io/display/ZP/Configuring+Z-Push+Autodiscover

First you'll need public DNS entries pointing your Z-PUSH server, the name needs to be autodiscover.maildomain.com. Later you'll need a valid TLS certificate for the Z-PUSH server.

sudo vim /usr/share/z-push/autodiscover.php

Set the following:

    define('TIMEZONE', 'America/Los_Angeles');
    define('USE_FULLEMAIL_FOR_LOGIN', true);
    define('BACKEND_PROVIDER','BackendZimbra');

http://vwiki.co.uk/Z-Push_v2_with_Zimbra#Pre_Z-Push_v2.0.6 Z-Push v2 with Zimbra Share The procedure below should get you up and running so that you can sync your mobile device to your Zimbra server, using the Active-Sync protocol, provided by Z-Push. It doesn't include setting up provisioning, which is the Active-Sync feature that enhances security by providing a mechanism to remote wipe your devices, enforce storage encryption etc. Buried in the Zimbra forum thread are instructions on how to set it up - Z-Push Zimbra Backend (Push Email, Contacts, Appointments & Tasks) - Zimbra :: Forums. Do not attempt to install Z-Push on the same server as Zimbra. It is possible, but will require you to hack your Zimbra installation, and performing a Zimbra upgrade will probably break Z-Push. Z-Push is essentially a website. Mobile devices access the site in order to be able to sync with your Zimbra server. Therefore, you need a publicly accessible server that can host the site, and a DNS record that points to it (that client mobile devices will need to be able to resolve) You are advised to read the INSTALL file that comes with the Zimbra backend before you attempt the install. Don't just blindly follow the steps below, they should work but are intended to provide additional support and not to replace any of the documentation supplied by Z-Push or the Zimbra Backend's authors. You may miss a critical dependency or alteration required for your environment. Version 65 and later has a script “zpzb-install.sh” to automate the install. Download that into your z-push backend folder (/usr/share/z-push/backend) along with the backend archive: https://sourceforge.net/projects/zimbrabackend/files/

Download Zimbra Backend
cd /usr/share/z-push/backend
sudo wget https://sourceforge.net/projects/zimbrabackend/files/Release70/zimbra70.tgz
sudo wget https://sourceforge.net/projects/zimbrabackend/files/Release70/zpzb-install.sh
Make Installer Executable then Install

Execute the script by typing ./zpzb-install.sh NN. The latest zimbraNN.tgz will be extracted into a directory zimbraNN

sudo chmod +700 zpzb-install.sh
sudo ./zpzb-install.sh 79
Edit Backend
sudo vim ./zimbra/config.php

Then edit the config.php in the ./backend/zimbra folder: Add your server address (the Proxy server address is preferred, you can also use the DNS name instead of the IP if your hosts file is setup properly):

  define('ZIMBRA_URL', 'https://webmail.mailserver.com');

Add another option if z-push is on the same private subnet as the Zimbra server:

  define('ZIMBRA_DISABLE_URL_OVERRIDE', true);

Some additional steps are sometimes required due to bugs etc, see the INSTALL file included with the backend for more info.

  • If running Zimbra 7.2 onwards and have clients with multiple devices you need to allow them to connect simultaneously, on your Zimbra server allow an appropriate number of sessions (default is 5) 
      ◦ zmlocalconfig -e zimbra_session_limit_soap=7 
      ◦ zmconfigdctl reload 
  • If running Zimbra 8 onwards you need to whitelist your Z-Push server otherwise its likely to get blocked by Zimbra, on your Zimbra server allow your Z-Push server's IP address 
Whitelist Z-PUSH Server in Zimbra
zmprov mcf +zimbraHttpThrottleSafeIPs 192.168.0.47
Testing

In theory, it should be working now, in order to test…

    1. Browse to your server, eg http://autodiscover.domain.com/Microsoft-Server-ActiveSync 
        ◦ You should be prompted for a username and password (for an account on your Zimbra server) 
        ◦ If Apache has failed to deliver the prompt to you, check the webserver log. Either your website isn't configured correctly or Z-Push experienced a PHP error. 
    2. Enter a valid Zimbra user/pass  (use the full email address for the username)
        ◦ You should get a page showing "Z-Push - Open Source ActiveSync" which doesn't contain errors - this confirms that connectivity exists between all the required components (Apache, Z-Push, Zimbra), and that they are basically OK. 
Configure Autodiscover Backend

You'll want this if you want autodiscover to work…

sudo vim /usr/share/z-push/autodiscover/config.php

Find the backend provider initialization - and replace with Zimbra - as follows:

    define('BACKEND_PROVIDER', ‘BackendZimbra');
  define('TIMEZONE', ‘America/Los_Angeles');
  define('USE_FULLEMAIL_FOR_LOGIN', true);
Modify Z-PUSH Conf File

This was neccessary to pass the Activesync test

sudo vim /etc/httpd/conf.d/z-push.conf

Erase everything above # Security and add this:

# Z-Push - ActiveSync over-the-air - default Apache configuration
<IfModule mod_alias.c>
    Alias /Microsoft-Server-ActiveSync /usr/share/z-push/index.php
AliasMatch (?i)/Autodiscover/Autodiscover.xml "/usr/share/z-push/autodiscover/autodiscover.php"
</IfModule>

<Directory /usr/share/z-push>
    # Don't list a directory index, follow symlinks (maybe state dir is somewhere linked)
    DirectoryIndex index.php
    Options -Indexes +FollowSymLinks

    # Z-push requirements
    php_value magic_quotes_gpc off
    php_value magic_quotes_runtime off
    php_value register_globals off
    php_value short_open_tag on

    # Optional
    # php_value display_errors off

    # Setting memory limit higher (larger attachments)
    php_value memory_limit 128M

Restart Apache

sudo systemctl restart httpd
Fix Z-PUSH Logrotate

This was needed to make the bundled z-push.lr work on CentOS

sudo chown apache:apache /var/log/z-push

Modify the logrotate config:

sudo vim /etc/logrotate.d/z-push.lr

Edit so that is matches the following:

/var/log/z-push/*.log {
        size 1k
        create 664 root z-push
        compress
        rotate 4
        su root z-push
}

You can change the rotate 4 to a higher value if you want a longer history, just make sure you have enough disk space for it.

Letsencrypt (Z-PUSH)

Make sure you have port 80 and 443 tcp forwarded to your Z-PUSH server and the public A record pointing the autodiscover address to your public IP.

Create Virtualhost

This is needed so Certbot can validate a running virtualhost

sudo vim /etc/httpd/conf.d/autodiscover.domain.com.conf

Add the following:

<VirtualHost *:80>
     ServerName autodiscover.domain.com
</VirtualHost>

Create a new autodiscover virtual host for each email domain you'll be using.

Remove Apache Welcome Page
sudo rm /etc/httpd/conf.d/welcome.conf
Restart Apache
sudo systemctl restart httpd
Install certbot (via snapd)

Install/enable epel-release and snapd

sudo yum install epel-release
sudo yum install snapd
sudo systemctl enable --now snapd.socket
sudo systemctl start snapd
sudo ln -s /var/lib/snapd/snap /snap
sudo snap install core; sudo snap refresh core

Remove old certbot if it exists

sudo yum remove certbot
sudo sed -i '/certbot-auto/d' /etc/crontab
sudo rm /usr/local/bin/certbot-auto
sudo rm -rf /opt/eff.org

Install certbot via snap

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Request and install certificates for virtual hosts

sudo /usr/bin/certbot --apache

When prompted enabled Redirect so all requests go over https

Enable autorenew via crontab
echo "0 0,12 * * * root python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/bin/certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
Manual Certificate Renewal for Z-PUSH
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr

Fill out requested info, put in domain name you're creating the certificate for when asked for the server name.

Submit the CSR

For Namecheap.com

Download the CRT and Bundle from Namecheap and copy the crt, bundle and server.key to their respective locations per your .conf file

Edit the Apache conf file:
SSLCertificateFile /etc/pki/tls/certs/autodiscover_domain_com.crt

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
SSLCertificateKeyFile /etc/pki/tls/private/server.key

#   Certificate Authority (CA):
#   Set the CA certificate verification path where to find CA
#   certificates for client authentication or alternatively one
#   huge file containing all of them (file must be PEM encoded)
SSLCACertificateFile /etc/pki/tls/certs/autodiscover_domain_com.bundle

chmod the server.key file to 600

Restart Apache

Fail2ban (Z-PUSH)

https://wiki.z-hub.io/display/ZP/Fail2Ban+support

Install Fail2ban
sudo yum install fail2ban policycoreutils-python
Enable Auth Fail Logging
sudo vim /etc/z-push/z-push.conf.php

Set the following:

define('LOGAUTHFAIL', true);
Create a Jail for SSHd
sudo vim /etc/fail2ban/jail.d/sshd.local

Add the following:

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

[selinux-ssh]
enabled  = true
port     = ssh
logpath  = %(auditd_log)s
Create a Jail for Apache
sudo vim /etc/fail2ban/jail.d/apache.local

Add the following:

[apache-auth]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s

[apache-badbots]
enabled  = true
port     = http,https
logpath  = %(apache_access_log)s
bantime  = 48h
maxretry = 1

[apache-noscript]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s

[apache-overflows]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2

[apache-nohome]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2

[apache-botsearch]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2

[apache-fakegooglebot]
enabled  = true
port     = http,https
logpath  = %(apache_access_log)s
maxretry = 1
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>

[apache-modsecurity]
enabled  = true
port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2

[apache-shellshock]
enabled = true
port    = http,https
logpath = %(apache_error_log)s
maxretry = 1
Create a filter for Z-PUSH
sudo vim /etc/fail2ban/filter.d/z-push.conf

Add the following:

# FILE : /etc/fail2ban/filter.d/z-push.conf
# Fail2Ban configuration file
[INCLUDES]
before = common.conf
[Definition]
# Option:  failregex
# Notes.:  regex to match the password failures messages in the logfile. The
#          host must be matched by a group named "host". The tag "<HOST>" can
#          be used for standard IP/hostname matching and is only an alias for
#          (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values:  TEXT
#
failregex = IP: <HOST> failed to authenticate user
ignoreregex =
[Init]
journalmatch = _SYSTEMD_UNIT=fail2ban.service
Create a jail for Z-PUSH
sudo vim /etc/fail2ban/jail.d/z-push.local

Add the following:

# z-push.local
[z-push]
enabled  = true
port     = http,https
filter   = z-push
logpath = /var/log/z-push/z-push-error.log
maxretry = 5
bantime  = 7200
Fix SELinux Issue

After an update SELinux and Fail2Ban is broken: https://bugzilla.redhat.com/show_bug.cgi?id=1777562

We'll need to use audit2allow to fix this.

Set selinux to Permissive mode
setenforce 0
Restart/Enable/Check Services
sudo systemctl restart httpd
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
sudo fail2ban-client status z-push
Use audit2allow to Generate selinux Rule

https://wiki.centos.org/HowTos/SELinux

sudo grep fail2ban /var/log/audit/audit.log | sudo audit2allow -m fail2banlocal > fail2banlocal.te

Check the file to make sure it looks like everything is on the up and up.

Now make the rule:

sudo grep fail2ban /var/log/audit/audit.log | sudo audit2allow -M fail2banlocal

Make the policy active:

sudo semodule -i fail2banlocal.pp

Re-enable selinux:

sudo setenforce 1

Restart fail2ban:

sudo systemctl restart fail2ban
sudo fail2ban-client status z-push

Test it by logging into https://autodiscover.domain.com with an incorrect username/password 5 times then check:

sudo fail2ban-client status z-push

Unban your IP by typing:

sudo fail2ban-client unban --all

Install TLS/SSL certificate

I use the Positive SSL from namecheap.com which is a Comodo SSL.

https://wiki.zimbra.com/wiki/Installing_a_Comodo_SSL_Certificate_on_Zimbra_Collaboration

Generate the CSR via the admin console: Configure → Certificates → Install Certificate (for each Zimbra Server)

Download the archives that the CA sends, copy crt only to the /tmp folder (even though the CSR is generated on the Admin console, installing the certificates is done on the actual server that uses the certificate)

Download the root/intermediate certificates:
Sectigo RSA DV Bundle [ Intermediate + Cross Signed ] (SectigoRSADVBundle.pem)
SHA-2 Root : USERTrust RSA Certification Authority (SHA-2 Root USERTrust RSA Certification Authority.crt)
from: https://support.sectigo.com/Com_KnowledgeDetailPage?Id=kA01N000000rfBO . Copy them to the /tmp folder.

Combine the Root and Intermediate certificates (do this on each respective Zimbra server):

cat /tmp/"SHA-2 Root  USERTrust RSA Certification Authority.crt" /tmp/SectigoRSADVBundle.pem > /tmp/commercial_ca.crt
cp /tmp/my_domain_com.crt /tmp/commercial.crt

If the command below fails try adding the contents of “SHA-2 Root USERTrust RSA Certification Authority.crt” to the top of “SectigoRSADVBundle.pem” and rename that commercial_ca.crt

For the commerical_ca.crt this worked as of June 13 2024 (here as a shortcut to those of you that are doing this certificate renewal thing on Zimbra often)

-----BEGIN CERTIFICATE-----
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBjzELMAkGA1UEBhMCR0IxGzAZBgNV
BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE
ChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFJTQSBEb21haW4g
VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA1nMz1tc8INAA0hdFuNY+B6I/x0HuMjDJsGz99J/LEpgPLT+N
TQEMgg8Xf2Iu6bhIefsWg06t1zIlk7cHv7lQP6lMw0Aq6Tn/2YHKHxYyQdqAJrkj
eocgHuP/IJo8lURvh3UGkEC0MpMWCRAIIz7S3YcPb11RFGoKacVPAXJpz9OTTG0E
oKMbgn6xmrntxZ7FN3ifmgg0+1YuWMQJDgZkW7w33PGfKGioVrCSo1yfu4iYCBsk
Haswha6vsC6eep3BwEIc4gLw6uBK0u+QDrTBQBbwb4VCSmT3pDCg/r8uoydajotY
uK3DGReEY+1vVv2Dy2A0xHS+5p3b4eTlygxfFQIDAQABo4IBbjCCAWowHwYDVR0j
BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFI2MXsRUrYrhd+mb
+ZsF4bgBjWHhMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAbBgNVHSAEFDASMAYGBFUdIAAw
CAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0
LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2Bggr
BgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNv
bS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDov
L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMr9hvQ5Iw0/H
ukdN+Jx4GQHcEx2Ab/zDcLRSmjEzmldS+zGea6TvVKqJjUAXaPgREHzSyrHxVYbH
7rM2kYb2OVG/Rr8PoLq0935JxCo2F57kaDl6r5ROVm+yezu/Coa9zcV3HAO4OLGi
H19+24rcRki2aArPsrW04jTkZ6k4Zgle0rj8nSg6F0AnwnJOKf0hPHzPE/uWLMUx
RP0T7dWbqWlod3zu4f+k+TY4CFM5ooQ0nBnzvg6s1SQ36yOoeNDT5++SR2RiOSLv
xvcRviKFxmZEJCaOEDKNyJOuB56DPi/Z+fVGjmO+wea03KbNIaiGCpXZLoUmGv38
sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFgTCCBGmgAwIBAgIQOXJEOvkit1HX02wQ3TE1lTANBgkqhkiG9w0BAQwFADB7
MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
VQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UE
AwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTE5MDMxMjAwMDAwMFoXDTI4
MTIzMTIzNTk1OVowgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5
MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBO
ZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0
aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgBJlFzYOw9sI
s9CsVw127c0n00ytUINh4qogTQktZAnczomfzD2p7PbPwdzx07HWezcoEStH2jnG
vDoZtF+mvX2do2NCtnbyqTsrkfjib9DsFiCQCT7i6HTJGLSR1GJk23+jBvGIGGqQ
Ijy8/hPwhxR79uQfjtTkUcYRZ0YIUcuGFFQ/vDP+fmyc/xadGL1RjjWmp2bIcmfb
IWax1Jt4A8BQOujM8Ny8nkz+rwWWNR9XWrf/zvk9tyy29lTdyOcSOk2uTIq3XJq0
tyA9yn8iNK5+O2hmAUTnAU5GU5szYPeUvlM3kHND8zLDU+/bqv50TmnHa4xgk97E
xwzf4TKuzJM7UXiVZ4vuPVb+DNBpDxsP8yUmazNt925H+nND5X4OpWaxKXwyhGNV
icQNwZNUMBkTrNN9N6frXTpsNVzbQdcS2qlJC9/YgIoJk2KOtWbPJYjNhLixP6Q5
D9kCnusSTJV882sFqV4Wg8y4Z+LoE53MW4LTTLPtW//e5XOsIzstAL81VXQJSdhJ
WBp/kjbmUZIO8yZ9HE0XvMnsQybQv0FfQKlERPSZ51eHnlAfV1SoPv10Yy+xUGUJ
5lhCLkMaTLTwJUdZ+gQek9QmRkpQgbLevni3/GcV4clXhB4PY9bpYrrWX1Uu6lzG
KAgEJTm4Diup8kyXHAc/DVL17e8vgg8CAwEAAaOB8jCB7zAfBgNVHSMEGDAWgBSg
EQojPpbxB+zirynvgqV/0DCktDAdBgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rID
ZsswDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAG
BgRVHSAAMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29t
L0FBQUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggr
BgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUA
A4IBAQAYh1HcdCE9nIrgJ7cz0C7M7PDmy14R3iJvm3WOnnL+5Nb+qh+cli3vA0p+
rvSNb3I8QzvAP+u431yqqcau8vzY7qN7Q/aGNnwU4M309z/+3ri0ivCRlv79Q2R+
/czSAaF9ffgZGclCKxO/WIu6pKJmBHaIkU4MiRTOok3JMrO66BQavHHxW/BBC5gA
CiIDEOUMsfnNkjcZ7Tvx5Dq2+UUTJnWvu6rvP3t3O9LEApE9GQDTF1w52z97GA1F
zZOFli9d31kWTz9RvdVFGD/tSo7oBmF0Ixa1DVBzJ0RHfxBdiSprhTEUxOipakyA
vGp4z7h/jnZymQyd/teRCBaho1+V
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
-----END CERTIFICATE-----
Validate Certificates and Chains

If you get an error here you can't continue.

/opt/zimbra/bin/zmcertmgr verifycrt comm /opt/zimbra/ssl/zimbra/commercial/commercial.key /tmp/commercial.crt /tmp/commercial_ca.crt
Deploy the Certificates
/opt/zimbra/bin/zmcertmgr deploycrt comm /tmp/commercial.crt /tmp/commercial_ca.crt
zmcontrol restart

</code>

Enable LDAPS
zmlocalconfig -e ldap_common_require_tls=1
zmcontrol restart

Fail2Ban (MAIL & PROXY)

NOTE: this needs to be tested and modified accordingly (07-03-2020)
NOTE: If a user account gets disabled in Zimbra due to too many incorrect logins, it's likely the IP is also banned in Fail2Ban on the Z-PUSH/Proxy/Mail servers.

Install Fail2Ban
sudo dnf install epel-release
sudo dnf install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Create a Jail for SSHd
sudo vim /etc/fail2ban/jail.d/sshd.local

Add the following:

[sshd]
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

[selinux-ssh]
enabled  = true
port     = ssh
logpath  = %(auditd_log)s
Create Zimbra Filter

https://github.com/leogallego/fail2ban-zimbra

sudo vim /etc/fail2ban/filter.d/zimbra.conf

Add the following:

# Fail2Ban configuration file
#
# Author: Leonardo A. Gallego <leonardo.gallego @ gmail.com>
#
#
[Definition]
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named "host". The tag "<HOST>" can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
failregex =     \[ip=<HOST>;\] account – authentication failed for .* \(no such account\)$
                \[ip=<HOST>;\] security – cmd=Auth; .* error=authentication failed for .*, invalid password;$
                \[ip=<HOST>;\] security – cmd=AdminAuth; .* error=authentication failed for .*, invalid password;$
                \[ip=<HOST>;\] security – cmd=Auth; .* error=authentication failed for .*, account lockout$
                \[ip=<HOST>;\] account – authentication failed for .* \(account lockout\)$
                ;oip=<HOST>;.* security – cmd=Auth; .* protocol=soap; error=authentication failed for .* invalid password;$
                \[oip=<HOST>;.* SoapEngine – handler exception: authentication failed for .*, account not found$
                WARN .*ip=<HOST>;ua=ZimbraWebClient .* security – cmd=AdminAuth; .* error=authentication failed for .*;$
                WARN  \[.*\] \[name=.*;ip=<HOST>;ua=.*;\] security - cmd=Auth; account=.*; protocol=.*; error=.*, invalid password;
                INFO .*ip=<HOST>;ua=zclient.*\] .* authentication failed for \[.*\], (invalid password|account not found)+$
                NOQUEUE: reject: RCPT from .*\[<HOST>\]: 550 5.1.1 .*: Recipient address rejected:


# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#ignoreregex =
Create a Postfix SASL Filter
sudo vim /etc/fail2ban/filter.d/postfix-sasl.conf

Add the following:

# Fail2Ban filter for postfix authentication failures
#
#
# Author: Leonardo A. Gallego
# Revision: 16.12.05
# Description: Modified SASL filter for Zimbra Postfix authentication failures

[INCLUDES]

before = common.conf

[Definition]

_daemon = postfix/smtpd

failregex = (?i): warning: [-._\w]+\[<HOST>\]: SASL (?:LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [A-Za-z0-9+/ ]*)?$

#ignoreregex =
Create Zimbra Jail

https://forums.zimbra.org/viewtopic.php?t=58894

sudo vim /etc/fail2ban/jail.d/zimbra.local

Add the following:

# Zimbra 8.0.x compatible
[DEFAULT]
ignoreip = 200.200.200/32 ##Put the IP of your external relay if you use one, I've had issues with zimbra-recipient banning our relay as of 8.8 with the rules used in this document...


[zimbra-account]
### Set to enabled = false on Zimbra Proxy
enabled = true
filter = zimbra
action = iptables-allports[name=Zimbra-account]
logpath = /opt/zimbra/log/mailbox.log
bantime = 7200
maxretry = 5

[zimbra-audit]
### Set to enabled = false on Zimbra Proxy
enabled = true
filter = zimbra
action = iptables-allports[name=Zimbra-audit]
logpath = /opt/zimbra/log/audit.log
bantime = 7200
maxretry = 5

[zimbra-recipient]
enabled = true
filter = zimbra
action = iptables-allports[name=Zimbra-recipient]
logpath = /var/log/zimbra.log
findtime = 604800
bantime = 7200
maxretry = 5

[postfix]
enabled = true
filter = postfix
action = iptables-multiport[name=Postfix, port=smtp, protocol=tcp]
logpath = /var/log/zimbra.log
bantime = 7200
maxretry = 5

[sasl-iptables]
enabled = true
#filter = sasl
filter   = postfix-sasl
action = iptables-allports[name=sasl]
logpath = /var/log/zimbra.log
bantime = 7200
maxretry = 5

# filter: postfix-sasl must exist in filter.d
Restart Fail2Ban and Check Status
sudo systemctl restart fail2ban
sudo fail2ban-client status

Misc Polishing

Add Proxy and Z-PUSH Server IPs to Trusted List

This allows external IP addresses to show up as OIP in Zimbra logs, plus other useful stuff I’m sure. The needs to be done on a single server only, preferably the main server.

zmprov mcf +zimbraMailTrustedIP 192.168.0.46
zmprov mcf +zimbraMailTrustedIP 192.168.0.47
zmcontrol restart
Verify the Settings
zmprov gcf zimbraMailTrustedIP
Relaying/Domain Forwarding

https://wiki.zimbra.com/wiki/Managing_Domains

If you want the Zimbra server to relay all mail destined for a particular domain (say, example.com) to another mta (say, other-mta.domain.com), you can forward the domain.

zmprov
md example.com zimbraMailCatchAllAddress @example.com
md example.com zimbraMailCatchAllForwardingAddress @example.com 
md example.com zimbraMailTransport smtp:other-mta.domain.com
Removal of Relaying/Domain Forwarding

If at a later date you wish to remove the domain forwarding/catchall address run the following commands:

zmprov md domain.com zimbraMailCatchAllAddress ""
zmprov md domain.com zimbraMailCatchAllForwardingAddress ""
zmprov md domain.com zimbraMailTransport lmtp:server.domain.com:7025

Where domain.com is your domain and server.domain.com is the FQDN (Fully Qualified Domain Name) of your Zimbra server.

Domain Catchall

If you want to set up an account “user@domain.com” to catch any mail not delivered to existing users in the domain “domain.com”, you can configure the account as a domain catchall.

zmprov modifyAccount user@domain.com zimbraMailCatchAllAddress @domain.com

If the users “john@domain.com”, “webmaster@domain.com”, and “xyznobody@domain.com” don't exist, and mail arrives for them, it will be delivered to the catchall account “user@domain.com”. This will increase the amount of spam delivered, and can lead to being blacklisted. To remove the catchall from an email account, unset the catchall address:

zmprov modifyAccount user@domain.com zimbraMailCatchallAddress ""
DKIM

https://wiki.zimbra.com/wiki/Configuring_for_DKIM_Signing

We normally use a relay to send E-mail through and DKIM signatures are added there, but with DMARC added internal messages were being flagged as SPAM so it appears E-Mail that doesn't go out through the relay will need to be signed as well.

Add DKIM data

/opt/zimbra/libexec/zmdkimkeyutil -a -d example.com

Copy the data it generates and record it in your Zimbra document. Create a DNS record for the public DKIM key.

Tuning

Incorporate some of info found here after verification: https://wiki.zimbra.com/wiki/Ajcody-Mysql-Topics

Incorporate some of info found here after verification: https://forums.zimbra.org/viewtopic.php?t=18006

Use a Mysql tuner which will check and make recommendations for mysql settings (note: use after production server is running for over 24hours, run at least once a year): https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl

wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
mv mysqltuner.pl /opt/zimbra/mysqltuner.pl
chown zimbra.zimbra /opt/zimbra/mysqltuner.pl
chmod +x /opt/zimbra/mysqltuner.pl
su - zimbra
./mysqltuner.pl

Set Cache sizes

This is for inactive IMAP sessions
https://forums.zimbra.org/viewtopic.php?f=15&t=62916

zmprov ms `zmhostname` zimbraImapInactiveSessionEhcacheSize 104857600
zmprov ms `zmhostname` zimbraImapInactiveSessionCacheMaxDiskSize 2147483648

BONUS Reverse Proxy

If you setup a reverse proxy for any of your other public services you can use it too for the z-push and Zimbra proxy server. This way you can setup letsencrypt on the proxy and use your own internal certificate authority for the z-push and proxy servers (the mta should still use a publicly trusted certificate); no worrying about renewing certificates on 3 mail devices every year… and it saves you your very precious public ips.