cheat sheet

route

Display, add, delete, and modify entries in the Windows IP routing table — control how packets are forwarded between subnets, add persistent static routes, and diagnose routing failures.

route — IP Routing Table Manager

What it is

route is a built-in Windows command that reads and manipulates the kernel IP routing table — the data structure that determines which network interface and next-hop gateway the OS uses to forward each outgoing packet. Use it to add a static route to a specific subnet via a non-default gateway, remove a conflicting route, or inspect the full routing table when ping reaches the wrong path. The PowerShell equivalent is Get-NetRoute / New-NetRoute / Remove-NetRoute. netsh interface ipv4 add route is the alternative for persistent routes with interface-index targeting.

Availability

route ships as C:\Windows\System32\route.exe on all Windows versions. Adding and deleting routes requires Administrator privileges.

cmd
route /?

Output:

css
Manipulates network routing tables.

ROUTE [-f] [-p] [-4|-6] command [destination]
                  [MASK netmask]  [gateway] [METRIC metric]  [IF interface]

  -f           Clears the routing tables of all gateway entries.
  -p           When used with the ADD command, makes a route persistent
               across boots of the system.
  -4           Force using IPv4.
  -6           Force using IPv6.
  command      One of these:
               PRINT   Prints  a route
               ADD     Adds    a route
               DELETE  Deletes a route
               CHANGE  Modifies an existing route
  destination  Specifies the host.
  MASK         Specifies that the next parameter is the 'netmask' value.
  netmask      Specifies a subnet mask value for this route entry.
  gateway      Specifies gateway.
  IF           Specifies the interface number for the specified route.
  METRIC       Specifies the metric, e.g. cost for the destination.

Syntax

cmd
route [-f] [-p] [-4|-6] PRINT|ADD|DELETE|CHANGE [destination] [MASK netmask] [gateway] [METRIC metric] [IF interface]

Output: (varies by sub-command)

Essential options

SwitchMeaning
PRINTDisplay the routing table (or a filtered subset)
ADDAdd a new route
DELETEDelete a route
CHANGEModify an existing route's gateway or metric
-pMake the added route persistent (survives reboots)
-fFlush all gateway routes before executing the command
MASK <netmask>Subnet mask for the destination; defaults to host route (255.255.255.255)
METRIC <n>Route cost — lower metric wins when multiple routes match
IF <interface>Bind the route to a specific interface index

Printing the routing table

route PRINT displays the full routing table including the interface list, IPv4 routes, and IPv6 routes. The most important columns are Destination, Netmask, Gateway, Interface, and Metric.

cmd
route PRINT

Output:

markdown
===========================================================================
Interface List
  4...00 1a 2b 3c 4d 5e ......Intel(R) Ethernet Connection
  7...00 5e ab cd ef 01 ......Microsoft Wi-Fi Direct Virtual Adapter
===========================================================================

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0      192.168.1.1   192.168.1.100     25
        127.0.0.0        255.0.0.0         On-link       127.0.0.1    331
      192.168.1.0    255.255.255.0         On-link   192.168.1.100    281
    192.168.1.100  255.255.255.255         On-link   192.168.1.100    281
===========================================================================

Filtering the table by destination

Passing a destination pattern to PRINT restricts output to matching routes, making it easy to check whether a specific network is routed correctly.

cmd
route PRINT 10.*

Output:

markdown
===========================================================================
IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
         10.0.0.0      255.0.0.0      10.0.0.1    10.0.0.50     25
===========================================================================

Adding a static route

ADD inserts a new entry. Without -p the route is in-memory only and is lost on reboot. Always specify MASK for subnet routes; omitting it creates a host route (/32).

cmd
rem Route 10.10.0.0/16 through a secondary gateway
route ADD 10.10.0.0 MASK 255.255.0.0 192.168.1.254 METRIC 10

Output:

code
 OK!

Verify the new route:

cmd
route PRINT 10.10.*

Output:

graphql
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
        10.10.0.0      255.255.0.0    192.168.1.254  192.168.1.100     10

Adding a persistent route

-p writes the route to the registry so it is restored at every boot. Use this for production servers where a secondary subnet must always be reachable without manual re-entry after a reboot.

cmd
route -p ADD 172.16.0.0 MASK 255.255.0.0 192.168.1.254

Output:

code
 OK!

