Proteja seu banco MySQL, MariaDB ou PostgreSQL: feche as portas 3306 e 5432, crie usuários com privilégio mínimo e exija TLS nas conexões.

Para que serve

Bancos expostos na internet estão entre os alvos mais varridos por robôs: em minutos aparecem tentativas de senha em portas 3306, 5432 e 1433, e bancos invadidos são apagados e trocados por um pedido de resgate. A segurança de banco de dados começa por três medidas simples: não expor a porta, dar a cada aplicação só o acesso que ela precisa e criptografar o tráfego. Este artigo mostra cada uma no MySQL/MariaDB e no PostgreSQL, com notas para o SQL Server.

Pré-requisitos

  • Acesso root ao servidor/VM do banco e ao console IPMI/iLO (caso alguma regra de firewall bloqueie seu acesso).
  • Lista de quais servidores precisam falar com o banco (aplicação, réplica, backup).
  • Backup recente antes de alterar usuários e permissões.

1. Segurança de banco de dados começa pela porta: veja o que está exposto

ss -tlnp | grep -E '3306|5432|1433|33060|6432|6033'

Se aparecer 0.0.0.0:3306, *:5432 ou [::]:..., o banco aceita conexões em todos os IPs, inclusive os públicos. Confirme de fora, a partir de outra máquina:

nmap -Pn -p 3306,5432,1433 SEU_IP_PUBLICO

O resultado esperado é filtered ou closed.

2. Faça o banco escutar só onde precisa

MySQL/MariaDB (mysqld.cnf ou 50-server.cnf, seção [mysqld]):

bind-address = 127.0.0.1          # só local
# ou o IP privado, se a aplicação estiver em outra VM:
# bind-address = 10.0.0.11
mysqlx = OFF                      # MySQL 8: desliga o X Protocol (porta 33060) se não usar

PostgreSQL (/etc/postgresql/17/main/postgresql.conf ou um arquivo em conf.d):

listen_addresses = 'localhost'                 # ou 'localhost,10.0.0.21'

Reinicie o serviço e repita o ss -tlnp. Depois, adicione uma camada de firewall permitindo a porta só para os IPs conhecidos, no UFW, no firewall do Proxmox ou no pfSense/OPNsense. Veja UFW no Ubuntu e Debian e Firewall do Proxmox VE.

Atenção: ao ativar firewall, libere antes a sua porta SSH. Se perder o acesso, entre pelo console IPMI/iLO e desative a regra (ufw disable ou pve-firewall stop).

Acesso administrativo remoto (DBeaver, pgAdmin, Workbench) deve passar por VPN (veja servidor WireGuard na categoria VPN) ou por túnel SSH, sem abrir a porta:

ssh -L 15432:127.0.0.1:5432 usuario@servidor
# no cliente gráfico, conecte em 127.0.0.1:15432

3. Crie usuários com privilégio mínimo

MySQL e MariaDB

Comece pelo script de endurecimento (remove usuários anônimos, banco de teste e root remoto):

mysql_secure_installation        # MySQL
mariadb-secure-installation      # MariaDB

Crie um usuário por aplicação, preso ao IP de origem e ao seu banco:

CREATE USER 'loja'@'10.0.0.30' IDENTIFIED BY 'SenhaLongaEAleatoria';
GRANT SELECT, INSERT, UPDATE, DELETE ON loja.* TO 'loja'@'10.0.0.30';
-- para a ferramenta de migração, um usuário separado com DDL:
CREATE USER 'loja_migra'@'10.0.0.30' IDENTIFIED BY '...';
GRANT ALL PRIVILEGES ON loja.* TO 'loja_migra'@'10.0.0.30';

Evite '%' como host e nunca dê GRANT ALL ON *.* a aplicações. Revise quem existe:

SELECT user, host, plugin FROM mysql.user ORDER BY user;
SHOW GRANTS FOR 'loja'@'10.0.0.30';

PostgreSQL

