demo · v141

Network Topology Explorer

Local Network Access restrictions divide the web into three address spaces — public, private, and loopback — and block public websites from reaching the lower two without an explicit permission grant. Explore the address space taxonomy, classify any IP address, and understand which source→target combinations Chrome 141 allows, prompts for, or outright blocks.

The three address spaces

Public (internet)

Any IP not in a reserved range. Normal web traffic. No restrictions imposed by LNA on requests within this space.

93.184.216.34 (example.com) 8.8.8.8 (Google DNS) 2606:2800::1 (IPv6)
Private (local network)

RFC 1918 ranges and other local-network blocks. Routers, printers, smart TVs, NAS units live here. LNA gates public-to-private requests.

10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 fc00::/7 (IPv6 ULA)
Loopback (localhost)

The host itself. Dev servers, local tooling. LNA treats this as even more sensitive than private — public-to-loopback is blocked in most cases.

127.0.0.0/8 ::1/128 (IPv6)

IP address classifier

Enter an IP address above and click Classify.

Source → target permission matrix

Source \ Target Public Private Loopback
Public origin allowed blocked* blocked*
Private origin allowed allowed blocked*
Loopback origin allowed allowed allowed

* "blocked" means Chrome sends a CORS preflight requesting Access-Control-Allow-Private-Network: true. Without it the request fails.

Simulate a blocked cross-space fetch

This simulates what a public website experiences trying to fetch http://192.168.1.1/ — Chrome blocks it at the network layer (or sends a preflight that the device won't answer). The fetch below will always fail in a public context.
No simulation run yet.

headers a compliant IoT device must serve

# The device at 192.168.1.100 must answer the LNA preflight:
HTTP/1.1 200 OK
Access-Control-Allow-Origin:          https://app.example
Access-Control-Allow-Private-Network: true          ← the key header
Access-Control-Allow-Methods:         GET, POST
Access-Control-Allow-Headers:         Content-Type
Vary:                                 Origin

# Chrome sends the OPTIONS preflight with:
Access-Control-Request-Private-Network: true
# The device MUST echo back Access-Control-Allow-Private-Network: true
# or Chrome cancels the actual request before it leaves the browser.

a compliant Node.js / Deno device server

// Handles the LNA preflight then the actual request
Deno.serve({ port: 8080 }, (req) => {
  const origin = req.headers.get("origin") ?? "";
  const corsHeaders = {
    "Access-Control-Allow-Origin":          origin,
    "Access-Control-Allow-Private-Network": "true",
    "Access-Control-Allow-Methods":         "GET, POST, OPTIONS",
    "Access-Control-Allow-Headers":         "Content-Type",
    "Vary":                                 "Origin",
  };

  if (req.method === "OPTIONS") {
    // respond to LNA preflight immediately
    return new Response(null, { status: 204, headers: corsHeaders });
  }

  return new Response(
    JSON.stringify({ device: "smart-plug-001", state: "on" }),
    { headers: { ...corsHeaders, "Content-Type": "application/json" } }
  );
});

see also