# Ensure Cloud Firewalls Do Not Allow Unrestricted MySQL Access

- Source: https://support.icompaas.com/support/solutions/articles/ensure-cloud-firewalls-do-not-allow-unrestricted-mysql-access
- Section: [Solutions](https://support.icompaas.com/support/solutions) › [DigitalOcean Cloud](https://support.icompaas.com/support/solutions/c_do_cloud) › [DigitalOcean Rules](https://support.icompaas.com/support/solutions/folders/digitalocean-rules)
- Last updated: 2026-08-13
- Publisher: iCompaas, Inc. (https://www.icompaas.com)

## Description

This rule verifies that no DigitalOcean Cloud Firewall permits MySQL (TCP port 3306) from an unrestricted source. Cloud Firewalls are DigitalOcean's equivalent of a security group; an unrestricted source is 0.0.0.0/0 (All IPv4) or ::/0 (All IPv6).

The rule enumerates every firewall's inbound\_rules and flags any rule whose protocol is TCP, whose ports include 3306, and whose sources include 0.0.0.0/0 or ::/0. This applies to self-managed MySQL/MariaDB running on Droplets; DigitalOcean Managed Databases are governed by their own trusted-source settings rather than Cloud Firewalls.

Remediation narrows the source of the port-3306 rule to the specific application server IPs, a resource tag, or the VPC/private network, and removes the unrestricted rule once connectivity through the scoped path is confirmed.

-   Inbound TCP rules on port 3306 with source 0.0.0.0/0
    
-   Inbound TCP rules on port 3306 with source ::/0
    
-   Port-range or 'all' rules encompassing port 3306 from an unrestricted source
    

## Rationale

Exposing a database port directly to the internet bypasses every application-layer control and puts the database engine's own authentication on the front line. Automated scanners routinely sweep for open port 3306 and attempt to log in with default or weak credentials, or exploit known MySQL vulnerabilities. A successful connection can lead to data theft, ransom, or destruction.

Databases should only be reachable from the application tier that needs them. Scoping the inbound rule to specific app-server addresses, a tag, or the private VPC network ensures the database is never directly addressable from the public internet.

-   Direct database exposure sidesteps all application-layer protection
    
-   Open 3306 is a constant target for credential and vulnerability scans
    
-   Private-network / tag scoping keeps the DB reachable only by the app tier
    

## Impact

Pros:

-   Removes the database from public reachability
    
-   Forces access through the application tier or private network
    
-   Reduces exposure to database brute-force and CVE exploitation
    

Cons:

-   Requires knowing the exact app-server IPs, tags, or VPC range
    
-   A missed source can break application-to-database connectivity
    
-   External tooling that connected directly must move behind the allowed path
    

## Default Value

DigitalOcean firewalls suggest only an SSH (port 22) inbound rule on creation and deny all other inbound traffic by default, so any port-3306 exposure was configured deliberately.

## Pre-Requisite

-   Control Panel access with permission to view and edit firewalls
    
-   A DigitalOcean API token or doctl authenticated for API/CLI checks
    
-   Knowledge of the application server IPs, resource tag, or VPC/private network that must reach MySQL
    

## Remediation

### Test Plan

Using the DigitalOcean Control Panel:

1.  Sign in to cloud.digitalocean.com and go to Networking, then Firewalls.
    
2.  Open each firewall and select the Rules tab.
    
3.  Under Inbound Rules, look for a MySQL rule or any Custom TCP rule whose Ports include 3306.
    
4.  Inspect the Sources for that rule and note whether it lists 'All IPv4' and/or 'All IPv6'.
    
5.  Pass: No inbound rule allowing TCP port 3306 has a source of All IPv4 (0.0.0.0/0) or All IPv6 (::/0).
    
6.  Fail: At least one inbound rule allows TCP port 3306 from All IPv4 or All IPv6.
    

Using doctl or the API:

Enumerate firewalls and inspect inbound rules for port 3306 open to an unrestricted source.

doctl compute firewall list --format ID,Name,InboundRules

curl -s -X GET -H "Authorization: Bearer $DIGITALOCEAN\_TOKEN" "https://api.digitalocean.com/v2/firewalls" | jq '.firewalls\[\] | {id, name, offending: \[.inbound\_rules\[\] | select(.protocol=="tcp" and (.ports=="3306" or .ports=="0") and (.sources.addresses // \[\] | any(.=="0.0.0.0/0" or .=="::/0")))\]}'

Pass: the offending array is empty for every firewall. Fail: any firewall returns an inbound TCP rule covering port 3306 with a source of 0.0.0.0/0 or ::/0.

### Implementation Steps

Using the DigitalOcean Control Panel:

1.  In Networking, then Firewalls, open the firewall and select the Rules tab.
    
2.  Click Add inbound rule, choose MySQL (or Custom TCP port 3306), and set Sources to the specific app-server IPs, a resource tag, or the VPC/private network range.
    
3.  Save the rule and confirm the application can still reach the database through the scoped path.
    
4.  Find the original port-3306 rule whose source is All IPv4 / All IPv6, open its … (More) menu, and choose Delete rule.
    
5.  Repeat for every firewall exposing MySQL to an unrestricted source.
    

Using doctl or the API:

Add a scoped port-3306 rule, then remove the unrestricted one.

doctl compute firewall add-rules <firewall-id> --inbound-rules "protocol:tcp,ports:3306,address:10.10.0.0/16"

doctl compute firewall remove-rules <firewall-id> --inbound-rules "protocol:tcp,ports:3306,address:0.0.0.0/0"

curl -s -X POST -H "Authorization: Bearer $DIGITALOCEAN\_TOKEN" -H "Content-Type: application/json" -d '{"inbound\_rules":\[{"protocol":"tcp","ports":"3306","sources":{"addresses":\["10.10.0.0/16"\]}}\]}' "https://api.digitalocean.com/v2/firewalls/<firewall-id>/rules"

curl -s -X DELETE -H "Authorization: Bearer $DIGITALOCEAN\_TOKEN" -H "Content-Type: application/json" -d '{"inbound\_rules":\[{"protocol":"tcp","ports":"3306","sources":{"addresses":\["0.0.0.0/0","::/0"\]}}\]}' "https://api.digitalocean.com/v2/firewalls/<firewall-id>/rules"

### Backout Plan:

1.  If application connectivity breaks, temporarily re-add the prior rule with doctl compute firewall add-rules <firewall-id> --inbound-rules "protocol:tcp,ports:3306,address:0.0.0.0/0" (or the equivalent POST /rules) while you correct the allowed sources.
    
2.  Re-apply the scoped rule and remove the unrestricted rule once the correct app-server sources or VPC range are confirmed.
    

## References:

1.  [DigitalOcean Cloud Firewalls overview](https://docs.digitalocean.com/products/networking/firewalls/)
    
2.  [How to Configure Firewall Rules](https://docs.digitalocean.com/products/networking/firewalls/how-to/configure-rules/)
    
3.  [Firewalls API reference](https://docs.digitalocean.com/reference/api/reference/firewalls/)
    
4.  [doctl compute firewall add-rules](https://docs.digitalocean.com/reference/doctl/reference/compute/firewall/add-rules/)
    
5.  [doctl compute firewall reference](https://docs.digitalocean.com/reference/doctl/reference/compute/firewall/)

## Related compliance guidance

- [SOC 2 compliance: a practical implementation guide for cloud-native SaaS teams](https://support.icompaas.com/compliance/soc-2-trust-services-criteria): Configuration checks like this one are the technical half of a SOC 2 / ISO 27001 programme — the guide shows where they fit, what else an auditor expects, and how to evidence them.
- [ISO/IEC 27001:2022 compliance: a practical implementation guide](https://support.icompaas.com/compliance/iso-27001-2022): ISO 27001 Annex A.8 (technological controls) is where cloud hardening evidence lands; the guide shows how to run the ISMS around it.