Persistent routes appear in the PRINT output under the Persistent Routes section in addition to the Active Routes section.

Deleting a route

DELETE removes a route by destination (and optionally mask). If multiple routes share the same destination, specify the mask to disambiguate.

cmd
route DELETE 10.10.0.0 MASK 255.255.0.0

Output:

code
 OK!
cmd
rem Delete all routes to a host
route DELETE 192.168.99.50

Output:

code
 OK!

Changing a route

CHANGE updates the gateway or metric of an existing route without deleting and re-adding it. Only the gateway and metric can be changed — the destination and mask identify the entry.

cmd
route CHANGE 172.16.0.0 MASK 255.255.0.0 GATEWAY 192.168.1.1 METRIC 20

Output:

code
 OK!

Binding a route to a specific interface

On multi-homed machines (multiple NICs), use IF <index> to pin the route to the correct adapter. Get interface indexes from route PRINT (the Interface List at the top) or netsh interface ip show interfaces.

cmd
route ADD 10.20.0.0 MASK 255.255.0.0 10.20.0.1 IF 4

Output:

code
 OK!

Route metrics explained

The metric is a 32-bit integer that controls which route wins when multiple match the same destination. Lower metrics are preferred. Windows computes an "interface metric" automatically based on the link speed (faster = lower) and adds it to the per-route metric you specify. The total displayed in route PRINT is route_metric + interface_metric.

Link typeDefault interface metric
Loopback75
10 Gigabit Ethernet5
1 Gigabit Ethernet10
100 Mb Ethernet35
WiFi (802.11)50
Mobile broadband70

To override the automatic computation and pin an interface metric, use netsh or PowerShell:

cmd
netsh interface ipv4 set interface "Ethernet" metric=5

Output:

rust
Ok.
powershell
Set-NetIPInterface -InterfaceAlias "Ethernet" -InterfaceMetric 5 -AutomaticMetric Disabled

When two paths match (e.g. dual-homed laptop with WiFi + Ethernet both having default routes), lower-metric interface wins. Reversing the priority just means swapping the metric values.

Routing decision algorithm

Windows uses longest-prefix match: among all matching routes, the one with the longest netmask wins. If two routes share the same prefix length, the lower metric wins. If both are equal, Windows chooses ECMP (Equal-Cost Multi-Path) and load-balances per-flow.

For a packet destined to 93.184.216.34, the kernel walks the routing table looking for the most specific match:

  1. Exact host route 93.184.216.34/32 — most specific
  2. Route 93.184.216.0/24
  3. Route 93.184.0.0/16
  4. Default route 0.0.0.0/0 — least specific, always last

The most-specific match wins; metric ties are broken by ECMP. Use Find-NetRoute (PowerShell) to ask the OS exactly which route would be picked for a given destination:

powershell
Find-NetRoute -RemoteIPAddress 8.8.8.8

Output:

yaml
IPAddress         : 192.168.1.100
InterfaceIndex    : 12
InterfaceAlias    : Ethernet
AddressFamily     : IPv4
...

DestinationPrefix : 0.0.0.0/0
NextHop           : 192.168.1.1
RouteMetric       : 0
ifIndex           : 12

This is the single best diagnostic for "why is traffic going out the wrong interface" — it tells you exactly which route the kernel chose without ambiguity.

PowerShell equivalents

The NetTCPIP PowerShell module provides typed, scriptable replacements for route. Output is objects rather than text, which is far easier to filter and pipeline.

powershell
# View all routes (equivalent to `route PRINT`)
Get-NetRoute -AddressFamily IPv4

# Filter to default routes only
Get-NetRoute -DestinationPrefix '0.0.0.0/0'

# Filter by interface
Get-NetRoute -InterfaceAlias "Ethernet"

# Add a new persistent route (equivalent to `route -p ADD`)
New-NetRoute -DestinationPrefix '10.10.0.0/16' -InterfaceAlias 'Ethernet' `
    -NextHop 192.168.1.254 -RouteMetric 10 -PolicyStore PersistentStore

# Remove a route (equivalent to `route DELETE`)
Remove-NetRoute -DestinationPrefix '10.10.0.0/16' -Confirm:$false

# Change a route's gateway by removing + recreating
Get-NetRoute -DestinationPrefix '172.16.0.0/16' | Remove-NetRoute -Confirm:$false
New-NetRoute -DestinationPrefix '172.16.0.0/16' -InterfaceAlias 'Ethernet' `
    -NextHop 192.168.1.1 -RouteMetric 20

