Jump to content
Sign in to follow this  
gnoo

MTU & fragmentação de pacotes IP e a sua análise com python

Recommended Posts

Posted (edited)

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:

2081715649_Capturadeecr_2019-04-27_21-49-34.thumb.png.fc0120ba4f540b4690242669aff3c800.png

 

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.

mtu.png.2c6fd0e61cb97e3bea8c9b37993e6a92.png

 

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.

1943026457_Capturadeecr_2019-04-27_18-45-54.png.b5f141b044702b7eef3193e64a47a61e.png

No header de um datagrama IP temos 5 campos importantes de entender quando falamos de fragmentação de pacotes IP.

header.png.ca370050b0aaf44a1a45fa96b9dfe6e3.png

 

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.

Edited by gnoo
  • Curtir 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...