NETSTAT-NAT(1)

πŸ’– NETSTAT-NAT πŸ’–

okay so bestie, welcome to netstat-nat(1) β€” it lives in the General Commands Manual section and it is genuinely one of my favourite little utilities, no cap.


✨ NAME ✨

netstat-nat β€” extract and filter NAT/firewall connection data


πŸŽ€ SYNOPSIS πŸŽ€

netstat-nat [-no] [-x|-X[width]] {[-G] [-S|-D]}|[-L|-R] [-s ource]…
            [-d estination]… [-g ateway]… [-p rotocol]…
            [-r {src,dst,gate}{,-port}|state] [nf_conntrack]

πŸ¦‹ DESCRIPTION πŸ¦‹

so like, every network-enabled host out here is tracking its ongoing connections, but the ones that are really doing it are stateful firewalls and gateways (routers) β€” the ones doing network address translation. On Linux this whole situation is accounted for by the netfilter framework, and it tracks connectionless protocols (like udp(7), icmp(7)) right alongside the connection-based ones (like tcp(7)). iconic behaviour honestly.

netstat-nat parses nf_conntrack (that's /proc/net/nf_conntrack by default, or the standard input stream if you pass "-"), filters it so only NAT connections survive (by default, cf. -LR), looks up the canonical names for the hosts and ports (unless you hit it with -n), and presents it all in a table, like:

Proto NATed Address                  Destination Address            State
icmp  10.179.163.88                  tarta.nabijaczleweli.xyz
icmp  10.200.233.12                  tarta.nabijaczleweli.xyz
tcp   10.32.144.39.host.securi:63770 tarta.nabijaczleweli.xyz:https TIME_WAIT
tcp   10.32.144.39.host.securi:64361 tarta.nabijaczleweli.xyz:http  TIME_WAIT
tcp   10.72.217.111:33864            tarta.nabijaczleweli.xyz:5900  TIME_WAIT
tcp   10.72.217.111:39074            tarta.nabijaczleweli.xyz:5900  TIME_WAIT
tcp   nabijaczleweli.nabijaczl:20985 lb-10-268-216-78-iad.git:https ESTABLISHED
tcp   nabijaczleweli.nabijaczl:21047 waw07s05-in-f4.1e100.net:http  TIME_WAIT
tcp   nabijaczleweli.nabijaczl:20751 waw07s05-in-f14.1e100.ne:https ESTABLISHED
tcp   nabijaczleweli.nabijaczl:17906 101010.pl:https                ESTABLISHED
tcp   192.168.1.136:38216            lt-in-f188.1e100.net:5228      ESTABLISHED
tcp   192.168.1.136:38330            lt-in-f188.1e100.net:5228      ESTABLISHED
tcp   192.168.1.136:39972            lt-in-f188.1e100.net:5228      ESTABLISHED
tcp   192.168.1.136:40092            lt-in-f188.1e100.net:5228      ESTABLISHED
udp   rozbian.nabijaczleweli.x:46115 10.158.103.58:https            ASSURED
udp   rozbian.nabijaczleweli.x:42560 10.69.17.108:https             ASSURED
udp   rozbian.nabijaczleweli.x:44786 10.140.3.34:https              ASSURED
udp   rozbian.nabijaczleweli.x:47079 10.140.3.34:https              UNREPLIED
udp   192.168.1.185:3076             ec2-10-213-30-29.eu-cent:https ASSURED
udp   tarta.nabijaczleweli.xyz:39517 ns-153.awsdns-19.com:domain
udp   tarta.nabijaczleweli.xyz:16829 ns-1007.awsdns-61.net:domain
udp   tarta.nabijaczleweli.xyz:46874 ns-1411.awsdns-48.org:domain

and from this little guy we can literally see: two ongoing incoming ICMP queries (no state available); many remote hosts are calling tarta (and it is the one to hang up); local hosts nabijaczleweli and 192.168.1.136 are generally calling google; that the HTTP/3 revolution is real; and that tarta is querying some DNS servers (they didn't reply yet). the tea is all here πŸ’…

the state column can be any of:

  • ESTABLISHED β€” a functional ongoing connection
  • ASSURED β€” similar, but for connectionless protocols
  • (blank) β€” either no connection state is tracked (like in ICMP), or waiting for remote reply (like in UDP)
  • UNREPLIED β€” remote didn't reply for longer than the expected time-out
  • TIME_WAIT β€” the local side of the connection was closed, delayed remote packets are being collected before recycling
  • FIN_WAIT β€” the remote side of the connection was closed, waiting for acknowledgement (β†’FIN, ACKβ†’, waiting for β†’FIN)
  • SYN_RECV β€” a remote client started opening a connection, but didn't acknowledge the local response (β†’SYN, SYN,ACKβ†’, waiting for β†’ACK)
  • SYN_SENT β€” a local client started opening a connection, but remote didn't yet accept it (SYNβ†’, waiting for β†’SYN,ACK)
  • CLOSE β€” TIME_WAIT because connection was closed forcibly (β†’RST)
the last 5 only really apply to TCP-like protocols. just so you know 🫢

With -L or -R on tarta the table looks very similar (-nX21 added as well), but loopback connections also appear:

Proto Source Address        Destination Address   State
tcp   [::1]:49118           [::1]:9928            TIME_WAIT
tcp   [::1]:50624           [::1]:80              ESTABLISHED
tcp   10.221.132.191:35862  192.168.1.250:5900    TIME_WAIT
tcp   127.0.0.1:34030       127.0.0.1:8213        TIME_WAIT
tcp   127.0.0.1:52476       127.0.1.1:3493        ESTABLISHED
tcp   10.176.163.40:51167   192.168.1.250:443     TIME_WAIT
tcp   10.62.134.22:23178    192.168.1.250:80      SYN_RECV
tcp   10.62.134.22:47444    192.168.1.250:80      SYN_RECV
udp   127.0.0.1:42738       127.0.0.1:323
udp   127.0.0.1:44850       127.0.0.1:5353
udp   127.0.0.1:46444       127.0.0.1:53          ASSURED
udp   192.168.1.144:20407   192.168.1.250:53
udp   192.168.1.146:59266   192.168.1.250:53
udp   192.168.1.204:35989   192.168.1.250:53
udp   192.168.1.250:23225   10.46.8.231:53
udp   192.168.1.250:11300   10.11.28.69:53
udp   192.168.1.250:51413   10.116.123.52:6881    ASSURED

(Public addresses were anonymised as 10/8 in both tables; both tables heavily abridged.) ✨


πŸ‘‘ OPTIONS πŸ‘‘

  • -n β€” Don't try to resolve IP addresses to hostnames nor port numbers to service names (hosts(5), services(5)) β€” just normalise them.
  • -o β€” Don't output the table header line.
  • -x β€” Widen the table: addresses are 40 instead of 30 columns wide.
  • -X β€” Widen the table: address columns are the width of a fully-specified ipv6(7) address + port (like [fc00:e355:e73f:b463:a28e:529d:7838:65be]:34012).
  • -Xwidth β€” Widen the table: address columns use the given width.

  • -G (also -N) β€” Add a Gateway Address column between the source and destination columns β€” this is the outside-facing address of the node performing NAT.

  • -S β€” Only show connections this node facilitates from its local network to the outside world (SNAT β€” source NAT). Overrides -D.
  • -D β€” Only show connections this node facilitates to its local network from the outside world (DNAT β€” destination NAT). Overrides -S.

By default, the table is filtered as-if -S and -D were used additively instead of subtractively.


  • -L β€” Only show direct connections made by this node (and any of its configured addresses). This still includes hosts outside the local network. Disables -SDG. Overrides -R.
  • -R β€” Only show non-NAT connections that don't involve this node('s addresses) at all (This is most likely because their destinations are broadcast addresses.) Disables -SDG. Overrides -L.

  • -s source,… β€” Hide connections that don't originate from sources (parsed as an address or looked up in DNS (getaddrinfo(3)); comma- or whitespace-separated, or specify multiple times).
  • -d destination,… β€” Hide connections that aren't targeting destinations (likewise).
  • -g gateway,… β€” Hide connections that aren't going through gateways (likewise).
  • -p protocol,… β€” Hide connections that aren't formed by these layer 4 protocols (like UDP, TCP, or ICMP) (case-insensitive; likewise).

  • -r {src,dst,gate}{,-port}|state β€” Sort the output by the given column (after partitioning by L4 protocol):
    • src β€” source address (this is the default)
    • dst β€” destination address
    • src-port β€” source port
    • dst-port β€” destination port
    • state β€” connection state
    • gate β€” gateway address
    • gate-port β€” gateway port

ties are then broken in this order. Everything is sorted lexicographically (as a string), before address/port→name lookup (unless disabled by -n).


πŸ“ FILES πŸ“

  • /proc/net/nf_conntrack: Contains the current netfilter connections. This is usually only readable by root.
root-only, bestie. don't come crying to me when you get a permission denied 😭

🌈 ENVIRONMENT VARIABLES 🌈

  • NETSTAT_NAT_LOCAL_ADDRS: If set, contains a comma- or whitespace-separated list of addresses to be considered local. This supersedes any real system state (for use with nf_conntrack backups).

πŸ’€ EXIT STATUS πŸ’€

1 if nf_conntrack couldn't be opened or a source, destination, or gateway didn't exist.


🧚 SEE ALSO 🧚

conntrack(8) provides a read-write interface to this table.

getaddrinfo(3), getifaddrs(3), getnameinfo(3), hosts(5), services(5)


and that's the whole thing, babe β€” this page is brought to you by netstat-nat-ng 2b-1, dated August 23, 2025 πŸ’– go read your connection table, you absolute main character 🫢✨

πŸ“¦ where this page comes from