Load balancing in Zimbra Open-Source Edition using HAProxy

One of the main tasks when building large Zimbra OSE infrastructures is effective load balancing. It not only enhances service reliability but also ensures uniform service responsiveness for all users. To address this, load balancers—both software and hardware solutions—are employed to redistribute requests among servers. Among them are basic solutions like RoundRobin, which simply directs each subsequent request to the next server in the roster, and more advanced options like HAProxy, widely used in high-load computing infrastructures due to several significant advantages. Let’s explore how to ensure the cooperative operation of the HAProxy load balancer and Zimbra OSE.

Load balancing in Zimbra Open-Source Edition using HAProxy

Thus, given the task conditions, we have a Zimbra OSE infrastructure consisting of two Zimbra Proxies, two LDAP servers, an LDAP Replica, four mail storage units with 1,000 mailboxes each, and three MTAs. Considering we are dealing with a mail server, it will receive three types of traffic that require balancing: HTTP for the web client, and POP and SMTP for email transmission. At this point, HTTP traffic will be directed to servers the Zimbra Proxies with IP addresses 192.168.0.57 and 192.168.0.58, while SMTP traffic will go to the MTA servers with IP addresses 192.168.0.77 and 192.168.0.78.

As mentioned earlier, to ensure the even distribution of requests among servers, we will use the HAProxy load balancer, which will operate on the entry node of the Zimbra infrastructure running Ubuntu 18.04. The installation of haproxy on this operating system is performed using the command sudo apt-get install haproxy. After this, it is necessary to change the parameter in the file /etc/default/haproxy to ENABLED=0 to ENABLED=1. Now, to verify that haproxy is running, simply enter the command service haproxy. If this service is running, it will be evident from the command output.

One of the main drawbacks of HAProxy is that by default it does not pass the connecting client's IP address, replacing it with its own. This can lead to situations where emails sent by malicious actors cannot be identified. IP address, to add it to the blacklist. However, this issue can be resolved. To do this, you need to edit the file /opt/zimbra/common/conf/master.cf.in on servers with Postfix and add the following lines:

26      inet  n       -       n       -       1       postscreen
        -o postscreen_upstream_proxy_protocol=haproxy
 
466    inet  n       -       n       -       -       smtpd
%%uncomment SERVICE:opendkim%%  -o content_filter=scan:[%%zimbraLocalBindAddress%%]:10030
        -o smtpd_tls_wrappermode=yes
        -o smtpd_sasl_auth_enable=yes
        -o smtpd_client_restrictions=
        -o smtpd_data_restrictions=
        -o smtpd_helo_restrictions=
        -o smtpd_recipient_restrictions=
        -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
        -o syslog_name=postfix/smtps
        -o milter_macro_daemon_name=ORIGINATING
        -o smtpd_upstream_proxy_protocol=haproxy
%%uncomment LOCAL:postjournal_enabled%% -o smtpd_proxy_filter=[%%zimbraLocalBindAddress%%]:10027
%%uncomment LOCAL:postjournal_enabled%% -o smtpd_proxy_options=speed_adjust
 
588 inet n      -       n       -       -       smtpd
%%uncomment SERVICE:opendkim%%  -o content_filter=scan:[%%zimbraLocalBindAddress%%]:10030
        -o smtpd_etrn_restrictions=reject
        -o smtpd_sasl_auth_enable=%%zimbraMtaSaslAuthEnable%%
        -o smtpd_tls_security_level=%%zimbraMtaTlsSecurityLevel%%
        -o smtpd_client_restrictions=permit_sasl_authenticated,reject
        -o smtpd_data_restrictions=
        -o smtpd_helo_restrictions=
        -o smtpd_recipient_restrictions=
        -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
        -o syslog_name=postfix/submission
        -o milter_macro_daemon_name=ORIGINATING
        -o smtpd_upstream_proxy_protocol=haproxy
%%uncomment LOCAL:postjournal_enabled%% -o smtpd_proxy_filter=[%%zimbraLocalBindAddress%%]:10027
%%uncomment LOCAL:postjournal_enabled%% -o smtpd_proxy_options=speed_adjust

As a result, we will open ports 26, 466, and 588, which will accept incoming traffic from HAProxy. After saving the files, you should restart Postfix on all servers with the command zmmtactl restart.

After that, we will proceed to configure HAProxy. First, we will create a backup of the configuration file cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak. Then we will open the original file in a text editor /etc/haproxy/haproxy.cfg and begin to gradually add the necessary settings. The first block will involve adding a logging server, setting the maximum allowed number of concurrent connections, and specifying the user and group name to which the executing process will belong.

global
    user daemon
    group daemon
    daemon
    log 127.0.0.1 daemon
    maxconn 5000
    chroot /var/lib/haproxy

The figure of 5000 concurrent connections wasn't chosen arbitrarily. Since our infrastructure supports 4000 mailboxes, it's necessary to account for the possibility that all of them might access their work email simultaneously. Additionally, it's important to leave a small buffer in case their number increases.

Now let's add a block with the default settings:

defaults
        timeout client 1m
        log global
        mode tcp
        timeout server 1m
        timeout connect 5s

In this block, we set the maximum wait time for the client and server to close the connection if it times out, as well as set the operating mode for HAProxy. In our case, the load balancer operates in TCP mode, meaning it simply passes TCP packets without analyzing their content.

Next, we will add rules for connections on different ports. For example, if port 25 is used for SMTP connections and email delivery, it makes sense to redirect connections to it to the MTA available in our infrastructure. However, if the connection is on port 80, it is an HTTP request, which needs to be forwarded to Zimbra Proxy.

Rule for port 25:

frontend smtp-25
bind *:27
default_backend backend-smtp-25
 
backend backend-smtp-25
server mta1 192.168.0.77:26 send-proxy
server mta2 192.168.0.78:26 send-proxy

Rule for port 465:

frontend smtp-465
bind *:467
default_backend backend-smtp-465

backend backend-smtp-465
server mta1 192.168.0.77:466 send-proxy
server mta2 192.168.0.78:466 send-proxy

Rule for port 587:

frontend smtp-587
bind *:589
default_backend backend-smtp-587
 
backend backend-smtp-587
server mail1 192.168.0.77:588 send-proxy
server mail2 192.168.0.78:588 send-proxy

Rule for port 80:

frontend http-80
bind    *:80
default_backend http-80
 
backend http-80
mode tcp
server zproxy1 192.168.0.57:80 check
server zproxy2 192.168.0.58:80 check

Rule for port 443:

frontend https
bind  *:443
default_backend https-443
 
backend https-443
mode tcp
server zproxy1 192.168.0.57:80 check
server zproxy2 192.168.0.58:80 check

Please note that in the rules for forwarding TCP packets to the MTA, the parameter next to their addresses is send-proxy. This is necessary so that, in accordance with the earlier changes we made to the Postfix settings, the original IP address of the sender is forwarded along with the TCP packets.

Now that all necessary changes in HAProxy have been made, you can restart the service using the command service haproxy restart and proceed to use it.

The safety alphabet in Kubernetes: authentication, authorization, auditing

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers šŸ”„ Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster