Skip to content
Webmaster Tools
SecurityPort ScannerPort 3306 (MySQL)

Port 3306 (MySQL and MariaDB)

Port 3306 is the default TCP port of MySQL and MariaDB. How to allow remote access safely, firewall rules, bind-address, and fixing port already in use.

What port 3306 is

TCP port 3306 is the default port of the MySQL and MariaDB servers. Clients such as the mysql command line tool, PHP, WordPress and most ORMs connect there with the MySQL protocol. MySQL 8 also opens 33060 for the X Protocol used by MySQL Shell and the document store.

Traffic on 3306 is unencrypted unless TLS is set up. MySQL 5.7 and later generate a self-signed certificate automatically and modern clients try TLS first, but whether it is required depends on your server and client settings.

Should it be open to the internet?

Almost never. A public 3306 attracts constant password guessing. Most sites run the database on the same host as the application or on a private network, so it only needs to listen on loopback or a private address. For remote administration, use an SSH tunnel:

ssh -L 3306:127.0.0.1:3306 user@db.example.com
mysql -h 127.0.0.1 -P 3306 -u admin -p

bind-address

Which interfaces MySQL listens on is set by bind-address in my.cnf (on Debian and Ubuntu, /etc/mysql/mysql.conf.d/mysqld.cnf or /etc/mysql/mariadb.conf.d/50-server.cnf):

[mysqld]
bind-address = 127.0.0.1

Debian and Ubuntu packages ship with 127.0.0.1; other builds may listen on all interfaces. To allow a second server on a private network, bind to the private address, then create a user limited to that host:

CREATE USER 'app'@'192.0.2.20' IDENTIFIED BY 'a-long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app'@'192.0.2.20';

Avoid 'user'@'%', which allows logins from any address.

Firewall rules

With ufw, allow one application server only:

sudo ufw allow from 192.0.2.20 to any port 3306 proto tcp

With iptables:

sudo iptables -A INPUT -p tcp -s 192.0.2.20 --dport 3306 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP

With Docker, publish the port on loopback (-p 127.0.0.1:3306:3306) or not at all; ports published on all interfaces bypass ufw on most Linux hosts.

How to check what is listening

sudo ss -tlnp | grep ':3306'
sudo lsof -i :3306
mysql -e "SHOW VARIABLES LIKE 'port'; SHOW VARIABLES LIKE 'bind_address';"

A line with 127.0.0.1:3306 means local only; 0.0.0.0:3306 or *:3306 means every interface.

"Port 3306 already in use"

Usually a second MySQL or MariaDB is running: a system service plus a Docker container, or XAMPP alongside a native install. Find it with sudo lsof -i :3306 (on Windows, netstat -ano | findstr :3306), then stop one of them, or move the new one to another port with port = 3307 in its config or -p 3307:3306 in Docker.

Security notes

  • Run mysql_secure_installation on new servers to remove anonymous users and the test database.
  • Require TLS for remote users with ALTER USER ... REQUIRE SSL.
  • Give applications only the privileges they use, never ALL on *.*.
  • Keep the server patched and watch the error log for failed logins.

Check whether 3306 is reachable from the public internet with the Port Scanner.