Guest gnoo Posted April 27, 2019 at 09:03 PM Share Posted April 27, 2019 at 09:03 PM Saudações, há uns tempos atrás andei a bater com a cabeça no tema de fragmentação de pacotes e MTU, andei a mexer com python também para tentar observar esse todo esse processo, e percebi que este assunto tem alguma importância quando estamos a aprender redes e normalmente não prestamos muita atenção. Decidi fazer uma pequena introdução para aqueles mais distraídos, e também para aqueles que querem um dia mexer com gestão de redes e que precisam de movimentar grandes quantidades de dados seja em backups ou outras coisas, este tópico é de extrema importância. Tal como eu disse este tópico é apenas uma introdução e é imprescindível ler sobre este conteúdo num livro sobre a especialidade, alguma informação que aqui deixo foi retirada deste livro: MTU significa Unidade Máxima de Transmissão, determina o tamanho máximo de um Frame/Pacote recebido ou enviado a partir de um interface de rede, o valor do tamanho máximo é determinado pela tecnologia que estamos a utilizar para enviar informação entre dois dispositivos. Vamos dar o exemplo da Ethernet, um frame Ethernet normal carrega 1500 bytes, todos os datagramas /pacotes IP com tamanho superior a 1500 bytes serão fragmentados. Para ver o valor do MTU configurado na nossa placa de rede, quem tem o pacote iproute2 instalado no seu sistema, pode ver com o comando, ip addr, para aqueles que ainda usam o net-tools, podem ver com o comando ifconfig. O valor do MTU pode ser configurado tanto na nossa máquina como no dispositivo que está a fazer o roteamento de pacotes, atenção cada plca de rede tem um valor mínimo e máximo para o valor do MTU. Como a imagem que segue nos mostra se o valor da nossa configuração for 3,300, e o valor do MTU do dispositivo que faz o roteameneto dos pacotes for 1,300, ao passar no router esses pacotes vão fragmentados uma vez que o MTU do router, é menor que o MTU do emissor do pacote. No header de um datagrama IP temos 5 campos importantes de entender quando falamos de fragmentação de pacotes IP. Identification – O valor deste campo é utilizado após a fragmentação do lado do recetor na altura de reagrupar os pacotes fragmentados. Total Length – Diz-nos o tamanho de cada pacote / fragmento em bytes. Flags : X -Reservada não utilizada DF ( don’t Fragment ) - Quando o valor desta flag é 1, diz que o pacote não deve ser fragmentado MF ( more fragments ) - Os valores desta flag podem variar mediante o número de fragmentos caso seja o ultimo fragmento, o valor é zero porque é o último fragmento. O valor zero também pode querer dizer que não existem fragmentos para além desse pacote. Fragment Offset – Este valor indica ao recetor dos fragmentos em que posição e sequência cada fragmento de estar para reconstruir o pacote fragmentado pelo emissor do pacote. Header Checksum – Ao enviar o pacote cálculo é feito ao header, a cada hop ( cada passagem num router ), é feito um novo cálculo ao header pelo dispositivo que recebe o pacote, se o valor não corresponder ao anterior, o pacote é tido como corrompido e descartado. Script Com python: #coding:utf-8 #!/usr/bin/env python3 from socket import * import struct import binascii def ethernet_frame(raw_dados): mac_destino, mac_fonte, protocolo = struct.unpack('! 6s 6s H', raw_dados[:14]) return byte_to_hex_mac(mac_destino), byte_to_hex_mac(mac_fonte), htons(protocolo), raw_dados[14:] def byte_to_hex_mac(mac_em_bytes): endereco = binascii.hexlify(mac_em_bytes).decode("ascii") return ":".join([endereco[i:i+2] for i in range(0,12,2)]) def dados_pacote_ipv4(carga): tupla_dados_ipv4 = struct.unpack("!BBHHHBBH4s4s", carga[:20]) tamanho_total_pacote = tupla_dados_ipv4[2] identificacao = tupla_dados_ipv4[3] flags_offset_fragmento = tupla_dados_ipv4[4] checksum_cabecalho = tupla_dados_ipv4[7] ip_origem = inet_ntoa(tupla_dados_ipv4[8]) ip_destino = inet_ntoa(tupla_dados_ipv4[9]) fragmento = (flags_offset_fragmento << 3) & 1 #Flags flag_RES = (flags_offset_fragmento >> 15) & 1 flag_DF = (flags_offset_fragmento >> 14) & 1 flag_MF = (flags_offset_fragmento >> 13) & 1 return tamanho_total_pacote, identificacao, fragmento, checksum_cabecalho, ip_origem, ip_destino, flag_RES, flag_DF, flag_MF sock = socket(AF_PACKET, SOCK_RAW, ntohs(0x0003)) while True: raw_dados, addr = sock.recvfrom(65536) mac_destino, mac_fonte, tipo_ethernet, payload = ethernet_frame(raw_dados) # tipo_ethernet # Se for 8 vem ai pacote IP \0/ if tipo_ethernet == 8: tamanho_total_pacote, identificacao, fragmento, checksum_cabecalho, ip_origem, ip_destino, flag_RES, flag_DF, flag_MF = dados_pacote_ipv4(payload) print("##### IPv4 HEADER #####") print("Tamanho pacote em bytes {}".format(tamanho_total_pacote)) print("Identificação do Fragmento {}".format(identificacao)) print("Fragmento {}".format(fragmento)) print("Checksum cabeçalho {}".format(checksum_cabecalho)) print("IP Origem {}".format(ip_origem)) print("IP Destino {}".format(ip_destino)) print("----FLAGS---") print("Reservado : {}".format(flag_RES)) print("Sem Fragmento : {}".format(flag_DF)) print("Mais Fragmentos : {}".format(flag_MF)) Abraço. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.