|
|
(Uma revisão intermediária pelo mesmo usuário não está sendo mostrada) |
Linha 8: |
Linha 8: |
| Para utilizar o script você precisará do módulo '''netmiko''' instalado. Esse módulo te permite fazer conexões, via python, em diversos tipos de devices. Como utilizaremos o Debian aqui, é bem simples de instalar: | | Para utilizar o script você precisará do módulo '''netmiko''' instalado. Esse módulo te permite fazer conexões, via python, em diversos tipos de devices. Como utilizaremos o Debian aqui, é bem simples de instalar: |
| # apt install python3-netmiko | | # apt install python3-netmiko |
− | Instalado o '''netmiko''' basta criar o script abaixo. Este script é a primeira versão, pode conter bugs mas sinta-se convidado a ajudar a melhorá-lo. Pode me contactar para isso. | + | Instalado o '''netmiko''' basta pegar o script no '''Github''' em [https://github.com/gondimcodes/lgview '''https://github.com/gondimcodes/lgview''']. Este script é a primeira versão, pode conter bugs mas sinta-se convidado a ajudar a melhorá-lo. |
− | #!/usr/bin/env python3
| + | |
− | <nowiki>'''</nowiki>
| |
− | lgview is free software; you can redistribute it and/or modify
| |
− | it under the terms of the GNU General Public License as published by
| |
− | the Free Software Foundation; either version 2 of the License, or
| |
− | (at your option) any later version.
| |
− | <nowiki>#</nowiki>
| |
− | This program is distributed in the hope that it will be useful,
| |
− | but WITHOUT ANY WARRANTY; without even the implied warranty of
| |
− | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| |
− | GNU General Public License for more details.
| |
− | <nowiki>#</nowiki>
| |
− | You should have received a copy of the GNU General Public License
| |
− | along with this program; if not, write to the Free Software
| |
− | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
| |
− |
| |
− | Precisa do pacote: python3-netmiko
| |
− | <nowiki>'''</nowiki>
| |
− | import os
| |
− | import sys
| |
− | import re
| |
− | from netmiko import ConnectHandler
| |
− |
| |
− | __author__ = 'Marcelo Gondim'
| |
− | __version__= 1.0
| |
− | __datebegin__= "25/06/2023"
| |
− | <nowiki>#########################################################################</nowiki>
| |
− | routeviews = {
| |
− | <nowiki> </nowiki> "device_type": "cisco_xe",
| |
− | <nowiki> </nowiki> "host": "route-views.routeviews.org",
| |
− | <nowiki> </nowiki> "username": "rviews",
| |
− | <nowiki> </nowiki> "password": ""
| |
− | }
| |
− |
| |
− | ix_sp = {
| |
− | <nowiki> </nowiki> "device_type": "cisco_ios_telnet",
| |
− | <nowiki> </nowiki> "host": "lg.sp.ptt.br",
| |
− | }
| |
− |
| |
− | ix_rj = {
| |
− | <nowiki> </nowiki> "device_type": "cisco_ios_telnet",
| |
− | <nowiki> </nowiki> "host": "lg.rj.ix.br",
| |
− | }
| |
− |
| |
− | ix_ce = {
| |
− | <nowiki> </nowiki> "device_type": "cisco_ios_telnet",
| |
− | <nowiki> </nowiki> "host": "lg.ce.ix.br",
| |
− | }
| |
− |
| |
− | at_t = {
| |
− | <nowiki> </nowiki> "device_type": "cisco_ios_telnet",
| |
− | <nowiki> </nowiki> "host": "route-server.ip.att.net",
| |
− | <nowiki> </nowiki> "username": "rviews",
| |
− | <nowiki> </nowiki> "password": "rviews"
| |
− | }
| |
− |
| |
− | internexa = {
| |
− | <nowiki> </nowiki> "device_type": "juniper_junos",
| |
− | <nowiki> </nowiki> "host": "177.84.161.226",
| |
− | <nowiki> </nowiki> "username": "bgp_view",
| |
− | <nowiki> </nowiki> "password": "bgp_view"
| |
− | }
| |
− |
| |
− | algar = {
| |
− | <nowiki> </nowiki> "device_type": "juniper_junos",
| |
− | <nowiki> </nowiki> "host": "201.48.0.2",
| |
− | <nowiki> </nowiki> "username": "rviews",
| |
− | <nowiki> </nowiki> "password": "rviews"
| |
− | }
| |
− |
| |
− | <nowiki>#########################################################################</nowiki>
| |
− |
| |
− | try:
| |
− | <nowiki> </nowiki> prefixo = sys.argv[1]
| |
− | <nowiki> </nowiki> asn_mitigacao = sys.argv[2]
| |
− | <nowiki> </nowiki> asn_prefixo = sys.argv[3]
| |
− | except:
| |
− | <nowiki> </nowiki> print("Parametros faltando! Precisa passar o prefixo IPv4 /24 mitigado, o ASN mitigador e o ASN do prefixo mitigado.")
| |
− | <nowiki> </nowiki> print("Ex.: ./lgview.py 192.168.0.0/24 65000 65001")
| |
− | <nowiki> </nowiki> exit(0)
| |
− |
| |
− |
| |
− | def grep(texto, dado):
| |
− | <nowiki> </nowiki> linhas = texto.split('\n')
| |
− | <nowiki> </nowiki> lista = []
| |
− |
| |
− | <nowiki> </nowiki> for linha in linhas:
| |
− | <nowiki> </nowiki> if re.search(dado, linha):
| |
− | <nowiki> </nowiki> if "community" not in linha.lower():
| |
− | <nowiki> </nowiki> lista.append(linha)
| |
− |
| |
− | <nowiki> </nowiki> return lista
| |
− |
| |
− | os.system('cls' if os.name == 'nt' else 'clear')
| |
− | titulo = "LGVIEW - Lista prefixos nos Looking Glass para troubleshooting de Mitigacao DDoS - %s - v%s - %s" % (__author__, __version__,__datebegin__)
| |
− | print("#"*126)
| |
− | print(" %s" %(titulo))
| |
− | print("#"*126)
| |
− | print("Verificando Prefixo: " + prefixo + "\n")
| |
− | <nowiki>#########################################################################</nowiki>
| |
− |
| |
− | print("Checando LG: route-views.routeviews.org")
| |
− | consulta = ConnectHandler(**routeviews)
| |
− | consulta.send_command('terminal length 0')
| |
− | resultado = consulta.send_command('show ip bgp ' + prefixo)
| |
− |
| |
− | busca = grep(resultado, asn_prefixo)
| |
− |
| |
− | for elemento in busca:
| |
− | <nowiki> </nowiki> if asn_mitigacao not in elemento:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[91m' + elemento + '\033[0m')
| |
− | <nowiki> </nowiki> else:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[92m' + elemento + '\033[0m')
| |
− |
| |
− | <nowiki>#########################################################################</nowiki>
| |
− |
| |
− | print("Checando LG: IX-SP")
| |
− | consulta = ConnectHandler(**ix_sp)
| |
− | consulta.send_command('terminal length 0')
| |
− | resultado = consulta.send_command('show ip bgp ' + prefixo)
| |
− |
| |
− | busca = grep(resultado, asn_prefixo)
| |
− |
| |
− | for elemento in busca:
| |
− | <nowiki> </nowiki> if asn_mitigacao not in elemento:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[91m' + elemento + '\033[0m')
| |
− | <nowiki> </nowiki> else:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[92m' + elemento + '\033[0m')
| |
− |
| |
− | <nowiki>#########################################################################</nowiki>
| |
− |
| |
− | print("Checando LG: IX-RJ")
| |
− | consulta = ConnectHandler(**ix_rj)
| |
− | consulta.send_command('terminal length 0')
| |
− | resultado = consulta.send_command('show ip bgp ' + prefixo)
| |
− |
| |
− | busca = grep(resultado, asn_prefixo)
| |
− |
| |
− | for elemento in busca:
| |
− | <nowiki> </nowiki> if asn_mitigacao not in elemento:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[91m' + elemento + '\033[0m')
| |
− | <nowiki> </nowiki> else:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[92m' + elemento + '\033[0m')
| |
− |
| |
− | <nowiki>#########################################################################</nowiki>
| |
− |
| |
− | print("Checando LG: IX-CE")
| |
− | consulta = ConnectHandler(**ix_ce)
| |
− | consulta.send_command('terminal length 0')
| |
− | resultado = consulta.send_command('show ip bgp ' + prefixo)
| |
− |
| |
− | busca = grep(resultado, asn_prefixo)
| |
− |
| |
− | for elemento in busca:
| |
− | <nowiki> </nowiki> if asn_mitigacao not in elemento:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[91m' + elemento + '\033[0m')
| |
− | <nowiki> </nowiki> else:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[92m' + elemento + '\033[0m')
| |
− |
| |
− | <nowiki>#########################################################################</nowiki>
| |
− |
| |
− | print("Checando LG: AT&T")
| |
− | consulta = ConnectHandler(**at_t)
| |
− | consulta.send_command('set cli screen-length 0')
| |
− | resultado = consulta.send_command('show route protocol bgp ' + prefixo)
| |
− |
| |
− | busca = grep(resultado, asn_prefixo)
| |
− |
| |
− | for elemento in busca:
| |
− | <nowiki> </nowiki> if asn_mitigacao not in elemento:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[91m' + elemento + '\033[0m')
| |
− | <nowiki> </nowiki> else:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[92m' + elemento + '\033[0m')
| |
− |
| |
− | <nowiki>#########################################################################</nowiki>
| |
− |
| |
− | print("Checando LG: Internexa")
| |
− | consulta = ConnectHandler(**internexa)
| |
− | consulta.send_command('set cli screen-length 0')
| |
− | resultado = consulta.send_command('show route protocol bgp ' + prefixo)
| |
− |
| |
− | busca = grep(resultado, asn_prefixo)
| |
− |
| |
− | for elemento in busca:
| |
− | <nowiki> </nowiki> if asn_mitigacao not in elemento:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[91m' + elemento + '\033[0m')
| |
− | <nowiki> </nowiki> else:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[92m' + elemento + '\033[0m')
| |
− |
| |
− | <nowiki>#########################################################################</nowiki>
| |
− |
| |
− | print("Checando LG: Algar")
| |
− | consulta = ConnectHandler(**algar)
| |
− | consulta.send_command('set cli screen-length 0')
| |
− | resultado = consulta.send_command('show route protocol bgp ' + prefixo)
| |
− |
| |
− | busca = grep(resultado, asn_prefixo)
| |
− |
| |
− | for elemento in busca:
| |
− | <nowiki> </nowiki> if asn_mitigacao not in elemento:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[91m' + elemento + '\033[0m')
| |
− | <nowiki> </nowiki> else:
| |
− | <nowiki> </nowiki> print('AS-PATH: ' + '\033[92m' + elemento + '\033[0m')
| |
− |
| |
− | <nowiki>#########################################################################</nowiki>
| |
| Para executar é bem simples, passe como parâmetros: o '''prefixo IPv4 /24''' que quer fazer a busca, o '''ASN da empresa mitigadora''' e o '''ASN do seu prefixo'''. Abaixo um exemplo de chamada: | | Para executar é bem simples, passe como parâmetros: o '''prefixo IPv4 /24''' que quer fazer a busca, o '''ASN da empresa mitigadora''' e o '''ASN do seu prefixo'''. Abaixo um exemplo de chamada: |
| # ./lgview.py 198.51.100.0/24 65200 65001 | | # ./lgview.py 198.51.100.0/24 65200 65001 |
− | [[Arquivo:Lgview.png|nenhum|commoldura]]As linhas em '''vermelho''' merecem sua atenção porque indicam um provável vazamento do prefixo. Em algumas situações pode não ser um vazamento, mas precisa ser checado. Precisamos garantir que o prefixo /24 esteja passando pela nuvem de mitigação DDoS. | + | [[Arquivo:Lgview.png|nenhum|commoldura]]As linhas em '''vermelho''' merecem sua atenção porque indicam um provável vazamento do prefixo. Em algumas situações pode não ser um vazamento, mas precisa ser checado. Precisamos garantir que o prefixo /24 atacado, esteja passando pela nuvem de mitigação DDoS. |
| | | |
| == Conclusão == | | == Conclusão == |
Objetivo
Ajudar no troubleshooting de um dos principais problemas relacionados com o não funcionamento de uma Mitigação DDoS, o vazamento dos prefixos /24. Quando se tem contratado uma nuvem de mitigação DDoS, precisamos garantir que o prefixo /24 atacado passe pelo Scrubbing Center da fornecedora de mitigação DDoS. Se o tráfego estiver vazando por outros trânsitos IP, IX, etc ou se o prefixo IP não tiver sendo devidamente anunciado, sua mitigação falhará e o ataque poderá vir por outros caminhos. Embora existam ataques em IPv6, o IPv4 ainda é o principal alvo dos ataques DDoS e por isso esse artigo está focado no IPv4. Provedores que já utilizam IPv6 se beneficiam de menor consumo de clean pipe, diminuição de efeitos colaterais causados pela mitigação e economia em CGNAT.
A maneira mais simples de checarmos os vazamos de prefixos /24, é usando os diversos Looking Glass que encontramos pela Internet. Neles podemos ver se os prefixos estão realmente passando por onde devem. Pensando em ajudar nessa tarefa criei um script em python que checa em alguns Looking Glass, como está o anúncio do prefixo e te avisar onde está o problema. O script é simples, não é tão performático porque os sistemas que são consultados também não são rápidos, mas acredito que deve ajudar mesmo assim ou até mesmo servir como prova de conceito para quem está estudando Redes.
O script lgview.py
Para utilizar o script você precisará do módulo netmiko instalado. Esse módulo te permite fazer conexões, via python, em diversos tipos de devices. Como utilizaremos o Debian aqui, é bem simples de instalar:
# apt install python3-netmiko
Instalado o netmiko basta pegar o script no Github em https://github.com/gondimcodes/lgview. Este script é a primeira versão, pode conter bugs mas sinta-se convidado a ajudar a melhorá-lo.
Para executar é bem simples, passe como parâmetros: o prefixo IPv4 /24 que quer fazer a busca, o ASN da empresa mitigadora e o ASN do seu prefixo. Abaixo um exemplo de chamada:
# ./lgview.py 198.51.100.0/24 65200 65001
As linhas em vermelho merecem sua atenção porque indicam um provável vazamento do prefixo. Em algumas situações pode não ser um vazamento, mas precisa ser checado. Precisamos garantir que o prefixo /24 atacado, esteja passando pela nuvem de mitigação DDoS.
Conclusão
Espero que além de útil, o artigo possa ter passado o quão é importante essa validação.
Essa documentação foi útil? Compartilhe, divulgue e ajude outras pessoas.
Autor: Marcelo Gondim