Às vezes é inevitável executar servidores de banco de dados MySQL em uma rede pública ou exposta. Essa é uma configuração comum em um ambiente de hospedagem compartilhada, em que um servidor é configurado com vários serviços e geralmente é executado no mesmo servidor que o servidor de banco de dados. Para quem tem esse tipo de configuração, deve sempre ter algum tipo de proteção contra ataques cibernéticos como negação de serviço, hacking, cracking, violação de dados; tudo o que pode resultar em perda de dados. Essas são coisas que sempre queremos evitar para nosso servidor de banco de dados.
Aqui estão algumas dicas que podemos fazer para melhorar nossa segurança MySQL ou MariaDB.
Verifique seus servidores de banco de dados regularmente
A proteção contra quaisquer arquivos maliciosos no servidor é muito importante. Examine o servidor regularmente para procurar vírus, spywares, malwares ou rootkits, especialmente se o servidor de banco de dados estiver co-localizado com outros serviços, como servidor de e-mail, HTTP, FTP, DNS, WebDAV, telnet e assim por diante. Comumente, a maioria dos problemas de invasão de banco de dados se originou da camada de aplicativo que está voltada para a rede pública. Assim, é importante verificar todos os arquivos, especialmente arquivos da web/aplicativos, pois eles são um dos pontos de entrada para entrar no servidor. Se eles estiverem comprometidos, o hacker pode entrar no diretório do aplicativo e ter a capacidade de ler os arquivos do aplicativo. Eles podem conter informações confidenciais, por exemplo, as credenciais de login do banco de dados.
ClamAV é uma das soluções antivírus mais conhecidas e amplamente confiáveis para uma variedade de sistemas operacionais, incluindo Linux. É gratuito e muito fácil de instalar e vem com um mecanismo de detecção bastante bom para procurar coisas indesejadas em seu servidor. Agende verificações periódicas no cron job, por exemplo:
0 3 * * * /bin/freshclam ; /bin/clamscan / --recursive=yes -i > /tmp/clamav.log ; mail -s clamav_log_`hostname` [email protected] < /tmp/clamav.log
O acima atualizará o banco de dados de vírus ClamAV, verificará todos os diretórios e arquivos e enviará um e-mail sobre o status da execução e relatório todos os dias às 3 da manhã.
Use funções e privilégios de usuário mais estritos
Ao criar um usuário MySQL, não permita que todos os hosts acessem o servidor MySQL com host curinga (%). Você deve verificar seu host MySQL e procurar qualquer valor de host curinga, conforme mostrado na instrução a seguir:
mysql> SELECT user,host FROM mysql.user WHERE host = '%';
+---------+------+
| user | host |
+---------+------+
| myadmin | % |
| sbtest | % |
| user1 | % |
+---------+------+
Na saída acima, restrinja ou remova todos os usuários que tenham apenas o valor '%' na coluna Host. Os usuários que precisam acessar o servidor MySQL remotamente podem ser forçados a usar o método de encapsulamento SSH, que não requer configuração de host remoto para usuários do MySQL. A maioria dos clientes de administração MySQL, como MySQL Workbench e HeidiSQL, podem ser configurados para se conectar a um servidor MySQL via tunelamento SSH, portanto, é possível eliminar completamente a conexão remota para usuários do MySQL.
Além disso, limite o privilégio SUPER apenas para usuários de localhost ou conectando-se via arquivo de soquete UNIX. Seja mais cauteloso ao atribuir o privilégio FILE a usuários não root, pois permite ler e gravar arquivos no servidor usando as instruções LOAD DATA INFILE e SELECT ... INTO OUTFILE. Qualquer usuário a quem este privilégio é concedido também pode ler ou gravar qualquer arquivo que o servidor MySQL possa ler ou gravar.
Alterar as configurações padrão do banco de dados
Ao afastar-se da configuração, nomeação e configurações padrão, podemos reduzir o vetor de ataque a várias dobras. As ações a seguir são alguns exemplos de configurações padrão que os DBAs podem alterar facilmente, mas geralmente negligenciadas relacionadas ao MySQL:
- Altere a porta padrão do MySQL para diferente de 3306.
- Renomeie o nome de usuário root do MySQL para outro que não seja "root".
- Aplique a expiração da senha e reduza a vida útil da senha para todos os usuários.
- Se o MySQL estiver co-localizado com os servidores de aplicativos, imponha a conexão apenas por meio do arquivo de soquete UNIX e pare de ouvir na porta 3306 para todos os endereços IP.
- Aplique a criptografia cliente-servidor e a criptografia de replicação servidor-servidor.
Na verdade, abordamos isso em detalhes nesta postagem do blog, Como proteger servidores MySQL/MariaDB.
Configurar um escravo atrasado
Um escravo atrasado é apenas um escravo típico, porém o servidor escravo executa intencionalmente transações posteriores ao mestre por pelo menos um período de tempo especificado, disponível no MySQL 5.6. Basicamente, um evento recebido do mestre não é executado até que pelo menos N segundos depois de sua execução no mestre. O resultado é que o escravo refletirá o estado do mestre em algum tempo no passado.
Um escravo atrasado pode ser usado para recuperar dados, o que seria útil quando o problema fosse encontrado imediatamente, dentro do período de atraso. Suponha que configuramos um escravo com um atraso de 6 horas do mestre. Se nosso banco de dados foi modificado ou excluído (acidentalmente por um desenvolvedor ou deliberadamente por um hacker) dentro desse intervalo de tempo, existe a possibilidade de revertermos para o momento anterior ao que aconteceu, interrompendo o mestre atual e trazendo o servidor escravo para cima até certo ponto com o seguinte comando:
# on delayed slave
mysql> STOP SLAVE;
mysql> START SLAVE UNTIL MASTER_LOG_FILE='xxxxx', MASTER_LOG_POS=yyyyyy;
Onde 'xxxxx' é o arquivo de log binário e 'yyyyy' é a posição imediatamente antes do desastre acontecer (use a ferramenta mysqlbinlog para examinar esses eventos). Finalmente, promova o escravo para se tornar o novo mestre e seu serviço MySQL estará novamente operacional como de costume. Este método é provavelmente a maneira mais rápida de recuperar seu banco de dados MySQL no ambiente de produção sem precisar recarregar um backup. Ter vários escravos atrasados com durações de comprimento diferentes, conforme mostrado neste blog, Multiple Delayed Replication Slaves for Disaster Recovery with Low RTO sobre como configurar servidores de replicação atrasados econômicos em contêineres do Docker.
Ativar registro binário
O registro binário geralmente é recomendado para ser ativado mesmo que você esteja executando em um servidor MySQL/MariaDB autônomo. O log binário contém informações sobre instruções SQL que modificam o conteúdo do banco de dados. As informações são armazenadas na forma de "eventos" que descrevem as modificações. Apesar do impacto no desempenho, ter log binário permite que você tenha a possibilidade de reproduzir seu servidor de banco de dados no ponto exato em que deseja que ele seja restaurado, também conhecido como recuperação pontual (PITR). O log binário também é obrigatório para replicação.
Com o log binário habilitado, é preciso incluir o arquivo de log binário e as informações de posição ao fazer um backup completo. Para mysqldump, usar o sinalizador --master-data com valor 1 ou 2 imprimirá as informações necessárias que podemos usar como ponto de partida para avançar o banco de dados ao reproduzir os logs binários posteriormente.
Com o registro binário ativado, você pode usar outro recurso interessante de recuperação chamado flashback, descrito na próxima seção.
Ativar Flashback
O recurso de flashback está disponível no MariaDB, onde você pode restaurar os dados para o snapshot anterior em um banco de dados MySQL ou em uma tabela. O Flashback usa o mysqlbinlog para criar as instruções de rollback e precisa de uma imagem de linha de log binário COMPLETA para isso. Assim, para utilizar este recurso, o servidor MySQL/MariaDB deve estar configurado com o seguinte:
[mysqld]
...
binlog_format = ROW
binlog_row_image = FULL
O diagrama de arquitetura a seguir ilustra como o flashback é configurado em um dos escravos:
Para realizar a operação de flashback, primeiro você deve determinar a data e hora quando você quer "ver" os dados, ou arquivo de log binário e posição. Em seguida, use o sinalizador --flashback com o utilitário mysqlbinlog para gerar instruções SQL para reverter os dados para esse ponto. No arquivo SQL gerado, você notará que os eventos DELETE são convertidos em INSERTs e vice-versa, e também troca as partes WHERE e SET dos eventos UPDATE.
A seguinte linha de comando deve ser executada no slave2 (configurado com binlog_row_image=FULL):
$ mysqlbinlog --flashback --start-datetime="2020-02-17 01:30:00" /var/lib/mysql/mysql-bin.000028 -v --database=shop --table=products > flashback_to_2020-02-17_013000.sql
Em seguida, desconecte slave2 da cadeia de replicação porque vamos quebrá-lo e usar o servidor para reverter nossos dados:
mysql> STOP SLAVE;
mysql> RESET MASTER;
mysql> RESET SLAVE ALL;
Por fim, importe o arquivo SQL gerado para o servidor MariaDB para a loja de banco de dados no slave2:
$ mysql -u root -p shop < flashback_to_2020-02-17_013000.sql
Quando o acima for aplicado, a tabela "produtos" estará no estado de 2020-02-17 01:30:00. Tecnicamente, o arquivo SQL gerado pode ser aplicado a servidores MariaDB e MySQL. Você também pode transferir o binário mysqlbinlog do servidor MariaDB para poder usar o recurso de flashback em um servidor MySQL. No entanto, a implementação do MySQL GTID é diferente do MariaDB, portanto, a restauração do arquivo SQL exige que você desative o MySQL GTID.
Algumas vantagens de usar o flashback é que você não precisa parar o servidor MySQL/MariaDB para realizar esta operação. Quando a quantidade de dados a serem revertidos é pequena, o processo de flashback é muito mais rápido do que recuperar os dados de um backup completo.
Registrar todas as consultas de banco de dados
O log geral basicamente captura todas as instruções SQL que estão sendo executadas pelo cliente no servidor MySQL. No entanto, isso pode não ser uma decisão popular em um servidor de produção ocupado devido ao impacto no desempenho e ao consumo de espaço. Se o desempenho for importante, o log binário tem a prioridade mais alta para ser ativado. O log geral pode ser habilitado durante o tempo de execução executando os seguintes comandos:
mysql> SET global general_log_file='/tmp/mysql.log';
mysql> SET global log_output = 'file';
mysql> SET global general_log = ON;
Você também pode definir a saída geral do log para uma tabela:
mysql> SET global log_output = 'table';
Você pode então usar a instrução SELECT padrão na tabela mysql.general_log para recuperar consultas. Espere um pouco mais de impacto no desempenho ao executar com essa configuração, conforme mostrado nesta postagem do blog.
Caso contrário, você pode usar ferramentas de monitoramento externas que podem realizar amostragem e monitoramento de consultas para filtrar e auditar as consultas que chegam ao servidor. O ClusterControl pode ser usado para coletar e resumir todas as suas consultas, conforme mostrado nas capturas de tela a seguir, onde filtramos todas as consultas que contêm a string DELETE:
Informações semelhantes também estão disponíveis na página de consultas principais do ProxySQL (se seu aplicativo for conectando via ProxySQL):
Isso pode ser usado para rastrear alterações recentes que ocorreram no servidor de banco de dados e também pode ser usado para fins de auditoria.
Conclusão
Seus servidores MySQL e MariaDB devem estar bem protegidos o tempo todo, pois geralmente contêm dados confidenciais que os invasores estão cuidando. Você também pode usar o ClusterControl para gerenciar os aspectos de segurança de seus servidores de banco de dados, conforme demonstrado por esta postagem no blog, Como proteger seus bancos de dados de código aberto com o ClusterControl.