Usando o banco de dados de log Mikrotik para suprimir a força bruta

Boa tarde

Em uma publicação anterior , falei sobre como, fácil e naturalmente, você pode configurar a coleção de metadados de tráfego de rede nos roteadores Mikrotik em um banco de dados.

Agora é hora de ensinar nosso servidor a fazer uma análise elementar dos dados recebidos e enviar comandos de volta.

Objetivo: Controle dinâmico das regras do firewall Mikrotik para suprimir ataques de rede com adivinhação de senha.

Meios: Distribuição Linux fresca com rsyslogd v8, crond, DBMS mariadb e o próprio roteador Mikrotik.

Mecânica: Usando a tarefa atribuída, uma consulta SQL é executada no banco de dados com dados de tráfego acumulados e atualizados e retorna uma lista de endereços IP de saída; o script bash lançado pela coroa gera comandos Mikrotik e, usando uma conexão ssh, reabastece a lista de endereços para regras de bloqueio existentes.

Será sobre a proteção de portas TCP abertas. Podem ser portas que entram no Mikrotik e encaminhadas para a rede local.

Para começar, indicamos onde pode haver pontos fracos:

  • Protocolos de controle do roteador ssh, telnet, web, winbox
  • Serviços de correio smtp, pop, imap
  • Quaisquer serviços da web fornecidos fora
  • Área de trabalho remota MS RDP, VNC, etc.
  • Qualquer outra coisa a seu critério

Escrevendo uma consulta SQL para procurar força bruta

Nossa organização possui servidores de terminal abertos para o exterior através de portas não prioritárias.
No DNAT Mikrotik ativei o log das regras necessárias adicionando o prefixo RDP_DNAT. Por esse prefixo, procuraremos:

MariaDB [traflog]> select src,dport,count(dport) as ' ' from traffic where datetime>now() - interval 1 day and logpref='RDP_DNAT' group by src having count(dport)>50; +-----------------+-------+---------------------------------------+ | src | dport |   | +-----------------+-------+---------------------------------------+ | 185.156.177.58 | 12345 | 118 | | 185.156.177.59 | 12345 | 267 | | 193.238.46.12 | 12345 | 318 | | 193.238.46.13 | 12345 | 319 | | 193.238.46.99 | 12345 | 342 | | 194.113.106.150 | 12345 | 67 | | 194.113.106.152 | 12345 | 167 | | 194.113.106.153 | 12345 | 190 | | 194.113.106.154 | 12345 | 192 | | 194.113.106.155 | 12345 | 190 | | 194.113.106.156 | 12345 | 216 | | 194.113.106.158 | 12345 | 124 | +-----------------+-------+---------------------------------------+ 12 rows in set (0.06 sec) 

Essa solicitação mostra o endereço IP (do qual o ataque está vindo), a porta para a qual a conexão é feita (o número da porta é alterado) e o número de tentativas de conexão, com agrupamento preliminar por src e seleção de linhas, com o número de tentativas mais de 50 no passado, a partir do momento atual, dia.

No meu caso, esses endereços podem ser banidos com segurança, pois o número de conexões com clientes "bons" é menor, não mais do que 5 a 10 por dia, a partir de um IP.

A solicitação funciona bem, rápido, mas é um pouco longa. Para uso posterior, proponho uma visão que copie menos no futuro:

 MariaDB [traflog]> create or replace view rdp_brute_day as select src, dport, count(dport) from traffic where datetime>now() - interval 1 day and logpref='RDP_DNAT' group by src having count(dport)>50; Query OK, 0 rows affected (0.23 sec) 

Vamos verificar como a exibição funciona:

 MariaDB [traflog]> select src,count(dport) from rdp_brute_day; +----------------+--------------+ | src | count(dport) | +----------------+--------------+ | 185.156.177.58 | 11 | +----------------+--------------+ 1 row in set (0.09 sec) 

Ótimo.

Adicionamos o usuário Mikrotik com autorização pela chave dsa

No console linux, geramos a chave dsa, sob o usuário em nome de quem a tarefa agendada será lançada, feita a partir do root:

 root@monix:~# ssh-keygen -t dsa Generating public/private dsa key pair. Enter file in which to save the key (/root/.ssh/id_dsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_dsa. Your public key has been saved in /root/.ssh/id_dsa.pub. ... 

A senha não é necessária. Copiamos a chave pública /root/.ssh/id_dsa.pub para o Mikrotik de qualquer maneira possível. Eu o trouxe com o comando cat, copiei o texto da janela em um arquivo de texto, salvei e arrastei para a janela de arquivos do winbox.

Não sei por que, mas durante as operações a seguir, através da interface do winbox, algo deu errado. Ao conectar do servidor via ssh, o Mikrotik também solicitou uma senha para mim. Depois de excluir o usuário criado e executar todas as operações pelo console, a conexão dsa funcionou. Fez aproximadamente como descrito aqui .

