I need to turn on networking for MySQLd, but every time I do, the server gets brute-forced into oblivion. Some mean password guessing script starts hammering on the server, opening a connection on port 3306 and trying random passwords forever.
How can I stop this from happening?
For SSH, I use denyhosts, which works well. Is there a way to make denyhosts work with MySQLd?
I've also considered changing the port MySQL is running on, but this is less than ideal and only a stop-gap solution (what if they discover the new port?)
Does anyone have any other ideas?
If it makes a different, I'm running MySQL 5.x on FreeBSD 6.x.
I don't know of any denyhosts-like software packages for MySQL, but I do have a couple of solutions:
Edit:
To answer your comment, try this:
Where .20 is your MySQL and .50 is the remote connecting IP address.
1: Change the port from 3306. Not for reason of better security, but to take the load of the server to deal with false login attacks
2: Create SSL certificate and enable it on your MySQL server (it's a must-have to encrypt your client-server connection anyway)
3: Create one or more client certificates (all clients need to have the certificate and the client-software need to be configured to use it). If your clients is .Net you need to convert the client certificate to the pkcs12 format, but that's easily done, see this guide..
4: Set the MySQL user account's to require x509 client certificate, then an attacker both need the login credentials AND the client certificate (you can even put a password on the client certificate, then the attacker also need to require that too).
I used this guide to make the certificates and key files but there are many guides out there.
I prefer only to use my SSH connection to access my linux box for administration purpose, not for client access.
Using MySQL Proxy, you could write a small LUA script that takes a user/pass combination but waits X seconds to process the login if the connection request comes from an unapproved IP range.
You could furthermore add a bit of extra logic to the LUA script to blacklist IP ranges after three failed attempts.
All in all, it's technically doable, but I'm going with the other recommendations to tunnel via SSH or a VPN to a common, whitelisted (via FW or other means) IP range.
why not allowing acces to the mysqld port from only secure hosts ?
While this is not a "real" answer - I do not know why you need to expose it to the outside world directly.
Can't you enable ssh on that box, and use tunneling to access the db engine?
Or any other VPN solution to access it (openvpn comes to mind).
Not a real solution to the problem, but it might help if you just run the server on a different port. Most of those scanning bots are probably programmed to just check 3306. It won't solve the issue, but you'll probably get a lot fewer scans by just changing the port.
I believe connections should be firewalled: fast and nice. There's plenty of tutorials for iptables and whatever :)
Also you can install a cronjob on clients' hosts that will run smth on a server to prevent firewall from blocking known hosts.
using ssh for tunnels would be the best but you could try to use fail2ban instead of denyhosts because i think it's aimed towards monitoring more different appications so it shouldn't be a problem adding the mysql log to it.
Suggestion to consider for your my.cnf-ini [mysqld] section
to avoid the hundreds of attempts in 90 seconds. Chop them off at 10 attempts.
Consider once a day FLUSH HOSTS to clear the legitimate people trying to use your system that just CAN NOT remember their password. Maybe in a few days, they will get with it.