In my previous article, I showed you how to configure high availability clustering for MySQL or MariaDB.  But what if you are working in a secure environment where you need to have all ports locked down except those required for functionality?  There are a variety of ports that will need to be open depending on required functionality.  But they do not have to be open to the world.  This article is working under the assumption that the firewall is enabled and already configured to restrict access as needed for your environment.

The most obvious port to be opened for any SQL server is TCP port 3306 to other servers that need to access the database.  Another obvious choice is protected access on TCP port 22 if you are using a terminal session to remotely manage the server.  If you are using the HA configuration with Pacemaker and Corosync, there are six other ports that need to be open between the nodes of the cluster.  They do not need to be open to any other servers or services.

RedHat recommends a simple two command approach to opening ports required for high availability.  I argue that these are not restrictive enough for secure environments.  The commands are:

firewall-cmd --permanent --add-service=high-availability
firewall-cmd --add-service=high-availability

(Source: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/high_availability_add-on_reference/s1-firewalls-haar)

My issue with this approach is that it opens those ports to the world.  Granted, you most likely have a separate firewall protecting your network perimeter, so this is not a problem with users outside of your network.  Let's assume you have a bad actor within your network.  It could be a disgruntled employee, or it could be a system that has been compromised by an external threat.  Since these commands open those ports to any device on your network and not just the cluster nodes, this system is now at risk on those ports.  How big of a risk depends on future vulnerabilities yet to be detected in the service software.  Why take the risk?

There are very specific ports that are required for communication within the cluster itself.  They are:

  • TCP ports: 2224, 3121, and 21064
  • UDP ports: 5404, 5405, and 5406

To limit our exposure, we only want to open these ports between the specific server nodes in the cluster so that the servers can communicate over those ports only with each other.

The default firewall tool in Ubuntu is Uncomplicated Fire Wall (UFW).  Since the guide uses Ubuntu as the base server for our configuration, I am only addressing that configuration here.  This information should easily translate to firewalld or any other firewall software you may be using.

As a recap of the previous article, we have a MariaDB server running on the following IPs to provide a database backed for any services that rely on data storage.  We are not concerned with the VIP of the cluster for this level of inter-server communication.

  • 192.168.50.231
  • 192.168.50.232
  • 192.168.50.233

The same configuration can be used on each of the servers.  These must be added using an account with sudo privileges.  Since there are three IPs and six ports, there are a total of eighteen commands to hit every combination of port and IP.  You can shorten this by using a slash notation for the IP range, but there is a risk of other IPs in that range coming online and being able to access the services.  Because my motto is "perfect paranoia is perfect awareness," I prefer to err on the side of caution and specify every possible rule.  But you do you.

sudo ufw allow from 192.168.50.231 proto tcp to any port 2224

sudo ufw allow from 192.168.50.232 proto tcp to any port 2224

sudo ufw allow from 192.168.50.233 proto tcp to any port 2224

sudo ufw allow from 192.168.50.231 proto tcp to any port 3121

sudo ufw allow from 192.168.50.232 proto tcp to any port 3121

sudo ufw allow from 192.168.50.233 proto tcp to any port 3121

sudo ufw allow from 192.168.50.231 proto tcp to any port 21064

sudo ufw allow from 192.168.50.232 proto tcp to any port 21064

sudo ufw allow from 192.168.50.233 proto tcp to any port 21062

sudo ufw allow from 192.168.50.231 proto udp to any port 5404

sudo ufw allow from 192.168.50.232 proto udp to any port 5404

sudo ufw allow from 192.168.50.233 proto udp to any port 5404

sudo ufw allow from 192.168.50.231 proto udp to any port 5405

sudo ufw allow from 192.168.50.232 proto udp to any port 5405

sudo ufw allow from 192.168.50.233 proto udp to any port 5405

sudo ufw allow from 192.168.50.231 proto udp to any port 5406

sudo ufw allow from 192.168.50.232 proto udp to any port 5406

sudo ufw allow from 192.168.50.233 proto udp to any port 5406

By running the above commands, you now have enabled these ports through the software firewall native to each server.  You can verify the existing rules by running ufw show added.

Of course, there are other ways to modify configuration files to store your rules, but the above commands will write these for you.  If modifying configuration files, you will want to do a ufw reload to ensure the new rules are loaded.  And don't forget to enable the firewall by entering ufw enable , but only after you are sure you have enabled whatever port you are using to manage your server be it SSH, NoVNC, or some other service.  Google is your friend here.  Once the firewall is enabled, you can use ufw status to show the list of current rules.

Don't forget to check the status of your cluster after making any changes.  To do this, just run pcs status to display the current status of the cluster.  You should see results like the following.

Cluster name: mysql-ha
Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: u24-mysql03 (version 2.1.6-6fdc9deea29) - partition with quorum
  * Last updated: Wed Oct 9 00:53:56 2024 on u24-mysql01
  * Last change: Tue Oct 8 12:37:50 2024 by root via cibadmin on u24-mysql01
  * 3 nodes configured
  * 1 resource instance configured

Node List:
  * Online: [ u24-mysql01 u24-mysql02 u24-mysql03 ]

Full List of Resources:
  * Resource Group: mysql_ha_cluster:
    * virtual_ip (ocf:heartbeat:IPaddr2): Started u24-mysql01

Daemon Status:
  corosync: active/enabled
  pacemaker: active/enabled
  pcsd: active/enabled

As you can see from the above example output, all three nodes are showing online, the VIP resource is started, and the daemons are all active/enabled.

The above information should give you a decent head start to figuring out how to apply additional rules to allow web servers access to SQL services on TCP port 3306 on these servers. It should also provide guidance on configuring your web servers for access on TCP ports 80 and 443  if required. 

Remember to only open ports that are required for the role of the server that is being modified.  If you are not running web services, don't allow web service ports.