Em geral, recebi a entrada de boas-vindas sem uma senha usando a chave dsa e executei o comando de verificação:

 root@monix:/# ssh rsyslogger@192.168.0.230 /system resource print uptime: 2w1d5h22m43s version: 6.43.2 (stable) ... 

Bom

Escrevendo um script bash

O script não foi complicado:

 mikrotik_cmd_list(){ brute_src_list=$(mysql --skip-column-names traflog -e 'select src from rdp_brute_day') for src in $brute_src_list do echo "ip firewall address-list add address=$src list=rdp_banlist timeout=1d" done } mikrotik_cmd_list | ssh -T rsyslogger@192.168.0.230 

Para transferir todos os comandos dentro da mesma conexão ssh, eu precisava descrever a função mikrotik_cmd_list (), na qual uma solicitação é realizada primeiro com o salvamento de endereços IP na variável brute_src_list e, em seguida, no loop, essa variável gera sequencialmente comandos para o Mikrotik. Depois de chamar a função, a saída é roteada através do pipe para ssh.

Não se esqueça de fechar os direitos de acesso ao script a todos, exceto root, e tornar o arquivo executável.
O comando gerado pelo script adicionará o endereço IP ao rdp_banlist por 1 dia, após esse período será removido da própria lista. Se você quiser deixá-lo para sempre, remova a opção de tempo limite.

Adicione uma regra ao firewall

Eu vim com duas opções de como usar o rdp_banlist:

Opção um: adicione o rdp_banlist com um ponto de exclamação às regras NAT com o prefixo RDP_DNAT.

 add action=dst-nat chain=dstnat comment="..." dst-address=1.2.3.4 dst-port=12345 log=yes log-prefix=RDP_DNAT protocol=tcp src-address-list=\ !rdp_banlist to-addresses=192.168.200.181 to-ports=3389 

Algo assim. Ou seja, dnat tudo, exceto o que está em rdp_banlist.

Nesta opção, há um sinal de mais e menos.

A vantagem é que as conexões serão interrompidas imediatamente.

A desvantagem é que esse ip não entrará mais no banco de dados de tráfego e depois de um dia, quando o tempo limite de armazenamento na lista negra tiver passado, ele começará a cagar novamente.

Opção dois: adicione o rdp_banlist com um ponto de exclamação à regra de firewall da cadeia de encaminhamento, onde permitimos que o tráfego passe pelo TCP 3389, semelhante à maneira do primeiro método.

 add action=accept chain=forward comment="..." dst-port=3389 log=yes log-prefix=ACCEPT_RDP protocol=tcp src-address-list=\ !rdp_banlist to-ports=3389 

Algo assim. Nós permitimos tudo, exceto isso na lista de proibições.

Há também um sinal de mais e menos.

Plus. Os logs com o prefixo RDP_DNAT continuarão a ser transmitidos no banco de dados de tráfego, pelo qual determinamos o sinal de ataque. Como resultado, quando o tempo limite de proibição de um host específico que continua as tentativas de força bruta expirar, ele será adicionado à lista de proibição novamente após o próximo lançamento da tarefa agendada.

A desvantagem é que ele continua a ser péssimo na tabela DSTNAT, criando um novo registro com cada conexão, embora temporário.

Em geral, a decisão é sua, eu escolhi os dois :) (de fato, apenas o primeiro funciona nesse caso), já que o segundo foi ativado anteriormente e a mecânica era diferente, com base em entradas sequenciais nas listas stage1, stage2, stage3, banlist ... bem, você entendeu. Um truque antigo e pouco confiável, pode facilmente banir clientes "bons" e, ao mesmo tempo, pular os "ruins" que calcularam educadamente o estágio de tempo limite1.

Crontab de trabalho agendado

Resta adicionar a tarefa atribuída ao crontab:

 root@monix:/root# echo '12 * * * * root /usr/share/traflog/scripts/rdp_brute.sh >/dev/null 2>&1' >> /etc/crontab 

Esse registro executará o script a cada hora em 12 minutos.

Devo admitir que acabei de terminar esse trabalho hoje e, com um alto grau de probabilidade, algo pode dar errado. De acordo com as circunstâncias, complementarei e corrigirei os erros. Quero beber para dormir profundamente nos feriados de Ano Novo, por isso estou com pressa de terminar.
Provavelmente é tudo.

Obrigado a todos pela atenção e Feliz Ano Novo!

Referências:

Documentação do mysql
Documentação do firewall Mikrotik
Obrigado a Andrey Smirnov pelo artigo sobre conexão dsa.

Source: https://habr.com/ru/post/pt434736/


All Articles