1463 Network Segmentation Defense
Interactive Visualization of VLAN Isolation and Attack Containment
1463.1 Network Segmentation Defense - VLAN Isolation Limits Lateral Movement
This interactive animation demonstrates how network segmentation using VLANs (Virtual Local Area Networks) limits lateral movement during a security breach. Compare how an attacker spreads through a flat network versus a properly segmented network with firewall rules between segments.
This animation compares two network architectures:
- Flat Network: All devices on the same network segment with unrestricted communication
- Segmented Network: Devices organized into VLANs (IoT, Corporate, Guest) with firewall rules controlling inter-segment traffic
Watch how an attack spreads differently in each scenario.
- Click “Launch Attack” to start the attack simulation in both networks
- Use “Toggle View” to switch between Flat and Segmented network layouts
- Click “Reset” to restart the simulation
- Observe the Security Metrics panel showing attack containment statistics
- Watch traffic flow indicators and blocked connection attempts
Show code
// ============================================
// Network Segmentation Defense Animation
// ============================================
{
// IEEE Color palette
const colors = {
navy: "#2C3E50",
teal: "#16A085",
orange: "#E67E22",
gray: "#7F8C8D",
lightGray: "#ECF0F1",
white: "#FFFFFF",
red: "#E74C3C",
green: "#27AE60",
purple: "#9B59B6",
yellow: "#F1C40F",
darkRed: "#C0392B",
darkTeal: "#1ABC9C",
lightBlue: "#3498DB"
};
// Layout configuration
const width = 900;
const height = 620;
// Animation state
let currentView = "both"; // "both", "flat", "segmented"
let isAttacking = false;
let attackTimer = null;
let flatCompromisedCount = 0;
let segmentedCompromisedCount = 0;
let blockedAttempts = 0;
// Device definitions for flat network
const flatDevices = [
{ id: "f1", type: "iot", label: "Sensor 1", x: 80, y: 150, compromised: false },
{ id: "f2", type: "iot", label: "Camera", x: 160, y: 100, compromised: false },
{ id: "f3", type: "iot", label: "Thermostat", x: 240, y: 150, compromised: false },
{ id: "f4", type: "corp", label: "Workstation", x: 80, y: 250, compromised: false },
{ id: "f5", type: "corp", label: "File Server", x: 160, y: 300, compromised: false },
{ id: "f6", type: "corp", label: "Database", x: 240, y: 250, compromised: false },
{ id: "f7", type: "guest", label: "Guest 1", x: 80, y: 370, compromised: false },
{ id: "f8", type: "guest", label: "Guest 2", x: 160, y: 420, compromised: false },
{ id: "f9", type: "guest", label: "Printer", x: 240, y: 370, compromised: false }
];
// Device definitions for segmented network
const segmentedDevices = {
iot: [
{ id: "s1", type: "iot", label: "Sensor 1", x: 80, y: 120, compromised: false },
{ id: "s2", type: "iot", label: "Camera", x: 160, y: 80, compromised: false },
{ id: "s3", type: "iot", label: "Thermostat", x: 240, y: 120, compromised: false }
],
corp: [
{ id: "s4", type: "corp", label: "Workstation", x: 80, y: 260, compromised: false },
{ id: "s5", type: "corp", label: "File Server", x: 160, y: 220, compromised: false },
{ id: "s6", type: "corp", label: "Database", x: 240, y: 260, compromised: false }
],
guest: [
{ id: "s7", type: "guest", label: "Guest 1", x: 80, y: 400, compromised: false },
{ id: "s8", type: "guest", label: "Guest 2", x: 160, y: 360, compromised: false },
{ id: "s9", type: "guest", label: "Printer", x: 240, y: 400, compromised: false }
]
};
// VLAN definitions
const vlans = [
{ id: "iot-vlan", name: "VLAN 10: IoT Devices", color: colors.orange, y: 55, height: 120 },
{ id: "corp-vlan", name: "VLAN 20: Corporate", color: colors.teal, y: 195, height: 120 },
{ id: "guest-vlan", name: "VLAN 30: Guest", color: colors.purple, y: 335, height: 120 }
];
// Create main container
const container = d3.create("div")
.style("font-family", "system-ui, -apple-system, sans-serif")
.style("max-width", "900px")
.style("margin", "0 auto");
// Title
container.append("div")
.style("text-align", "center")
.style("margin-bottom", "15px")
.append("h3")
.style("color", colors.navy)
.style("margin", "0")
.text("Network Segmentation Defense");
// Control panel
const controls = container.append("div")
.style("display", "flex")
.style("justify-content", "center")
.style("gap", "10px")
.style("margin-bottom", "15px")
.style("flex-wrap", "wrap");
const buttonStyle = (btn, bg) => {
btn.style("padding", "10px 20px")
.style("font-size", "14px")
.style("font-weight", "600")
.style("border", "none")
.style("border-radius", "6px")
.style("cursor", "pointer")
.style("transition", "all 0.2s ease")
.style("background", bg)
.style("color", colors.white);
};
const attackBtn = controls.append("button")
.text("Launch Attack")
.call(btn => buttonStyle(btn, colors.red));
const resetBtn = controls.append("button")
.text("Reset")
.call(btn => buttonStyle(btn, colors.gray));
// View toggle
const viewToggle = controls.append("div")
.style("display", "flex")
.style("gap", "5px")
.style("margin-left", "20px");
const viewOptions = ["Both", "Flat Only", "Segmented Only"];
viewOptions.forEach((opt, i) => {
viewToggle.append("button")
.attr("class", `view-btn-${i}`)
.text(opt)
.style("padding", "10px 15px")
.style("font-size", "12px")
.style("font-weight", "500")
.style("border", `2px solid ${colors.navy}`)
.style("border-radius", "6px")
.style("cursor", "pointer")
.style("transition", "all 0.2s ease")
.style("background", i === 0 ? colors.navy : colors.white)
.style("color", i === 0 ? colors.white : colors.navy)
.on("click", function() {
currentView = i === 0 ? "both" : (i === 1 ? "flat" : "segmented");
viewToggle.selectAll("button")
.style("background", colors.white)
.style("color", colors.navy);
d3.select(this)
.style("background", colors.navy)
.style("color", colors.white);
updateView();
});
});
// SVG canvas
const svg = container.append("svg")
.attr("viewBox", `0 0 ${width} ${height}`)
.attr("width", "100%")
.style("background", colors.lightGray)
.style("border-radius", "8px")
.style("display", "block");
// Definitions
const defs = svg.append("defs");
// Glow filter for compromised devices
const glowFilter = defs.append("filter")
.attr("id", "compromisedGlow")
.attr("x", "-50%")
.attr("y", "-50%")
.attr("width", "200%")
.attr("height", "200%");
glowFilter.append("feGaussianBlur")
.attr("stdDeviation", "3")
.attr("result", "coloredBlur");
const glowMerge = glowFilter.append("feMerge");
glowMerge.append("feMergeNode").attr("in", "coloredBlur");
glowMerge.append("feMergeNode").attr("in", "SourceGraphic");
// Attack arrow marker
defs.append("marker")
.attr("id", "attackArrow")
.attr("viewBox", "0 0 10 10")
.attr("refX", 9)
.attr("refY", 5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M 0 0 L 10 5 L 0 10 z")
.attr("fill", colors.red);
// Traffic flow marker
defs.append("marker")
.attr("id", "trafficArrow")
.attr("viewBox", "0 0 10 10")
.attr("refX", 9)
.attr("refY", 5)
.attr("markerWidth", 4)
.attr("markerHeight", 4)
.attr("orient", "auto")
.append("path")
.attr("d", "M 0 0 L 10 5 L 0 10 z")
.attr("fill", colors.teal);
// Left panel - Flat Network
const leftPanel = svg.append("g")
.attr("class", "flat-network")
.attr("transform", "translate(0, 0)");
// Right panel - Segmented Network
const rightPanel = svg.append("g")
.attr("class", "segmented-network")
.attr("transform", "translate(450, 0)");
// Panel backgrounds
leftPanel.append("rect")
.attr("x", 10)
.attr("y", 30)
.attr("width", 430)
.attr("height", 480)
.attr("fill", colors.white)
.attr("stroke", colors.gray)
.attr("stroke-width", 2)
.attr("rx", 8);
rightPanel.append("rect")
.attr("x", 10)
.attr("y", 30)
.attr("width", 430)
.attr("height", 480)
.attr("fill", colors.white)
.attr("stroke", colors.gray)
.attr("stroke-width", 2)
.attr("rx", 8);
// Panel titles
leftPanel.append("text")
.attr("x", 225)
.attr("y", 55)
.attr("text-anchor", "middle")
.attr("font-size", "16px")
.attr("font-weight", "bold")
.attr("fill", colors.darkRed)
.text("Flat Network (No Segmentation)");
rightPanel.append("text")
.attr("x", 225)
.attr("y", 55)
.attr("text-anchor", "middle")
.attr("font-size", "16px")
.attr("font-weight", "bold")
.attr("fill", colors.teal)
.text("Segmented Network (VLANs)");
// === LEFT PANEL: Flat Network ===
// Central switch for flat network
leftPanel.append("rect")
.attr("x", 140)
.attr("y", 235)
.attr("width", 80)
.attr("height", 40)
.attr("fill", colors.navy)
.attr("stroke", colors.gray)
.attr("stroke-width", 2)
.attr("rx", 4);
leftPanel.append("text")
.attr("x", 180)
.attr("y", 260)
.attr("text-anchor", "middle")
.attr("font-size", "12px")
.attr("font-weight", "bold")
.attr("fill", colors.white)
.text("SWITCH");
// Connections to switch (all devices connected)
const flatConnections = leftPanel.append("g").attr("class", "flat-connections");
flatDevices.forEach(device => {
flatConnections.append("line")
.attr("x1", device.x + 25)
.attr("y1", device.y + 20)
.attr("x2", 180)
.attr("y2", 255)
.attr("stroke", colors.gray)
.attr("stroke-width", 1)
.attr("stroke-dasharray", "3,3")
.attr("opacity", 0.5);
});
// Draw flat network devices
const flatDeviceGroup = leftPanel.append("g").attr("class", "flat-devices");
function getDeviceColor(type) {
switch(type) {
case "iot": return colors.orange;
case "corp": return colors.teal;
case "guest": return colors.purple;
default: return colors.gray;
}
}
flatDevices.forEach(device => {
const g = flatDeviceGroup.append("g")
.attr("class", `flat-device-${device.id}`)
.attr("transform", `translate(${device.x}, ${device.y})`);
g.append("rect")
.attr("width", 50)
.attr("height", 40)
.attr("rx", 4)
.attr("fill", getDeviceColor(device.type))
.attr("stroke", colors.navy)
.attr("stroke-width", 2);
g.append("text")
.attr("x", 25)
.attr("y", 25)
.attr("text-anchor", "middle")
.attr("font-size", "8px")
.attr("fill", colors.white)
.attr("font-weight", "bold")
.text(device.label);
});
// Attacker for flat network
const flatAttacker = leftPanel.append("g")
.attr("class", "flat-attacker")
.attr("transform", "translate(350, 150)")
.style("opacity", 0);
flatAttacker.append("circle")
.attr("r", 18)
.attr("fill", colors.red)
.attr("stroke", colors.darkRed)
.attr("stroke-width", 2);
flatAttacker.append("text")
.attr("text-anchor", "middle")
.attr("y", 5)
.attr("font-size", "16px")
.attr("font-weight", "bold")
.attr("fill", colors.white)
.text("!");
flatAttacker.append("text")
.attr("text-anchor", "middle")
.attr("y", 35)
.attr("font-size", "10px")
.attr("fill", colors.red)
.attr("font-weight", "bold")
.text("Attacker");
// Attack path visualization for flat network
const flatAttackPath = leftPanel.append("g").attr("class", "flat-attack-path");
// === RIGHT PANEL: Segmented Network ===
// VLAN segments
vlans.forEach(vlan => {
const g = rightPanel.append("g").attr("class", `vlan-${vlan.id}`);
g.append("rect")
.attr("x", 30)
.attr("y", vlan.y)
.attr("width", 280)
.attr("height", vlan.height)
.attr("fill", vlan.color)
.attr("opacity", 0.15)
.attr("stroke", vlan.color)
.attr("stroke-width", 2)
.attr("stroke-dasharray", "5,3")
.attr("rx", 8);
g.append("text")
.attr("x", 40)
.attr("y", vlan.y + 18)
.attr("font-size", "10px")
.attr("font-weight", "bold")
.attr("fill", vlan.color)
.text(vlan.name);
});
// Firewall between VLANs
const firewallGroup = rightPanel.append("g").attr("class", "firewalls");
// Firewall between IoT and Corporate
firewallGroup.append("rect")
.attr("x", 320)
.attr("y", 130)
.attr("width", 80)
.attr("height", 25)
.attr("fill", colors.orange)
.attr("stroke", colors.darkRed)
.attr("stroke-width", 2)
.attr("rx", 4);
firewallGroup.append("text")
.attr("x", 360)
.attr("y", 147)
.attr("text-anchor", "middle")
.attr("font-size", "9px")
.attr("font-weight", "bold")
.attr("fill", colors.white)
.text("FIREWALL");
// Firewall between Corporate and Guest
firewallGroup.append("rect")
.attr("x", 320)
.attr("y", 270)
.attr("width", 80)
.attr("height", 25)
.attr("fill", colors.orange)
.attr("stroke", colors.darkRed)
.attr("stroke-width", 2)
.attr("rx", 4);
firewallGroup.append("text")
.attr("x", 360)
.attr("y", 287)
.attr("text-anchor", "middle")
.attr("font-size", "9px")
.attr("font-weight", "bold")
.attr("fill", colors.white)
.text("FIREWALL");
// Core Router/L3 Switch
rightPanel.append("rect")
.attr("x", 330)
.attr("y", 195)
.attr("width", 60)
.attr("height", 50)
.attr("fill", colors.navy)
.attr("stroke", colors.teal)
.attr("stroke-width", 2)
.attr("rx", 4);
rightPanel.append("text")
.attr("x", 360)
.attr("y", 215)
.attr("text-anchor", "middle")
.attr("font-size", "10px")
.attr("font-weight", "bold")
.attr("fill", colors.white)
.text("L3");
rightPanel.append("text")
.attr("x", 360)
.attr("y", 230)
.attr("text-anchor", "middle")
.attr("font-size", "8px")
.attr("fill", colors.white)
.text("Switch");
// Connections from VLANs to router
const segmentedConnections = rightPanel.append("g").attr("class", "segmented-connections");
// IoT VLAN connection
segmentedConnections.append("line")
.attr("x1", 170)
.attr("y1", 145)
.attr("x2", 330)
.attr("y2", 200)
.attr("stroke", colors.orange)
.attr("stroke-width", 2)
.attr("opacity", 0.5);
// Corp VLAN connection
segmentedConnections.append("line")
.attr("x1", 170)
.attr("y1", 255)
.attr("x2", 330)
.attr("y2", 220)
.attr("stroke", colors.teal)
.attr("stroke-width", 2)
.attr("opacity", 0.5);
// Guest VLAN connection
segmentedConnections.append("line")
.attr("x1", 170)
.attr("y1", 395)
.attr("x2", 330)
.attr("y2", 240)
.attr("stroke", colors.purple)
.attr("stroke-width", 2)
.attr("opacity", 0.5);
// Draw segmented network devices
const segmentedDeviceGroup = rightPanel.append("g").attr("class", "segmented-devices");
Object.entries(segmentedDevices).forEach(([segment, devices]) => {
devices.forEach(device => {
const g = segmentedDeviceGroup.append("g")
.attr("class", `seg-device-${device.id}`)
.attr("transform", `translate(${device.x}, ${device.y})`);
g.append("rect")
.attr("width", 50)
.attr("height", 40)
.attr("rx", 4)
.attr("fill", getDeviceColor(device.type))
.attr("stroke", colors.navy)
.attr("stroke-width", 2);
g.append("text")
.attr("x", 25)
.attr("y", 25)
.attr("text-anchor", "middle")
.attr("font-size", "8px")
.attr("fill", colors.white)
.attr("font-weight", "bold")
.text(device.label);
});
});
// Attacker for segmented network
const segAttacker = rightPanel.append("g")
.attr("class", "seg-attacker")
.attr("transform", "translate(50, 400)")
.style("opacity", 0);
segAttacker.append("circle")
.attr("r", 18)
.attr("fill", colors.red)
.attr("stroke", colors.darkRed)
.attr("stroke-width", 2);
segAttacker.append("text")
.attr("text-anchor", "middle")
.attr("y", 5)
.attr("font-size", "16px")
.attr("font-weight", "bold")
.attr("fill", colors.white)
.text("!");
segAttacker.append("text")
.attr("text-anchor", "middle")
.attr("y", 35)
.attr("font-size", "10px")
.attr("fill", colors.red)
.attr("font-weight", "bold")
.text("Attacker");
// Attack path visualization for segmented network
const segAttackPath = rightPanel.append("g").attr("class", "seg-attack-path");
// Blocked indicators group
const blockedGroup = rightPanel.append("g").attr("class", "blocked-indicators");
// === METRICS PANEL ===
const metricsPanel = svg.append("g")
.attr("class", "metrics-panel")
.attr("transform", `translate(10, 520)`);
metricsPanel.append("rect")
.attr("width", width - 20)
.attr("height", 90)
.attr("fill", colors.navy)
.attr("rx", 8)
.attr("opacity", 0.95);
metricsPanel.append("text")
.attr("x", 20)
.attr("y", 25)
.attr("font-size", "14px")
.attr("font-weight", "bold")
.attr("fill", colors.white)
.text("Security Metrics");
// Flat network metrics
const flatMetrics = metricsPanel.append("g")
.attr("transform", "translate(20, 45)");
flatMetrics.append("text")
.attr("font-size", "11px")
.attr("fill", colors.lightGray)
.text("Flat Network:");
flatMetrics.append("text")
.attr("x", 90)
.attr("font-size", "11px")
.attr("fill", colors.red)
.attr("class", "flat-compromised-text")
.text("Compromised: 0/9");
flatMetrics.append("text")
.attr("x", 210)
.attr("font-size", "11px")
.attr("fill", colors.red)
.attr("class", "flat-status-text")
.text("Status: Secure");
// Segmented network metrics
const segMetrics = metricsPanel.append("g")
.attr("transform", "translate(20, 70)");
segMetrics.append("text")
.attr("font-size", "11px")
.attr("fill", colors.lightGray)
.text("Segmented:");
segMetrics.append("text")
.attr("x", 90)
.attr("font-size", "11px")
.attr("fill", colors.green)
.attr("class", "seg-compromised-text")
.text("Compromised: 0/9");
segMetrics.append("text")
.attr("x", 210)
.attr("font-size", "11px")
.attr("fill", colors.green)
.attr("class", "seg-status-text")
.text("Status: Secure");
segMetrics.append("text")
.attr("x", 340)
.attr("font-size", "11px")
.attr("fill", colors.orange)
.attr("class", "blocked-text")
.text("Blocked Attempts: 0");
// Traffic indicators
const trafficLegend = metricsPanel.append("g")
.attr("transform", `translate(${width - 280}, 45)`);
trafficLegend.append("text")
.attr("font-size", "11px")
.attr("fill", colors.lightGray)
.text("Traffic Indicators:");
// Normal traffic
trafficLegend.append("line")
.attr("x1", 120)
.attr("y1", -3)
.attr("x2", 150)
.attr("y2", -3)
.attr("stroke", colors.teal)
.attr("stroke-width", 2)
.attr("marker-end", "url(#trafficArrow)");
trafficLegend.append("text")
.attr("x", 155)
.attr("font-size", "9px")
.attr("fill", colors.teal)
.text("Normal");
// Attack traffic
trafficLegend.append("line")
.attr("x1", 120)
.attr("y1", 17)
.attr("x2", 150)
.attr("y2", 17)
.attr("stroke", colors.red)
.attr("stroke-width", 2)
.attr("marker-end", "url(#attackArrow)");
trafficLegend.append("text")
.attr("x", 155)
.attr("font-size", "9px")
.attr("fill", colors.red)
.text("Attack");
// Blocked
trafficLegend.append("circle")
.attr("cx", 135)
.attr("cy", 37)
.attr("r", 8)
.attr("fill", "none")
.attr("stroke", colors.red)
.attr("stroke-width", 2);
trafficLegend.append("line")
.attr("x1", 128)
.attr("y1", 30)
.attr("x2", 142)
.attr("y2", 44)
.attr("stroke", colors.red)
.attr("stroke-width", 2);
trafficLegend.append("text")
.attr("x", 155)
.attr("y", 40)
.attr("font-size", "9px")
.attr("fill", colors.orange)
.text("Blocked");
// === ANIMATION FUNCTIONS ===
function updateMetrics() {
metricsPanel.select(".flat-compromised-text")
.text(`Compromised: ${flatCompromisedCount}/9`)
.attr("fill", flatCompromisedCount > 0 ? colors.red : colors.green);
metricsPanel.select(".flat-status-text")
.text(`Status: ${flatCompromisedCount === 0 ? "Secure" : (flatCompromisedCount < 9 ? "Breached" : "FULLY COMPROMISED")}`)
.attr("fill", flatCompromisedCount === 0 ? colors.green : colors.red);
metricsPanel.select(".seg-compromised-text")
.text(`Compromised: ${segmentedCompromisedCount}/9`)
.attr("fill", segmentedCompromisedCount > 0 ? colors.orange : colors.green);
metricsPanel.select(".seg-status-text")
.text(`Status: ${segmentedCompromisedCount === 0 ? "Secure" : "Contained to 1 VLAN"}`)
.attr("fill", segmentedCompromisedCount === 0 ? colors.green : colors.orange);
metricsPanel.select(".blocked-text")
.text(`Blocked Attempts: ${blockedAttempts}`);
}
function compromiseDevice(panel, deviceClass, delay) {
setTimeout(() => {
const device = panel.select(`.${deviceClass}`);
device.select("rect")
.transition()
.duration(300)
.attr("fill", colors.red)
.attr("stroke", colors.darkRed)
.attr("filter", "url(#compromisedGlow)");
}, delay);
}
function showAttackPath(panel, x1, y1, x2, y2, delay) {
setTimeout(() => {
const pathGroup = panel.select(panel === leftPanel ? ".flat-attack-path" : ".seg-attack-path");
// Create attack line
const line = pathGroup.append("line")
.attr("x1", x1)
.attr("y1", y1)
.attr("x2", x1)
.attr("y2", y1)
.attr("stroke", colors.red)
.attr("stroke-width", 2)
.attr("marker-end", "url(#attackArrow)");
line.transition()
.duration(400)
.attr("x2", x2)
.attr("y2", y2);
// Animate attack packet
const packet = pathGroup.append("circle")
.attr("cx", x1)
.attr("cy", y1)
.attr("r", 5)
.attr("fill", colors.red);
packet.transition()
.duration(400)
.attr("cx", x2)
.attr("cy", y2)
.on("end", () => packet.remove());
}, delay);
}
function showBlockedAttempt(x, y, delay) {
setTimeout(() => {
blockedAttempts++;
updateMetrics();
const blocked = blockedGroup.append("g")
.attr("transform", `translate(${x}, ${y})`)
.style("opacity", 0);
blocked.append("circle")
.attr("r", 15)
.attr("fill", "none")
.attr("stroke", colors.red)
.attr("stroke-width", 3);
blocked.append("line")
.attr("x1", -10)
.attr("y1", -10)
.attr("x2", 10)
.attr("y2", 10)
.attr("stroke", colors.red)
.attr("stroke-width", 3);
blocked.append("text")
.attr("y", 28)
.attr("text-anchor", "middle")
.attr("font-size", "8px")
.attr("font-weight", "bold")
.attr("fill", colors.red)
.text("BLOCKED");
blocked.transition()
.duration(200)
.style("opacity", 1);
// Fade out after a bit
setTimeout(() => {
blocked.transition()
.duration(500)
.style("opacity", 0.5);
}, 2000);
}, delay);
}
function runFlatNetworkAttack() {
// Show attacker
flatAttacker.transition().duration(500).style("opacity", 1);
// Phase 1: Initial compromise (Guest device)
setTimeout(() => {
flatCompromisedCount = 1;
updateMetrics();
compromiseDevice(leftPanel, "flat-device-f7", 0);
showAttackPath(leftPanel, 350, 150, 105, 380, 0);
}, 1000);
// Phase 2: Lateral movement to all devices (flat = no barriers)
const attackSequence = [
{ device: "f8", x: 105, y: 380, tx: 185, ty: 430 },
{ device: "f9", x: 185, y: 430, tx: 265, ty: 380 },
{ device: "f4", x: 265, y: 380, tx: 105, ty: 260 },
{ device: "f5", x: 105, y: 260, tx: 185, ty: 310 },
{ device: "f6", x: 185, y: 310, tx: 265, ty: 260 },
{ device: "f1", x: 265, y: 260, tx: 105, ty: 160 },
{ device: "f2", x: 105, y: 160, tx: 185, ty: 110 },
{ device: "f3", x: 185, y: 110, tx: 265, ty: 160 }
];
attackSequence.forEach((attack, i) => {
setTimeout(() => {
flatCompromisedCount = i + 2;
updateMetrics();
compromiseDevice(leftPanel, `flat-device-${attack.device}`, 0);
showAttackPath(leftPanel, attack.x, attack.y, attack.tx, attack.ty, 0);
}, 2000 + i * 600);
});
}
function runSegmentedNetworkAttack() {
// Show attacker
segAttacker.transition().duration(500).style("opacity", 1);
// Phase 1: Initial compromise (Guest device in Guest VLAN)
setTimeout(() => {
segmentedCompromisedCount = 1;
updateMetrics();
const guestDevices = segmentedDevices.guest;
compromiseDevice(rightPanel, `seg-device-${guestDevices[0].id}`, 0);
showAttackPath(rightPanel, 50, 400, guestDevices[0].x + 25, guestDevices[0].y + 20, 0);
}, 1000);
// Phase 2: Spread within Guest VLAN only
setTimeout(() => {
segmentedCompromisedCount = 2;
updateMetrics();
compromiseDevice(rightPanel, "seg-device-s8", 0);
showAttackPath(rightPanel, 105, 410, 185, 370, 0);
}, 2000);
setTimeout(() => {
segmentedCompromisedCount = 3;
updateMetrics();
compromiseDevice(rightPanel, "seg-device-s9", 0);
showAttackPath(rightPanel, 185, 370, 265, 410, 0);
}, 2600);
// Phase 3: Attempt to reach Corporate VLAN - BLOCKED!
setTimeout(() => {
showBlockedAttempt(360, 283, 0);
showAttackPath(rightPanel, 185, 370, 330, 283, 0);
}, 3500);
// Phase 4: Another attempt to reach IoT VLAN - BLOCKED!
setTimeout(() => {
showBlockedAttempt(360, 143, 0);
}, 4500);
// Phase 5: Try direct access to Corporate - BLOCKED!
setTimeout(() => {
showBlockedAttempt(300, 255, 0);
}, 5500);
}
function startAttack() {
if (isAttacking) return;
isAttacking = true;
attackBtn.text("Attacking...");
// Run both attacks simultaneously
runFlatNetworkAttack();
runSegmentedNetworkAttack();
// End attack phase
attackTimer = setTimeout(() => {
isAttacking = false;
attackBtn.text("Launch Attack");
}, 8000);
}
function reset() {
if (attackTimer) {
clearTimeout(attackTimer);
attackTimer = null;
}
isAttacking = false;
attackBtn.text("Launch Attack");
// Reset counters
flatCompromisedCount = 0;
segmentedCompromisedCount = 0;
blockedAttempts = 0;
updateMetrics();
// Reset flat network devices
flatDevices.forEach(device => {
device.compromised = false;
leftPanel.select(`.flat-device-${device.id} rect`)
.attr("fill", getDeviceColor(device.type))
.attr("stroke", colors.navy)
.attr("filter", null);
});
// Reset segmented network devices
Object.values(segmentedDevices).flat().forEach(device => {
device.compromised = false;
rightPanel.select(`.seg-device-${device.id} rect`)
.attr("fill", getDeviceColor(device.type))
.attr("stroke", colors.navy)
.attr("filter", null);
});
// Clear attack paths
leftPanel.select(".flat-attack-path").selectAll("*").remove();
rightPanel.select(".seg-attack-path").selectAll("*").remove();
// Clear blocked indicators
blockedGroup.selectAll("*").remove();
// Hide attackers
flatAttacker.style("opacity", 0);
segAttacker.style("opacity", 0);
}
function updateView() {
switch(currentView) {
case "both":
leftPanel.style("display", "block").attr("transform", "translate(0, 0)");
rightPanel.style("display", "block").attr("transform", "translate(450, 0)");
break;
case "flat":
leftPanel.style("display", "block").attr("transform", "translate(225, 0)");
rightPanel.style("display", "none");
break;
case "segmented":
leftPanel.style("display", "none");
rightPanel.style("display", "block").attr("transform", "translate(225, 0)");
break;
}
}
// Event handlers
attackBtn.on("click", startAttack);
resetBtn.on("click", reset);
// Initialize metrics
updateMetrics();
// Legend
const legend = container.append("div")
.style("display", "flex")
.style("justify-content", "center")
.style("gap", "20px")
.style("margin-top", "15px")
.style("flex-wrap", "wrap")
.style("font-size", "12px");
const legendItems = [
{ color: colors.orange, label: "IoT Devices" },
{ color: colors.teal, label: "Corporate" },
{ color: colors.purple, label: "Guest" },
{ color: colors.red, label: "Compromised" },
{ color: colors.orange, border: true, label: "Firewall" }
];
legendItems.forEach(item => {
const legendItem = legend.append("div")
.style("display", "flex")
.style("align-items", "center")
.style("gap", "5px");
legendItem.append("div")
.style("width", "14px")
.style("height", "14px")
.style("background", item.color)
.style("border-radius", "3px")
.style("border", item.border ? `2px solid ${colors.darkRed}` : "none");
legendItem.append("span")
.style("color", colors.navy)
.text(item.label);
});
// Key insights
const insights = container.append("div")
.style("margin-top", "20px")
.style("padding", "15px")
.style("background", colors.lightGray)
.style("border-radius", "8px")
.style("border-left", `4px solid ${colors.teal}`);
insights.append("div")
.style("font-weight", "bold")
.style("color", colors.navy)
.style("margin-bottom", "8px")
.text("Key Takeaways:");
const insightsList = insights.append("ul")
.style("margin", "0")
.style("padding-left", "20px")
.style("font-size", "13px")
.style("color", colors.navy);
[
"Flat networks allow attackers to move laterally to ANY device after initial compromise",
"VLAN segmentation isolates device groups, containing breaches to a single segment",
"Firewalls between VLANs enforce access control policies and block unauthorized traffic",
"IoT devices should be on separate VLANs from critical corporate systems",
"Proper segmentation reduces breach impact from 100% to just 33% of network (1 of 3 VLANs)"
].forEach(text => {
insightsList.append("li")
.style("margin-bottom", "4px")
.text(text);
});
return container.node();
}1463.2 Understanding Network Segmentation
The animation above demonstrates the critical difference between flat and segmented network architectures:
1463.2.1 Flat Network Problems
In a flat network, all devices share the same broadcast domain and can communicate freely:
- No isolation: IoT devices, workstations, servers, and guests all on same network
- Unrestricted lateral movement: Once an attacker compromises one device, they can reach all others
- Large attack surface: Every device is a potential pivot point
- No containment: A single breach can escalate to full network compromise
1463.2.2 VLAN Segmentation Benefits
VLANs (Virtual Local Area Networks) create logical separation between device groups:
| VLAN | Purpose | Devices | Security Level |
|---|---|---|---|
| VLAN 10 | IoT | Sensors, cameras, thermostats | Isolated, limited internet |
| VLAN 20 | Corporate | Workstations, file servers, databases | High security, monitored |
| VLAN 30 | Guest | Visitor devices, public Wi-Fi | Internet only, no internal access |
1463.2.3 Firewall Rules Between VLANs
The firewalls between VLANs enforce access control policies:
# Example firewall rules between VLANs
VLAN 10 (IoT) -> VLAN 20 (Corporate): DENY ALL
VLAN 30 (Guest) -> VLAN 20 (Corporate): DENY ALL
VLAN 30 (Guest) -> VLAN 10 (IoT): DENY ALL
VLAN 20 (Corporate) -> VLAN 10 (IoT): ALLOW specific management ports only
1463.3 IoT-Specific Segmentation Strategies
For IoT deployments, network segmentation is essential:
1463.3.1 1. Isolate IoT from Critical Systems
IoT devices often have: - Limited security capabilities - Infrequent firmware updates - Default or weak credentials - Known vulnerabilities
Keeping them on separate VLANs prevents compromised IoT devices from accessing sensitive corporate data.
1463.3.2 2. Micro-Segmentation
For high-security environments, consider further segmentation:
| Segment | Devices | Access Policy |
|---|---|---|
| IoT-Cameras | IP cameras only | Stream to NVR only |
| IoT-HVAC | HVAC controllers | Building management only |
| IoT-Sensors | Environmental sensors | Data collection server only |
1463.3.3 3. Zero Trust + Segmentation
Combine network segmentation with Zero Trust principles:
- Segment by function: Group devices by their role
- Verify every request: Authenticate even within segments
- Least privilege: Only allow necessary communications
- Monitor all traffic: Log and analyze inter-VLAN traffic
1463.4 Implementation Checklist
1463.5 What’s Next
Explore related security topics:
- IoT Security Threats - Understanding the threat landscape
- Zero Trust Architecture - Never trust, always verify
- Network Security Protocols - Securing communications
- Access Control - Managing device access
- Simulations Hub - More interactive security visualizations
This animation demonstrates network segmentation defense with:
- Side-by-side comparison: Flat vs segmented network architectures
- Attack simulation: Visual representation of lateral movement
- VLAN visualization: Color-coded segments with firewall barriers
- Blocked indicators: Shows firewall denying cross-VLAN traffic
- Real-time metrics: Compromised device counts and blocked attempts
- IEEE color palette: Orange for IoT, Teal for Corporate, Purple for Guest
Educational simplifications:
- Simplified VLAN topology (3 VLANs instead of more complex real-world designs)
- Instant compromise for visual clarity (real attacks take longer)
- Firewalls shown as discrete boxes (often integrated into L3 switches)
- Attack paths shown as direct lines (real lateral movement is more complex)
In production environments, additional controls like IDS/IPS, NAC, and microsegmentation provide deeper defense.