Acessar MySQL em IP privado com túnel SSH, sem abrir a porta 3306 para a internet
Use o servidor que já alcança o banco como ponte: ssh -L no terminal ou a opção TCP/IP over SSH do Workbench, com usuário de banco restrito e porta fechada para fora.
A Loja Trilha migrou o MySQL para uma VM na nuvem sem IP público, endereço interno 10.0.2.15. O aplicativo, na VM vizinha 10.0.1.5, conecta normalmente. O analista Marco, em casa, abre o MySQL Workbench e recebe tempo esgotado. A sugestão que aparece no chat da equipe é a de sempre: "libera a 3306 no firewall para o IP da casa dele". Na semana seguinte o IP da casa muda, alguém troca a regra por "qualquer origem" e o banco fica exposto para a internet inteira.
A resposta curta: entre por SSH na máquina que já alcança o banco e encaminhe uma porta local. O Workbench conecta em 127.0.0.1:3307 no notebook, o SSH carrega a conexão criptografada até a VM 10.0.1.5, e de lá ela segue pela rede privada até 10.0.2.15:3306. A porta do MySQL nunca é publicada.
Por que o túnel funciona e a porta aberta é o erro
Um banco em IP privado só é alcançável de dentro da rede da nuvem. Isso é uma proteção, não um defeito. A VM do aplicativo está dentro dessa rede e tem uma porta SSH aberta para administração. O encaminhamento de porta do SSH (a opção -L) aproveita esse acesso: tudo que entra numa porta do seu notebook é levado, dentro da sessão SSH, até a VM, que abre a conexão real com o banco como se fosse ela a cliente.
Abrir a 3306 para fora troca uma porta protegida por chave SSH por uma protegida só por usuário e senha do banco, e expõe o MySQL a varreduras automáticas que rodam o tempo todo. Mesmo restrita a um IP, a regra tende a ser afrouxada no primeiro problema. Se a ideia é a aplicação acessar o banco em outro servidor, o caminho é rede privada, como em MySQL em outro servidor; o túnel é para acesso humano e pontual.
Como montar o túnel
- Garanta acesso SSH por chave à VM ponte (10.0.1.5 por dentro, 203.0.113.10 por fora, no exemplo). O passo a passo está em chave SSH na VM.
- Crie um usuário de banco só para você, com o mínimo de permissão e aceitando conexão a partir do IP privado da ponte.
- Abra o túnel pelo terminal ou pelo Workbench.
- Conecte o cliente em
127.0.0.1na porta local escolhida. - Feche o túnel ao terminar.
- Confirme que a 3306 não responde de fora.
O usuário do banco
Do ponto de vista do MySQL, a conexão vem da VM ponte, não do seu notebook. Por isso o host do usuário é o IP privado dela:
CREATE USER 'marco_leitura'@'10.0.1.5' IDENTIFIED BY 'senha-longa-gerada-pelo-gerenciador';
GRANT SELECT ON loja.* TO 'marco_leitura'@'10.0.1.5';
Somente leitura, só no schema da loja. Para uma correção pontual, conceda a permissão necessária e revogue depois. Não use root: um comando errado digitado no fim do expediente com root afeta o banco inteiro.
Pelo terminal
O cliente OpenSSH já vem no Linux, no macOS e no Windows 10 e 11. O comando:
ssh -N -L 127.0.0.1:3307:10.0.2.15:3306 deploy@203.0.113.10
Lendo da esquerda para a direita: -N não abre um shell, só mantém o túnel; -L 127.0.0.1:3307 escuta na porta 3307 apenas no seu notebook; 10.0.2.15:3306 é o destino visto a partir da ponte. Prefixar com 127.0.0.1 evita que outras máquinas da sua rede de casa usem o túnel. Enquanto o comando roda, em outro terminal:
mysql -h 127.0.0.1 -P 3307 -u marco_leitura -p loja
Use 127.0.0.1, não localhost: no cliente mysql em Linux e macOS, localhost significa conectar pelo socket local, e o túnel não é usado. Escolhi 3307 para não colidir com um MySQL que você talvez tenha instalado no próprio notebook.
Deixando fixo no arquivo de configuração
Em ~/.ssh/config:
Host banco-loja
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519
LocalForward 127.0.0.1:3307 10.0.2.15:3306
ExitOnForwardFailure yes
ServerAliveInterval 30
Agora basta ssh -N banco-loja. O ExitOnForwardFailure faz o SSH sair com erro se não conseguir abrir a porta local, em vez de conectar e deixar você achando que o túnel existe. O ServerAliveInterval mantém a sessão viva em redes que derrubam conexões ociosas.
Pelo MySQL Workbench
Na nova conexão, escolha o método "Standard TCP/IP over SSH". Em SSH Hostname, coloque 203.0.113.10:22; em SSH Username, deploy; em SSH Key File, o caminho da sua chave privada. Em MySQL Hostname, coloque 10.0.2.15, porta 3306, e o usuário marco_leitura. O Workbench abre e fecha o túnel sozinho junto com a conexão. Outros clientes gráficos, como DBeaver, têm opção equivalente de túnel SSH nas configurações da conexão.
Restringindo o que a ponte permite
Por padrão, quem tem acesso SSH à ponte pode encaminhar para qualquer destino que ela alcance. No sshd_config da ponte, dá para limitar com PermitOpen, por exemplo num bloco Match User para o usuário de acesso ao banco, permitindo apenas 10.0.2.15:3306. Teste a mudança mantendo uma sessão aberta, para não se trancar fora. E a chave privada fica no seu notebook, não em chat nem em chamado: veja chave SSH não viaja em ticket.
Provedores de nuvem também oferecem serviços gerenciados de acesso, como bastion e gerenciadores de sessão, que fazem o mesmo papel sem você manter a porta 22 aberta para a internet. Vale considerar quando a equipe cresce.
Conferindo que o banco não está exposto
Na VM do banco, veja em que endereço o MySQL escuta:
sudo ss -tlnp | grep 3306
Se aparece 0.0.0.0:3306, ele escuta em todas as interfaces; a proteção depende do firewall e da ausência de IP público. Se a VM tem só IP privado, isso é aceitável; se tem IP público, ajuste o bind-address para o IP privado. De uma máquina fora da nuvem, tente nc -vz IP-PUBLICO 3306: o resultado esperado é falha de conexão ou tempo esgotado.
Erros comuns
- Abrir a 3306 no firewall "só para um IP". A regra é afrouxada no primeiro imprevisto e o banco fica exposto a varreduras.
- Conectar em
localhostem vez de127.0.0.1. O cliente usa o socket local e você conecta no banco errado ou em nenhum. - Criar o usuário do banco com o IP do notebook. O MySQL vê a conexão vindo da ponte e recusa o acesso.
- Usar
rootdo banco pelo túnel. Um comando errado tem alcance total. - Escutar o túnel em todas as interfaces. Qualquer um na rede do café usa a sua porta 3307.
- Deixar o túnel aberto em máquina compartilhada. Quem senta depois tem um caminho direto até o banco.
Checklist
- O acesso SSH à ponte é por chave, sem senha.
- O usuário de banco tem permissão mínima e host igual ao IP privado da ponte.
- O túnel escuta só em
127.0.0.1. - O cliente conecta em
127.0.0.1na porta local escolhida. - O túnel é fechado ao terminar.
- A 3306 não responde a partir da internet.
- A aplicação em produção acessa o banco pela rede privada, sem túnel.
De uma rede fora da sua nuvem, rode um teste de conexão na porta 3306 do IP público do servidor de banco: ela responde? Se responde, feche antes de montar qualquer túnel.
Referência: https://thesubtlepath.com/mysql/mysql-workbench-managing-mysql-behind-a-private-ip/