Same Job, Different Shell Part 4: Routing Tables
Once you know an interface’s own address (Part 3), the next diagnostic question is almost always “where does traffic from here actually go.” A routing table answers that, and reading one is one of the few commands in this series where the underlying concept, not just the syntax, differs slightly between platforms.
Linux: ip route
$ ip route show
default via 192.0.2.1 dev eth0
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.2
Two lines, and both matter. The first is the default route, everything not otherwise matched goes out eth0 via the gateway 192.0.2.1. The second is the connected route the kernel installs automatically the moment an address is assigned to eth0, anything in 192.0.2.0/24 is directly reachable, no gateway needed.
For a specific destination, rather than reading the whole table and mentally matching the longest prefix yourself, ask the kernel to do the lookup:
$ ip route get 1.1.1.1
1.1.1.1 via 192.0.2.1 dev eth0 src 192.0.2.2 uid 0
cache
That single command answers “which route will this specific packet actually take” directly, which is the question you actually have most of the time, rather than “show me everything and let me figure it out.”
The legacy tool, if you’re on an older box:
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.0.2.1 0.0.0.0 UG 0 0 0 eth0
192.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
-n stops it resolving hostnames for gateway/destination, which you almost always want; without it, a slow or dead DNS server can make route itself hang.
Windows: route print and Get-NetRoute
C:\> route print
produces the classic, dense, all-in-one text table: IPv4 routes, IPv6 routes, and the persistent routes list, all in one scroll. It’s the direct visual equivalent of Linux’s route -n, right down to the Destination/Gateway/Genmask-style columns, and it’s still what most Windows admins reach for first out of habit.
Get-NetRoute is the structured, scriptable version:
PS> Get-NetRoute -AddressFamily IPv4 |
Format-Table DestinationPrefix, NextHop, InterfaceAlias, RouteMetric -AutoSize
# just the default route (the Windows analogue of Linux's "ip route | grep default")
PS> Get-NetRoute -DestinationPrefix "0.0.0.0/0" | Select-Object -ExpandProperty NextHop
DestinationPrefix is Windows’ name for what Linux calls the route’s prefix (0.0.0.0/0 for default, same CIDR notation both places). NextHop is the gateway; a NextHop of 0.0.0.0 means the same thing Linux’s connected route without a via means, directly reachable on that subnet, no gateway hop needed.
Where the concepts actually diverge: RouteMetric
Every Windows route carries a RouteMetric, and Windows genuinely uses it: when multiple routes could match the same destination (two NICs both with a default route, for instance, one Wi-Fi and one Ethernet), the one with the lower RouteMetric wins, combined with the interface’s own metric.
Linux’s routing table has a metric field too (visible in ip route show output as metric N when it’s non-default, and it’s the Metric column in route -n), but day-to-day Linux administration leans on Linux’s actual tiebreaker mechanism far more: routing tables, ip rule, and policy-based routing. Windows has nothing directly equivalent to ip rule’s “route lookup depends on which table applies to this source/mark/fwmark” model; multi-path selection on Windows is metric-and-interface-priority based, not policy-table based. If you’re coming from Linux and looking for Windows’ ip rule or VRF-style equivalent, there genuinely isn’t a clean one at the Get-NetRoute level, it lives one layer up in things like Hyper-V virtual switches or third-party SD-WAN/VPN client route injection instead.
Adding a route: the one place Get-NetRoute’s cousin needs more than you’d expect
New-NetRoute looks like a straight equivalent to ip route add at a glance, but it has one requirement Linux’s version doesn’t: an interface is mandatory, not optional. You can’t add a route on Windows without telling it which -InterfaceAlias (or -InterfaceIndex) it belongs to.
# Linux: the kernel works out the interface from the gateway's subnet
$ sudo ip route add 198.51.100.0/24 via 192.0.2.1
# Windows: InterfaceAlias is required, not inferred
PS> New-NetRoute -DestinationPrefix "198.51.100.0/24" -InterfaceAlias "Ethernet" -NextHop 192.0.2.1
Leave -InterfaceAlias off and it fails outright rather than guessing, which is a small but real difference in how forgiving the two platforms are about an incomplete command.
Quick reference
| What you want | Linux | Windows |
|---|---|---|
| Full routing table | ip route show | route print |
| Structured/scriptable table | ip route show (parse or -j for JSON) | Get-NetRoute |
| Which route will this destination take | ip route get <ip> | Get-NetRoute -DestinationPrefix <ip>/32 (approximate; doesn’t do longest-prefix-match the way ip route get does) |
| Just the default route | ip route show default | Get-NetRoute -DestinationPrefix "0.0.0.0/0" |
| Add a route | ip route add <cidr> via <gw> | New-NetRoute -DestinationPrefix <cidr> -InterfaceAlias <if> -NextHop <gw> |
| Legacy text table | route -n | route print |
What’s next
Part 5 covers name resolution: dig, nslookup, and resolvectl against Resolve-DnsName, nslookup, and ipconfig /displaydns, including real query output captured live for this series.
Cross-references: Beyond ifconfig: The ip Command Reference Every Network Engineer Needs covers ip rule and policy routing tables in full, the piece of Linux routing this post only flags as having no Windows equivalent.