CREATE ROLE loja_owner LOGIN PASSWORD 'OutraSenhaLonga';
CREATE ROLE loja LOGIN PASSWORD 'SenhaLongaEAleatoria';
CREATE DATABASE loja OWNER loja_owner;   -- dono separado, usado só em migrações
REVOKE ALL ON DATABASE loja FROM PUBLIC;
GRANT CONNECT ON DATABASE loja TO loja;
\c loja
GRANT USAGE ON SCHEMA public TO loja;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO loja;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO loja;
ALTER DEFAULT PRIVILEGES FOR ROLE loja_owner IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO loja;

O papel loja_owner é dono das tabelas e só é usado pelas migrações; a aplicação conecta como loja. Desde o PostgreSQL 15, usuários comuns já não podem criar objetos no schema public por padrão.

No pg_hba.conf, libere cada usuário só para seu banco e IP, com SCRAM e TLS. Nunca use trust em linhas de rede:

# TYPE   DATABASE  USER  ADDRESS        METHOD
hostssl  loja      loja  10.0.0.30/32   scram-sha-256

Confira se as senhas usam SCRAM (SHOW password_encryption; deve retornar scram-sha-256, padrão desde a versão 14). Senhas MD5 antigas devem ser redefinidas; o PostgreSQL 18 já avisa que o MD5 será removido.

4. Exija TLS nas conexões

MySQL 8 gera certificados próprios na inicialização e já aceita TLS. Para obrigar:

SET PERSIST require_secure_transport = ON;   -- todas as conexões TCP
-- ou por usuário:
ALTER USER 'loja'@'10.0.0.30' REQUIRE SSL;

MariaDB 11.4 ou mais novo também habilita TLS automaticamente; em versões anteriores, configure ssl_cert, ssl_key e ssl_ca e use REQUIRE SSL nos usuários.

PostgreSQL no Debian/Ubuntu já vem com ssl = on e certificado autoassinado. Use linhas hostssl no pg_hba.conf (como acima) para recusar conexões sem criptografia. Para validar a identidade do servidor no cliente (sslmode=verify-full), substitua por um certificado emitido por uma CA sua ou pública.

5. Notas para SQL Server

  • Não exponha a porta 1433 na internet; libere no Firewall do Windows só os IPs da aplicação ou use VPN.
  • Prefira autenticação Windows ou, se usar logins SQL, desative o sa (ALTER LOGIN sa DISABLE;) depois de criar outro administrador.
  • Dê às aplicações papéis como db_datareader/db_datawriter no banco delas, e não sysadmin.

Como saber se funcionou

  • nmap de fora mostra as portas do banco como filtered/closed.
  • MySQL: na sessão da aplicação, SHOW SESSION STATUS LIKE 'Ssl_cipher'; retorna um cipher (não vazio).
  • PostgreSQL: SELECT usename, client_addr, ssl FROM pg_stat_ssl JOIN pg_stat_activity USING (pid); mostra ssl = t nas conexões remotas.
  • Tentar conectar com o usuário da aplicação a outro banco é recusado.

Problemas comuns

A aplicação parou de conectar depois do bind-address

Ela estava em outra máquina. Use o IP privado no bind-address/listen_addresses e crie o usuário com esse host de origem.

"no pg_hba.conf entry for host ... no encryption"

O cliente tentou sem TLS e a linha exige hostssl. Ajuste o cliente para sslmode=require ou superior.

Driver antigo não conecta ao MySQL 8.4

O MySQL 8.4 desativa por padrão o plugin mysql_native_password. Atualize o driver para um que suporte caching_sha2_password, em vez de reativar o plugin antigo.

Perguntas frequentes

Trocar a porta 3306 por outra resolve?

Não. Varreduras encontram o serviço em qualquer porta. O que protege é não expor e filtrar por IP.

Posso usar fail2ban no banco?

Pode, mas é paliativo. Se a porta não está acessível pela internet, não há força bruta para bloquear.

TLS deixa o banco mais lento?

O custo é pequeno em CPUs atuais, principalmente com conexões reaproveitadas por pool.

Leitura complementar

Precisa de ajuda?

Se suspeitar que seu banco foi acessado indevidamente, isole o servidor (bloqueie as portas pelo firewall ou pelo console IPMI/iLO), preserve os logs e abra um ticket imediatamente.

Esta resposta lhe foi útil? 0 Usuários acharam útil (0 Votos)

Leia também