Ubuntu Server 18.04 – MariaDB best practices for secure database servers

How to check for updates on Windows Server 2019

MariaDB, as well as MySQL, is a very useful resource to have at your disposal. However, it can also be used against you if configured improperly. Thankfully, it’s not too hard to secure, but there are several points of consideration to make regarding your database server when developing your security design.

The first point is probably obvious to most of you, and I have mentioned it before, but I’ll mention it just in case. Your database server should not be reachable from the internet. I do understand that there are some edge cases when developing a network, and certain applications may require access to a MySQL database over the internet. However, if your database server is accessible over the internet, miscreants will try their best to attack it and gain entry. If there’s any vulnerability in your version of MariaDB or MySQL, they’ll most likely be able to hack into it.

In most organizations, a great way to implement a database server is to make it accessible by only internal servers. This means that while your web server would obviously be accessible from the internet, its backend database should exist on a different server on your internal network and accept communications only from the web server. If your database server is a VPS, it should especially be configured to only accept communications from your web server, as VPS machines are accessible via the internet by default. Therefore, it’s still possible for your database server to be breached if your web server is also breached, but it would be less likely to be compromised if it resides on a separate and restricted server.

Some VPS providers, such as DigitalOcean, feature local networking, which you can leverage for your database server instead of allowing it to be accessible over the internet. If your VPS provider features local networking, you should definitely utilize it and deny traffic from outside the local network.

With regards to limiting which servers are able to access a database server, there are a few tweaks we can use to accomplish this. First, we can leverage the /etc/hosts.allow and /etc/hosts.deny files. With the /etc/hosts.deny file, we can stop traffic from certain networks or from specific services. With /etc/hosts.allow, we do the same but we allow the traffic. This works because IP addresses included in /etc/hosts.allow override /etc/hosts.deny. So basically, if you deny everything in /etc/hosts.deny and allow a resource or two in /etc/hosts.allow, you’re saying, deny everything, except resources I explicitly allow from the /etc/hosts.deny file.

To make this change, we’ll want to edit the /etc/hosts.allow file first. By default, this file has no configuration other than some helpful comments. Within the file, we can include a list of resources we’d like to be able to access our server, no matter what. Make sure that you include your web server here, and also make sure that you immediately add the IP address you’ll be using to SSH into the machine, otherwise you’ll lock yourself out once we edit the /etc/hosts.deny file. Here are some example hosts.allow entries, with a description of what each example rule does:


This rule allows a machine with an IP address of to access the server:


This rule allows any machine within the network to access the server:

ALL: 192.168.1.

In this rule, we have an incomplete IP address. This acts as a wildcard, which means that any IP address beginning with 192.168.1 is allowed:


This rule allows everything. You definitely don’t want to do this:

ssh: 192.168.1.

We can also allow specific daemons. Here, I’m allowing OpenSSH traffic originating from any IP address beginning with 192.168.1.

On your end, if you wish to utilize this security approach, add the resources on your database server you’ll be comfortable accepting communications from. Make sure you at least add the IP address of another server with access to OpenSSH, so you’ll have a way to manage the machine. You can also add all your internal IP addresses with a rule similar to the previous examples. Once you have this setup, we can edit the /etc/hosts.deny file.

The /etc/hosts.deny file utilizes the same syntax as /etc/hosts.allow. To finish this little exercise, we can block any traffic not included in the /etc/hosts.allow file with the following rule:


The /etc/hosts.allow and /etc/hosts.deny files don’t represent a complete layer of security, but are a great first step in securing a database server, especially one that might contain sensitive user or financial information. They’re by no means specific to MySQL either, but I mention them here because databases very often contain data that if leaked, could potentially wreak havoc on your organization and even put someone out of business. A database server should only ever be accessible by the application that needs to utilize it.

Another point of consideration is user security. We walked through creating database users in Chapter 9, Managing Databases. In that chapter, we walked through the MySQL commands for creating a user as well as GRANT, performing both in one single command. This is the example I used:

GRANT SELECT ON mysampledb.* TO 'appuser'@'localhost' IDENTIFIED BY 'password';

What’s important here is that we’re allowing access to the mysampledb database by a user named appuser. If you look closer at the command, we’re also specifying that this connection is allowed only if it’s coming in from localhost. If we tried to access this database remotely, it wouldn’t be allowed. This is a great default. But you’ll also, at some point, need to access the database from a different server. Perhaps your web server and database server are separate machines, which is a common enterprise. You could do this:

GRANT SELECT ON mysampledb.* TO 'appuser'@'%' IDENTIFIED BY 'password';

However, in my opinion, this is a very bad practice. The % character in a MySQL GRANT command is a wildcard, similar to * with other commands. Here, we’re basically telling our MariaDB or MySQL instance to accept connections from this user, from any network. There is almost never a good reason to do this. I’ve heard some administrators use the argument that they don’t allow external traffic from their company firewall, so allowing MySQL traffic from any machine shouldn’t be a problem. However, that logic breaks down when you consider that if an attacker does gain access to any machine in your network, they can immediately target your database server. If an internal employee gets angry at management and wants to destroy the database, they’ll be able to access it from their workstation. If an employee’s workstation becomes affected by malware that targets database servers, it may find your database server and try to brute-force it. I could go on and on with examples of why allowing access to your database server from any machine is a bad idea. Just don’t do it!

If we want to give access to a specific IP address, we can do so with the following instead:

GRANT SELECT ON mysampledb.* TO 'appuser'@'' IDENTIFIED BY 'password';

With the previous example, only a server or workstation with an IP address of is allowed to use the appuser account to obtain access to the database. That’s much better. You can, of course, allow an entire subnet as well:

GRANT SELECT ON mysampledb.* TO 'appuser'@'192.168.1.% IDENTIFIED BY 'password';

Here, any IP address beginning with 192.168.1 is allowed. Honestly, I really don’t like allowing an entire subnet. But depending on your network design, you may have a dozen or so machines that need access. Hopefully, the subnet you allow is not the same subnet your users’ workstations use!

Finally, another point of consideration is security patches for your database server software. I know I talk about updates quite a bit, but as I’ve mentioned, these updates exist for a reason. Developers don’t release patches for enterprise software simply because they’re bored, these updates often patch real problems that real people are taking advantage of right now as you read this. Install updates regularly. I understand that updates on server applications can scare some people, as an update always comes with the risk that it may disrupt business. But as an administrator, it’s up to you to create a roll-out plan for security patches, and ensure they’re installed in a timely fashion. Sure, it’s tough and often has to be done after-hours. But the last thing I want to do is read about yet another company where the contents of their database server were leaked and posted on Pastebin (https://pastebin.com/). A good security design includes regular patching.

Comments are closed.