Output:

diff
ifIndex DestinationPrefix  NextHop       RouteMetric  ifMetric  PolicyStore
------- -----------------  -------       -----------  --------  -----------
12      10.10.0.0/16       192.168.1.254          10        25  PersistentStore

PolicyStore PersistentStore is the modern equivalent of route -p; without it, the route is in ActiveStore (memory-only).

netsh routing commands

netsh interface ipv4 exposes a different command family that overlaps with route but offers interface-name targeting and is preferred for scripting around named adapters (which are stable across reboots, unlike interface indexes).

cmd
rem List all routes via netsh
netsh interface ipv4 show route

rem Add a persistent route via netsh — interface by name
netsh interface ipv4 add route prefix=10.10.0.0/16 interface="Ethernet" nexthop=192.168.1.254 metric=10 store=persistent

rem Delete a route
netsh interface ipv4 delete route prefix=10.10.0.0/16 interface="Ethernet"

Output:

rust
Ok.

Use netsh when scripting against adapter friendly names ("Ethernet", "WiFi") is more maintainable than interface indexes; use route when you want a single-line command across all interfaces.

Persistent route storage

route -p and New-NetRoute -PolicyStore PersistentStore write the route to the registry path:

sql
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\PersistentRoutes

Each entry is a value named with the route specification (e.g. 10.10.0.0,255.255.0.0,192.168.1.254,10). Inspect or back up the key directly:

powershell
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\PersistentRoutes'

Output:

yaml
PSPath        : ...PersistentRoutes
10.10.0.0,255.255.0.0,192.168.1.254,10 :
172.16.0.0,255.240.0.0,192.168.1.254,1 :

If the registry key contains an invalid route (e.g. gateway no longer on any subnet), Windows logs an error in the System event log at boot and skips the entry.

Routing tables on multi-homed hosts

When a machine has multiple NICs (Ethernet + WiFi, Ethernet + VPN, dual-NIC server), routing decisions become non-trivial. Three concepts matter:

  1. Default route per interface — each NIC's DHCP-assigned default route exists in the table; Windows picks the one with the lowest combined metric.
  2. Strong host model — Windows by default uses the weak host model (a packet can leave any interface regardless of source IP); enable strong host model with netsh interface ipv4 set interface "Ethernet" weakhostsend=disabled weakhostreceive=disabled.
  3. Per-VPN split-tunnel routes — VPN clients install /32 or /16 routes via the VPN gateway with low metrics; the rest stays on the default interface.
