TL;DR - An open MySQL port 3306 on the public internet is discovered by automated scanners within 5-15 minutes of going online. Shodan indexes over 3.6 million exposed MySQL instances at any given time. - Attackers run brute-force credential attacks, exploit known MySQL vulnerabilities, and use exposed instances as pivot points to access other systems on the same network. - You can check your own exposure with nmap, Shodan, or Censys in under a minute. - Safer alternatives: bind MySQL to localhost, use firewall rules to restrict by IP, connect through an SSH tunnel, or route access through a static IP gateway that you whitelist. - There is no legitimate reason to expose port 3306 to 0.0.0.0 in production. None.
Table of Contents
- Why You Should Never Expose Port 3306 to the Internet
- What Happens When You Expose Port 3306
- The Shodan Problem: Your Database Is Already Indexed
- Real Attacks Against Exposed MySQL Instances
- How to Check If Your Port 3306 Is Exposed
- Why Developers Expose It Anyway
- Alternative 1: Bind to Localhost
- Alternative 2: Firewall Rules and IP Whitelisting
- Alternative 3: SSH Tunnels
- Alternative 4: Static IP Gateway
- A Decision Framework
- FAQ
- Conclusion
Why You Should Never Expose Port 3306 to the Internet
MySQL's default port — 3306 — is one of the most frequently scanned ports on the internet. The moment you bind MySQL to 0.0.0.0 on a server with a public IP, automated bots begin probing it. Not in hours. Not after someone targets you specifically. Within minutes.
This is not hyperbole. It is measurable, repeatable, and well-documented. The decision to expose port 3306 to the public internet is one of the most common and most dangerous misconfigurations in database administration, and it happens every day — usually by developers who need remote access and take the fastest path to getting it working.
This article covers exactly what happens when you expose MySQL to the internet, how to check whether you already have, and the alternatives that give you remote access without the risk.
What Happens When You Expose Port 3306
When MySQL is bound to 0.0.0.0 (all interfaces) on a server with a public IP, and no firewall rule blocks inbound connections on port 3306, the following sequence begins immediately:
Minutes 1-15: Discovery. Automated scanners operated by security researchers (Shodan, Censys, Shadowserver) and malicious botnets sweep the internet continuously. These scanners probe common service ports across the entire IPv4 address space — roughly 3.7 billion routable addresses. Tools like Masscan can scan every IP on a single port in under 6 minutes. Your new MySQL instance will appear in scanning results before you finish configuring the application that uses it.
Minutes 15-60: Fingerprinting. Once a scanner identifies an open port 3306, it performs a MySQL protocol handshake to confirm the service. The initial handshake packet from MySQL includes the server version string (e.g., 5.7.42 or 8.0.35), which tells the attacker exactly which vulnerabilities apply. No authentication is needed to receive this information — MySQL sends it automatically as part of the connection protocol.
Hours 1-24: Brute-force attacks begin. Botnets start trying common credential combinations: root with an empty password, root/root, admin/admin, mysql/mysql, and dictionaries of common passwords. A 2023 analysis by CrowdSec found that exposed MySQL instances received an average of 4,800 brute-force login attempts in the first 24 hours. Some instances received over 14,000 attempts.
Days 1-7: Exploitation attempts. If the MySQL version exposed during fingerprinting has known vulnerabilities, automated exploit scripts target them specifically. If brute-force succeeds, the attacker begins data exfiltration, installs backdoor users, or uses the MySQL instance to pivot deeper into the network.
Ongoing: Persistent scanning. Once an IP is identified as running MySQL, it is added to target lists that are shared and sold among botnet operators. Even if you close the port later, your IP will continue to receive probe attempts for months.
The Shodan Problem: Your Database Is Already Indexed
Shodan is a search engine for internet-connected devices. It continuously scans the IPv4 address space and indexes the services it finds. A Shodan search for product:MySQL returns over 3.6 million results as of early 2026.
Each result includes: - The server's IP address - The MySQL version string - The geographic location - The hosting provider - Whether the instance requires authentication or allows anonymous connections
Anyone — security researchers, penetration testers, and attackers — can run this search for free. Censys provides the same capability, as does FOFA and ZoomEye. The information is public and updated continuously.
The implication is straightforward: if your MySQL port is open to the internet, its existence is already documented in multiple public databases. Security through obscurity — "nobody knows my server's IP" — does not work when the entire internet is indexed.
Real Attacks Against Exposed MySQL Instances
Exposed MySQL ports are not just a theoretical risk. They are actively exploited in documented campaigns:
GhostShell / Nansh0u campaign (2019-2020). This attack campaign targeted exposed MySQL and MS SQL servers, brute-forcing credentials and deploying cryptomining malware and rootkits. Guardicore Labs documented that the campaign compromised over 50,000 servers worldwide. The initial vector in every case was an exposed database port with weak credentials.
MySQL ransomware attacks (2017-present). Multiple campaigns have targeted exposed MySQL instances, connected with brute-forced credentials, exported all databases, dropped the originals, and left a ransom note in a table called WARNING or PLEASE_READ. Researchers at Secureworks documented waves of these attacks, with ransom demands typically between 0.2-0.5 BTC.
CVE-2012-2122 — Authentication bypass. One of the most infamous MySQL vulnerabilities: due to a casting error in the password comparison, MySQL on certain platforms (notably some Linux distributions compiled with certain GCC optimizations) would accept an incorrect password roughly once in every 256 attempts. A simple bash loop could authenticate as root in under a second on vulnerable versions. The fix was a one-line patch, but unpatched instances were exploited for years. An exposed port was the prerequisite.
CVE-2024-21096 — mysqldump client vulnerability. A more recent example: this vulnerability in the mysqldump utility could lead to code execution when processing a maliciously crafted database. While exploitation required a compromised MySQL server, exposed instances are the most likely vector for initial server compromise.
UDF (User-Defined Function) privilege escalation. Attackers who gain MySQL access with FILE privilege can write a shared library to disk and load it as a UDF, achieving operating system-level code execution. This is the standard post-exploitation path on compromised MySQL instances and is automated in tools like Metasploit's mysql_udf_payload module.
In each of these cases, the attack chain starts the same way: MySQL is reachable from the internet.
How to Check If Your Port 3306 Is Exposed
You can determine your exposure in under a minute.
From the command line (nmap)
# Scan your server's public IP for port 3306
nmap -p 3306 your-server-ip
# If it shows "open", your MySQL is reachable from the internet
# If it shows "filtered" or "closed", the port is blocked
Run this from a machine outside your server's network — from your laptop, a different server, or a mobile hotspot. Scanning from the server itself will not show you what the internet sees.
From Shodan
Go to shodan.io and search for your server's IP address. If MySQL appears in the results, it is indexed and publicly visible. Shodan also shows the MySQL version string, which tells you (and any attacker) which vulnerabilities apply.
From Censys
search.censys.io provides the same capability. Search for your IP and check whether port 3306 appears in the services list.
Check your MySQL bind address
On the server itself:
# Check what address MySQL is bound to
mysql -e "SHOW VARIABLES LIKE 'bind_address';"
# If it shows 0.0.0.0 or *, MySQL is listening on all interfaces
# If it shows 127.0.0.1 or localhost, it is only listening locally
If bind_address is 0.0.0.0 and no firewall rule blocks port 3306, your database is exposed.
Why Developers Expose It Anyway
Knowing that exposing port 3306 is dangerous does not stop it from happening. The reasons are practical:
Remote development. A developer needs to connect MySQL Workbench, DBeaver, or phpMyAdmin from their laptop to a database on a cloud server. The fastest way is to open the port. The secure way requires additional setup.
Quick debugging. A production issue requires immediate database access. The developer opens port 3306 "just for a few minutes" and forgets to close it. Three months later, it is still open.
Configuration defaults. Some Docker MySQL images and cloud server templates ship with bind-address = 0.0.0.0 by default, and the developer does not change it because the application works.
Misunderstanding of risk. "My database has a strong password, so it is fine." This ignores version fingerprinting, zero-day exploits, and the sheer volume of brute-force attempts that will test that password.
Each of these scenarios has the same root cause: the developer needs remote access and the obvious path is to open the port. The solution is to make the secure path equally obvious and nearly as fast.
Alternative 1: Bind to Localhost
The simplest mitigation: tell MySQL to only listen on the loopback interface.
In my.cnf (or mysqld.cnf):
[mysqld]
bind-address = 127.0.0.1
After restarting MySQL, port 3306 is only accessible from the server itself. No amount of internet scanning will find it because the server does not respond to external connection attempts on that port.
The limitation is obvious: you can only access MySQL from the server. For applications running on the same machine, this is fine. For remote access, you need one of the following alternatives.
Alternative 2: Firewall Rules and IP Whitelisting
If MySQL needs to accept connections from specific remote hosts (e.g., an application server on a different machine), use firewall rules to restrict access to those IPs only.
Using UFW (Ubuntu):
# Deny all inbound on 3306 by default
sudo ufw deny 3306
# Allow only your application server's IP
sudo ufw allow from 10.0.1.5 to any port 3306
# Allow your static IP for administration
sudo ufw allow from 203.0.113.50 to any port 3306
Using iptables:
# Drop all inbound on 3306
iptables -A INPUT -p tcp --dport 3306 -j DROP
# Allow specific IPs (insert before the DROP rule)
iptables -I INPUT -p tcp -s 10.0.1.5 --dport 3306 -j ACCEPT
iptables -I INPUT -p tcp -s 203.0.113.50 --dport 3306 -j ACCEPT
Using cloud provider firewalls (recommended over OS-level firewalls for cloud servers):
- DigitalOcean: Cloud Firewalls in the control panel
- AWS: Security Groups attached to the RDS or EC2 instance
- GCP: VPC Firewall Rules
Cloud firewalls are applied at the network edge, before traffic reaches your server. This means port scans do not even generate connection attempts on your server — they are dropped upstream.
For more on IP whitelisting strategies, see our guide to database IP whitelisting.
Alternative 3: SSH Tunnels
An SSH tunnel creates an encrypted channel between your local machine and the remote server, forwarding the MySQL port through that channel.
# Create an SSH tunnel: local port 3307 -> remote localhost:3306
ssh -L 3307:127.0.0.1:3306 user@your-server-ip -N
# Now connect your MySQL client to localhost:3307
mysql -h 127.0.0.1 -P 3307 -u dbuser -p
The advantages:
- MySQL stays bound to 127.0.0.1 — no internet exposure
- The connection is encrypted through the SSH tunnel
- Access is authenticated via SSH keys (stronger than passwords)
- No firewall rule changes needed
The disadvantages: - Requires SSH access to the server (not available with managed databases like RDS) - Each developer needs SSH key management - The tunnel must be started before each session and breaks if the SSH connection drops - Not practical for non-technical team members who need database access
For a detailed walkthrough, see our guide on SSH tunnels for database access.
Alternative 4: Static IP Gateway
A static IP gateway provides remote database access through a browser without exposing any ports on your database server.
The model works like this:
- You whitelist a single IP address (the gateway's IP) in your database firewall.
- You access the database through a web-based tool (phpMyAdmin, Adminer) hosted on the gateway.
- The gateway connects to your database from its static IP and proxies the session to your browser.
- When you are done, the session terminates. There is no persistent connection.
DBEverywhere operates this way. You add one IP to your database's allowed connections list, and access is available from any browser on any network. Your database port is never exposed to the internet — it only accepts connections from the whitelisted gateway IP.
The advantages: - No port exposure — MySQL stays bound to localhost or restricted by firewall - No SSH keys or VPN software to manage - Works with managed databases (RDS, DigitalOcean, PlanetScale) that do not offer SSH access - Non-technical team members can access the database through a browser - Session-based access with automatic timeouts (20 minutes on free, 8 hours on paid)
The disadvantage is that you are routing database access through a third-party service. For teams that need maximum control, SSH tunnels or a self-managed VPN are more appropriate. For teams that want simplicity and zero infrastructure, the gateway model is the path of least resistance.
A Decision Framework
| Scenario | Best Alternative |
|---|---|
| Application and database on the same server | Bind to localhost |
| Application and database on separate servers in the same network | Firewall rules (allow private IP only) |
| Developer needs occasional remote access, has SSH access | SSH tunnel |
| Team needs remote access to a managed database (RDS, DO, etc.) | Static IP gateway or cloud provider firewall + whitelisted IP |
| Non-technical team member needs to view data | Static IP gateway with browser-based UI |
| "I just need to check something real quick" | SSH tunnel or static IP gateway — not opening port 3306 |
In every scenario, the answer is the same: do not expose port 3306. The only variable is which alternative fits your access pattern.
FAQ
Is it safe to expose port 3306 if I have a strong password?
No. A strong password protects against brute-force attacks but not against version-specific exploits (like CVE-2012-2122's authentication bypass), zero-day vulnerabilities, or denial-of-service attacks. Additionally, the MySQL version string is sent to any connecting client before authentication, giving attackers the information they need to select targeted exploits. A strong password is a necessary condition for security but not a sufficient one. The port should not be publicly reachable in the first place.
What about port 5432 (PostgreSQL) or 27017 (MongoDB)?
The same principle applies to every database port. PostgreSQL on 5432, MongoDB on 27017, Redis on 6379, and Elasticsearch on 9200 are all actively scanned and exploited. MongoDB in particular has been the target of massive ransom campaigns — in 2017 alone, over 28,000 exposed MongoDB instances were wiped and ransomed. The advice in this article applies to all database ports, not just MySQL's 3306.
How quickly will attackers find my exposed MySQL port?
Based on honeypot research by SANS Internet Storm Center and independent security researchers, a newly exposed MySQL port on a public IP typically receives its first connection attempt within 5-15 minutes. Shodan indexes new services within 24-48 hours. After that, the scanning is continuous and comes from multiple botnets simultaneously. The speed of discovery is one of the strongest arguments against "temporary" port exposure — there is no safe window.
My hosting provider's tutorial says to allow remote MySQL connections. Is that wrong?
Many hosting tutorials prioritize getting things working over getting things secure. The tutorial is technically correct — changing bind-address to 0.0.0.0 and allowing port 3306 through the firewall does enable remote connections. But it enables them from the entire internet, not just from your machine. A responsible tutorial would include firewall rules to restrict access to specific IPs. If yours did not, add those rules immediately.
Can I just change the port to something other than 3306?
Changing the port (security through obscurity) adds a trivial speed bump. Automated scanners like Masscan scan all 65,535 ports, not just well-known ones. A full-port scan of your server takes seconds. Shodan indexes non-standard ports just as readily as standard ones. Changing the port might reduce the volume of automated brute-force attempts slightly, but it does not meaningfully reduce your risk. Use a proper firewall instead.
Conclusion
There is no production scenario where exposing port 3306 to 0.0.0.0 on the public internet is the right choice. The risk is immediate and well-documented: automated discovery within minutes, brute-force attacks within hours, and potential exploitation within days.
The alternatives are proven and practical. Bind to localhost if your application is co-located. Use firewall rules to whitelist specific IPs if you need inter-server communication. Set up an SSH tunnel if you need occasional remote access from your machine. Use a static IP gateway like DBEverywhere if your team needs browser-based access from anywhere without managing tunnels or VPN clients.
If you are reading this and your MySQL port is currently exposed, fix it now. Check with nmap -p 3306 your-server-ip from an external machine. If it says "open," you are on every botnet's target list. Change bind-address to 127.0.0.1, add firewall rules, and restart MySQL. It takes less than five minutes and eliminates an attack surface that has been responsible for hundreds of thousands of database compromises.
Then set up a proper remote access method so you never need to open that port again.
Try DBEverywhere Free
Access your database from any browser. No installation, no Docker, no SSH tunnels.
Get Started