powershell
# Set interface to strong-host (rejects packets arriving on the wrong NIC)
Set-NetIPInterface -InterfaceAlias "Ethernet" `
    -WeakHostSend Disabled -WeakHostReceive Disabled

To audit which interface a destination uses across all routes, walk the destinations:

powershell
'8.8.8.8','10.10.0.5','172.16.5.10' | ForEach-Object {
    $r = Find-NetRoute -RemoteIPAddress $_ | Select-Object -First 1
    [PSCustomObject]@{Dest=$_; Via=$r.NextHop; Interface=$r.InterfaceAlias}
}

Output:

arduino
Dest        Via             Interface
----        ---             ---------
8.8.8.8     192.168.1.1     Ethernet
10.10.0.5   192.168.1.254   Ethernet
172.16.5.10 10.8.0.1        VPN

IPv6 routing

The route command accepts -6 for IPv6 routes, but netsh interface ipv6 and PowerShell Get-NetRoute -AddressFamily IPv6 are more idiomatic. IPv6 has fundamentally the same model but uses prefix-length notation and link-local scope IDs.

cmd
rem List IPv6 routes
route -6 PRINT

rem Add a persistent IPv6 default route
route -6 -p ADD ::/0 fe80::1%12 METRIC 100

Output:

ruby
===========================================================================
Active Routes:
 If Metric Network Destination      Gateway
 12     25 ::/0                     fe80::1%12
 12    256 fe80::/64                On-link
...
powershell
Get-NetRoute -AddressFamily IPv6 |
    Where-Object DestinationPrefix -ne '::/0' |
    Sort-Object InterfaceIndex

Route flapping and ECMP

When two routes share the same destination prefix AND the same metric, Windows enables ECMP — each new connection picks one route via per-flow hashing. Existing connections stay on their original route. This is invisible in route PRINT (both entries appear normally) but can cause subtle issues:

  • Asymmetric forward/reverse paths
  • Pathping seeing inconsistent hop sets
  • Stateful firewalls between paths dropping flows

To force a single route to win, give it a lower metric:

cmd
route CHANGE 10.0.0.0 MASK 255.0.0.0 192.168.1.1 METRIC 5
route CHANGE 10.0.0.0 MASK 255.0.0.0 192.168.1.2 METRIC 10

Output:

code
 OK!
 OK!

Now traffic to 10.0.0.0/8 always uses the 192.168.1.1 next-hop.

Auditing the routing table

Periodic snapshots of the routing table catch unauthorised changes (malware, misbehaving VPN clients, accidental persistent routes) and provide a baseline for incident response.

powershell
$baseline = "C:\Audit\routes_$($env:COMPUTERNAME)_$(Get-Date -Format yyyy-MM-dd).csv"
Get-NetRoute -AddressFamily IPv4 |
    Where-Object {$_.PolicyStore -eq 'PersistentStore' -or $_.DestinationPrefix -eq '0.0.0.0/0'} |
    Select-Object DestinationPrefix, NextHop, RouteMetric, InterfaceAlias, PolicyStore |
    Export-Csv -NoTypeInformation $baseline

Output:

css
(none — writes CSV)

Compare two snapshots with Compare-Object or fc.

Common pitfalls

  1. Non-persistent routes vanish on reboot — always use -p (or New-NetRoute -PolicyStore PersistentStore) for routes that must survive a restart; non-persistent routes are memory-only.
  2. Wrong gateway for the interface — the gateway must be reachable directly (on the same subnet as the interface IP); an unreachable gateway produces The route addition failed: The parameter is incorrect.
  3. Conflicting metrics — if two routes match the same destination, the lower metric wins; check existing routes with route PRINT before adding to avoid silent metric ties.
  4. -f flushes all gateway routes firstroute -f ADD ... deletes everything except loopback and on-link routes before adding the new entry; rarely what you want.
  5. IPv6 requires -6route PRINT shows both IPv4 and IPv6 by default, but ADD/DELETE/CHANGE default to IPv4; use -6 explicitly for IPv6 static routes.
  6. Interface index changes after driver reinstallIF <idx> in a persistent route can break if the NIC driver is reinstalled and gets a new index; prefer adapter-name based commands in PowerShell or netsh.
  7. Auto-computed interface metric overrides expectationroute -p ADD ... METRIC 10 may end up displayed as 35 because Windows adds the interface metric (25 for Ethernet); subtract the interface metric to predict the displayed value.
  8. route DELETE without MASK deletes the first match — multiple routes to the same destination at different prefix lengths require an explicit MASK; otherwise only one entry is removed.
  9. Strong-host vs weak-host model — by default a Windows machine accepts packets on any interface as long as the destination IP is local; this can confuse multi-homed routing.
  10. Routes with metric 0 are still less preferred than metric 1 — Windows treats them all as numeric values; metric 0 is not "first" magic.
  11. route -p writes to the registry but doesn't validate — invalid persistent routes silently fail at next boot and only show up in the System event log.
  12. VPN clients commonly install bad routes — Cisco AnyConnect, OpenVPN, and others can leave orphan persistent routes after disconnect; audit route PRINT after VPN disconnections.
  13. route ADD on RAS interfaces fails — dial-up and PPP interfaces require the route to be added after the link is up; use rasdial connection scripts or persistent routes that re-apply on link establishment.
  14. The On-link gateway is not a real IP — it means "the destination is on this subnet, no gateway needed"; you cannot use it explicitly in ADD.

Real-world recipes

Add a VPN split route

Send only traffic destined for the corporate 10.0.0.0/8 range through the VPN gateway, leaving all other traffic on the default route.

cmd
route -p ADD 10.0.0.0 MASK 255.0.0.0 10.8.0.1 METRIC 5

Output:

code
 OK!

Check why traffic takes the wrong path

Print all routes and look for the most specific match that applies to the destination.

cmd
route PRINT 192.168.*

Output:

graphql
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
      192.168.0.0    255.255.0.0         On-link   192.168.1.100    281
      192.168.5.0  255.255.255.0     192.168.1.1   192.168.1.100     15

Remove all manually added static routes

Flush only gateway entries (default routes and explicit next-hop routes) while leaving on-link and loopback routes intact.

cmd
route -f

Output:

css
(none — flushes gateway routes and returns to prompt)

Script: persist routes for a lab network

cmd
@echo off
set GW=192.168.1.254
route -p ADD 10.0.0.0   MASK 255.0.0.0   %GW%
route -p ADD 172.16.0.0 MASK 255.240.0.0 %GW%
route -p ADD 192.168.100.0 MASK 255.255.255.0 %GW%
echo Lab routes installed.

Output:

code
 OK!
 OK!
 OK!
Lab routes installed.

Identify the active default gateway via PowerShell

powershell
Get-NetRoute -DestinationPrefix '0.0.0.0/0' |
    Sort-Object {$_.RouteMetric + $_.InterfaceMetric} |
    Select-Object -First 1 -Property NextHop, InterfaceAlias,
        @{n='Total Metric';e={$_.RouteMetric + $_.InterfaceMetric}}

Output:

arduino
NextHop      InterfaceAlias  Total Metric
-------      --------------  ------------
192.168.1.1  Ethernet                  25

Remove all routes via a specific gateway

When a VPN disconnects without cleaning up, dozens of orphan routes may remain. Wipe them in bulk by next-hop.

powershell
$gw = '10.8.0.1'
Get-NetRoute -NextHop $gw -ErrorAction SilentlyContinue |
    Remove-NetRoute -Confirm:$false
"Removed all routes via $gw"

Output:

css
Removed all routes via 10.8.0.1

Diff persistent routes against an expected list

A configuration drift detector: compare the live persistent route table against a checked-in CSV.

powershell
$expected = Import-Csv C:\Config\routes.csv
$actual   = Get-NetRoute -PolicyStore PersistentStore -AddressFamily IPv4 |
    Select-Object DestinationPrefix, NextHop, RouteMetric
Compare-Object $expected $actual -Property DestinationPrefix, NextHop |
    Format-Table -AutoSize

Output:

ini
DestinationPrefix NextHop       SideIndicator
----------------- -------       -------------
10.20.0.0/16      192.168.1.99  =>
172.16.0.0/16     192.168.1.254 <=

=> means present locally but not in spec; <= means in spec but missing locally. Reconcile by adding/removing routes.

Export the full route table as JSON

JSON is the easiest format to feed into structured logging pipelines (Splunk, Elasticsearch, Sentinel).

powershell
Get-NetRoute -AddressFamily IPv4 |
    Select-Object DestinationPrefix, NextHop, RouteMetric,
        InterfaceAlias, InterfaceMetric, PolicyStore |
    ConvertTo-Json | Out-File -Encoding utf8 C:\Audit\routes.json

Output:

css
(none — writes JSON)

Force a specific destination through a specific NIC

When Test-NetConnection shows traffic to 10.0.0.5 leaving the wrong adapter, pin it explicitly with a /32 host route.

cmd
route -p ADD 10.0.0.5 MASK 255.255.255.255 192.168.1.1 IF 12 METRIC 1

Output:

code
 OK!

Verify with Find-NetRoute -RemoteIPAddress 10.0.0.5 — the returned InterfaceAlias should match the intended NIC.

Reset routing to factory defaults

If a router table has become so corrupted that incremental cleanup is impractical, the nuclear option is netsh interface ipv4 reset plus a reboot.

cmd
netsh interface ipv4 reset
netsh interface ipv6 reset
shutdown /r /t 5

Output:

vbnet
Resetting Interface, OK!
Resetting Neighbor, OK!
Resetting Path, OK!
Resetting , failed.
Access is denied.

Restart access is denied.
Restarting the computer in 5 seconds...

This rebuilds the routing table from DHCP and persistent routes only — no surviving in-memory state. Run as Administrator.

See also

  • ipconfig — view interface IPs and default gateways
  • arp — Layer 2 neighbor table (one layer below routing)
  • tracert — see which routers the table sends packets through
  • ping — confirm a route reaches its destination
  • netsh — alternative routing command set with adapter-name targeting
  • netstat-r flag also shows the routing table
  • Linux ip — cross-platform comparison with modern iproute2

Sources