Available for day contractsFrom 21st September I have availability for day and half day contracts. Please contact for more information.

Contact →
mikepreston.org

BSD Network Tools

Inspecting and configuring networking on FreeBSD, OpenBSD, and NetBSD with ifconfig, route, netstat, and pf.

BSD Network Tools

Inspecting and configuring networking on FreeBSD, OpenBSD, and NetBSD with ifconfig, route, netstat, and pf.

Overview

If you arrive from Linux, the muscle memory is wrong. On modern Linux the ip suite (iproute2) has displaced ifconfig, route, netstat, and arp, which are now legacy compatibility wrappers. On the BSDs the opposite is true: ifconfig, route, netstat, and arp are the primary, current, fully-supported tools. There is no ip command, no ss, and no tc. The classic BSD utilities never went away because they were never deprecated — they are actively developed and remain the canonical interface.

Three points trip up newcomers most:

  • Interface names are driver-based, not eth0/eth1. An Intel gigabit NIC is em0 or igb0, a Realtek is re0, a Broadcom is bge0. The number is the unit, not a slot. Run ifconfig -l to discover them.
  • Configuration persists in plain rc.conf-style files, not in a daemon's database. FreeBSD and NetBSD use /etc/rc.conf; OpenBSD uses per-interface /etc/hostname.if files. Runtime changes via ifconfig are lost on reboot unless written to these files.
  • The firewall is not netfilter. OpenBSD invented and ships pf; FreeBSD ships pf, ipfw, and legacy ipf; NetBSD's default is npf (its in-tree pf and ipf are deprecated and their use is discouraged — reach for npf).
BSD (classic tools)Linux (iproute2)maps tmaps tmaps tmaps tmaps tip addr / ip linkip routesstcnftablesifconfigroute / netstat -rsockstat / netstat-andummynet / ALTQpf / ipfw / npfBSD (classic tools)Linux (iproute2)maps tmaps tmaps tmaps tmaps tip addr / ip linkip routesstcnftablesifconfigroute / netstat -rsockstat / netstat-andummynet / ALTQpf / ipfw / npf

Per-OS defaults at a glance

Capability FreeBSD OpenBSD NetBSD
Persistent config /etc/rc.conf /etc/hostname.if /etc/rc.conf + /etc/ifconfig.if
Default firewall none enabled; pf, ipfw, ipf available pf (always present) npf (pf, ipf in-tree but deprecated)
sockstat yes no (use fstat/netstat) no (use fstat/netstat)
Traffic shaping dummynet (ipfw), ALTQ (pf) pf queueing (HFSC), ALTQ on older ALTQ
Link aggregation lagg trunk/aggr agr

Linux to BSD Command Mapping

The single most useful table if you think in iproute2. The BSD column is the idiomatic equivalent, not a drop-in syntax match — the arguments differ.

Task Linux (iproute2) BSD
Show/set addresses ip addr ifconfig
Show/set link state ip link ifconfig
Show routing table ip route netstat -rn
Add/del routes ip route add/del route add/delete
Neighbour (ARP) ip neigh arp
Neighbour (IPv6 ND) ip -6 neigh ndp
Socket statistics ss sockstat (FreeBSD) / netstat -an
Interface counters ip -s link netstat -i / netstat -ibdh
Traffic shaping tc dummynet (ipfw) / pf queues / ALTQ
Link media/speed ethtool ifconfig <if> media
Tunnels/VLANs/bridges ip link add ifconfig <if> create
Firewall nft / iptables pfctl / ipfw / npfctl

A common mistake: there is no ip route show table-style multi-table routing on stock BSD. FreeBSD has setfib/multiple FIBs and OpenBSD has rdomains/rtables, but these are deliberate, separate features — not the everyday model.

ifconfig

ifconfig is the workhorse: it shows and configures addresses, link state, media, MTU, and creates virtual interfaces. It is not deprecated here.

Key Concepts

  • A single ifconfig invocation can stack multiple operations: address family, address, netmask, and flags all on one line.
  • Secondary addresses are aliases. The first inet is the primary; every additional address must use the alias keyword. This is the biggest divergence from ip addr add, which treats all addresses uniformly.
  • Netmask can be given as a dotted quad, a hex mask (0xffffff00), or — on FreeBSD and NetBSD — CIDR via /24. OpenBSD ifconfig also accepts /24.

Showing Interfaces

# List interface names only (the "what are my NICs called" command)
ifconfig -l

# Show all interfaces, full detail
ifconfig

# Show one interface
ifconfig em0

# Show only up-and-running interfaces
ifconfig -u

# Show only interfaces of a given type/group (FreeBSD/OpenBSD groups)
ifconfig -g egress      # OpenBSD: the interface with the default route

Addresses

# Set the primary IPv4 address (CIDR form, FreeBSD/NetBSD/OpenBSD)
ifconfig em0 inet 192.0.2.10/24

# Equivalent with explicit netmask
ifconfig em0 inet 192.0.2.10 netmask 255.255.255.0

# Add a SECONDARY address — must use 'alias'
ifconfig em0 inet 192.0.2.11/32 alias

# Remove a secondary address
ifconfig em0 inet 192.0.2.11 -alias

# IPv6 address
ifconfig em0 inet6 2001:db8::10 prefixlen 64

# Add a secondary IPv6 alias
ifconfig em0 inet6 2001:db8::11 prefixlen 64 alias

# Remove the primary IPv4 address entirely
ifconfig em0 inet 192.0.2.10 -alias    # (removing primary uses -alias too)

Note: for the primary address you normally just overwrite it by setting a new one. The alias/-alias distinction matters most when adding or removing extra addresses on an interface that already has one.

Link State, MTU, and MAC

# Bring an interface up / down
ifconfig em0 up
ifconfig em0 down

# Set MTU (jumbo frames example)
ifconfig em0 mtu 9000

# Override the MAC address (link-layer)
ifconfig em0 ether 02:00:00:aa:bb:cc      # FreeBSD: 'ether' or 'lladdr'
ifconfig em0 lladdr 02:00:00:aa:bb:cc     # OpenBSD/NetBSD: 'lladdr'

Media (the ethtool equivalent)

media/mediaopt set speed, duplex, and link options. This is where ethtool muscle memory goes.

# Show supported media types and current setting
ifconfig em0 media

# Force 1000baseT full duplex
ifconfig em0 media 1000baseT mediaopt full-duplex

# Force autoselect (let the PHY negotiate)
ifconfig em0 media autoselect

# Wireless: list options (FreeBSD wraps the NIC in a wlanN clone)
ifconfig wlan0 list scan

Cloned (Virtual) Interfaces

BSD creates virtual interfaces on demand with create. This is the ip link add analogue.

# Create and destroy
ifconfig vlan0 create
ifconfig vlan0 destroy

# tap (layer-2) and tun (layer-3) point-to-point devices
ifconfig tap0 create
ifconfig tun0 create

# bridge, lagg, gif (generic tunnel), gre
ifconfig bridge0 create
ifconfig lagg0 create
ifconfig gif0 create

Naming caveat: FreeBSD uses lagg for aggregation and tap/tun; OpenBSD uses trunk/aggr for aggregation, and tun/tap exist but tap is tap. Verify the cloner name on the target OS with ifconfig <name> create — an unknown cloner errors immediately.

VLANs

802.1Q VLAN interfaces are cloned and bound to a parent (the "vlandev").

# FreeBSD: create vlan10 on top of em0 with tag 10
ifconfig vlan0 create vlan 10 vlandev em0
ifconfig vlan0 inet 192.0.2.10/24 up

# FreeBSD also supports the descriptive name form
ifconfig em0.10 create          # creates a vlan interface named em0.10, tag 10

# OpenBSD: same vlan/vlandev keywords
ifconfig vlan10 create
ifconfig vlan10 vlan 10 vlandev em0
ifconfig vlan10 inet 192.0.2.10/24 up

The vlan/vlandev keyword pair is consistent across FreeBSD, OpenBSD, and NetBSD. The auto-named em0.10 shorthand is a FreeBSD convenience — do not assume it on OpenBSD/NetBSD.

Bridges

A bridge joins interfaces at layer 2. Members are added with addm.

# Create the bridge
ifconfig bridge0 create

# Add member interfaces
ifconfig bridge0 addm em0 addm em1

# Bring it up
ifconfig bridge0 up

# Remove a member
ifconfig bridge0 deletem em1

# Inspect members and STP state
ifconfig bridge0
bridge0em0 (addm)em1 (addm)tap0 (addm)L2 forwardingbridge0em0 (addm)em1 (addm)tap0 (addm)L2 forwarding

This is the standard pattern for bridging VMs/jails to a physical NIC (a tap per guest, all added to one bridge0).

Link Aggregation

The keyword and driver differ by OS — a frequent stumbling block.

# FreeBSD: lagg with LACP
ifconfig lagg0 create
ifconfig lagg0 laggproto lacp laggport em0 laggport em1
ifconfig lagg0 inet 192.0.2.10/24 up

# FreeBSD failover protocol (active/standby)
ifconfig lagg0 laggproto failover laggport em0 laggport em1

# OpenBSD: 'aggr' (the LACP/802.1AX driver) — members added with 'trunkport'
ifconfig aggr0 create
ifconfig aggr0 trunkport em0 trunkport em1
ifconfig aggr0 inet 192.0.2.10/24 up

# OpenBSD also has the older 'trunk' driver for non-LACP modes
# (failover, loadbalance, roundrobin, broadcast — NOT lacp):
ifconfig trunk0 create
ifconfig trunk0 trunkproto failover trunkport em0 trunkport em1

# NetBSD uses 'agr' (which does LACP)

Verify before relying on it: FreeBSD = lagg/laggproto/laggport; OpenBSD splits the job — aggr(4) is the LACP/802.1AX driver, while the older trunk(4) does not implement LACP (only failover, loadbalance, roundrobin, broadcast); NetBSD = agr (which does LACP). Both OpenBSD drivers add members with trunkport. The protocol names are broadly shared but not identical across all three — check the man page on the box.

route

route manipulates the kernel routing table directly. The syntax is the classic BSD form and differs from ip route — there is no via/dev grammar.

Key Concepts

  • -net declares a network destination; -host a single host. Omitting both lets route guess from the netmask.
  • default is the keyword for the default route (Linux's 0.0.0.0/0).
  • To view the table, the idiomatic command is netstat -rn, not route — route is for changes and single lookups (route get).

Viewing and Looking Up

# Show the whole routing table, numeric (the everyday command)
netstat -rn

# Show IPv4 only / IPv6 only
netstat -rn -f inet
netstat -rn -f inet6

# Look up the route the kernel would use for a destination
route get 8.8.8.8
route -6 get 2001:4860:4860::8888

Adding and Deleting

# Add a default gateway
route add default 192.0.2.1
route -n add default 192.0.2.1        # -n: no DNS resolution on output

# Add a network route via a gateway
route add -net 10.0.0.0/8 192.0.2.254

# Add a host route
route add -host 10.1.2.3 192.0.2.254

# IPv6 default
route -6 add default 2001:db8::1

# Delete routes
route delete default
route delete -net 10.0.0.0/8
route delete -host 10.1.2.3

# Change an existing route's gateway
route change default 192.0.2.2

# Flush the entire routing table (careful — drops your default too)
route flush

FreeBSD note: route add default 192.0.2.1 works, but scripts often use the explicit route add -net default 192.0.2.1. On OpenBSD the persistent default lives in /etc/mygate, not in a route command.

arp and ndp

arp manages the IPv4 neighbour cache; ndp is its IPv6 (Neighbour Discovery) counterpart. Together they cover what ip neigh does on Linux.

# --- arp (IPv4) ---
# Show the ARP cache, numeric
arp -an

# Show one host
arp 192.0.2.10

# Add a static (permanent) ARP entry
arp -s 192.0.2.10 00:11:22:33:44:55

# Delete an entry
arp -d 192.0.2.10

# Flush the whole ARP cache (FreeBSD)
arp -d -a

# --- ndp (IPv6 neighbour discovery) ---
# Show the neighbour cache
ndp -an

# Add a static neighbour entry
ndp -s 2001:db8::10 00:11:22:33:44:55

# Delete an entry
ndp -d 2001:db8::10

# Show default router list and prefix list (FreeBSD/NetBSD;
# OpenBSD ndp has no -r/-p — use route(8) / sysctl there)
ndp -r
ndp -p

netstat

On BSD, netstat is not legacy — it is the primary tool for routes, sockets, interface counters, and protocol statistics. Note that BSD netstat flags overlap with Linux's but the output and some flags differ (there is no -tulpn idiom; use the forms below).

Routing and Interfaces

# Routing table (numeric) — the canonical "show routes"
netstat -rn

# Per-interface statistics (packets, errors, collisions)
netstat -i

# Numeric, human-readable, with byte counters (FreeBSD)
netstat -ibdh

# Watch one interface live, updating every second (FreeBSD)
netstat -I em0 -w 1

Sockets

# All sockets, numeric (TCP + UDP + UNIX)
netstat -an

# Only Internet sockets (no UNIX domain)
netstat -an -f inet
netstat -an -f inet6

# Listening TCP sockets, numeric
netstat -an -p tcp | grep LISTEN

# FreeBSD: show the PID/program owning each socket
netstat -anv          # -v adds extra columns; pair with sockstat for owners

Protocol and Buffer Statistics

# Per-protocol statistics (retransmits, resets, drops...)
netstat -s
netstat -sp tcp          # just TCP
netstat -sp ip

# mbuf (network memory buffer) usage — BSD-specific, no Linux analogue
netstat -m

netstat -m (mbuf clusters) has no real Linux equivalent and is the first place to look when a BSD box reports out-of-memory under network load.

sockstat (FreeBSD)

sockstat is FreeBSD's answer to ss/lsof -i: it maps open sockets to the processes and users that own them. OpenBSD and NetBSD have no sockstat — use netstat -an plus fstat there.

# All open sockets with owning process and user
sockstat

# IPv4 + IPv6 listening sockets only (the "what's listening" command)
sockstat -4 -6 -l

# Only a specific protocol
sockstat -P tcp

# Filter by port
sockstat -p 443

# Connected (non-listening) sockets
sockstat -c

# OpenBSD / NetBSD equivalent — find what holds a socket:
fstat | grep internet
netstat -an -f inet

Firewalls

The BSDs ship different firewalls. Pick by OS and by what you already know. This section summarises; each firewall is a large topic in its own right.

NetBSDnpf (default)pfipfOpenBSDpf (only)FreeBSDpfipfw + dummynetipf (legacy)NetBSDnpf (default)pfipfOpenBSDpf (only)FreeBSDpfipfw + dummynetipf (legacy)

pf (FreeBSD, OpenBSD, NetBSD)

pf is OpenBSD's firewall and the most portable. Rules live in /etc/pf.conf; pfctl loads and inspects them. pf grammar diverged between OpenBSD and FreeBSD but has largely reconverged — OpenBSD modernised it (match, the nat-to/rdr-to translation rules, and the built-in queue system), and current FreeBSD pf accepts the same inline match … nat-to/rdr-to form, retaining the standalone nat/rdr statements only for backward compatibility. Write the modern nat-to/rdr-to syntax (as below) on both. The lasting divergence is queueing: FreeBSD still uses ALTQ (kernel-options-gated) where OpenBSD has the newer queue/HFSC system. Always check man pf.conf on the target.

# Enable / disable pf
pfctl -e            # enable
pfctl -d            # disable

# Load (and replace) the ruleset from a file
pfctl -f /etc/pf.conf

# Validate without loading
pfctl -nf /etc/pf.conf

# Show loaded rules / NAT rules / state table / info
pfctl -sr           # show filter rules
pfctl -sn           # show NAT rules
pfctl -ss           # show the state table
pfctl -si           # show status and counters
pfctl -sa           # show everything

# Tables (named address lists)
pfctl -t bruteforce -T add 203.0.113.5
pfctl -t bruteforce -T show
pfctl -t bruteforce -T flush

# Anchors (sub-rulesets, e.g. for jails / dynamic rules)
pfctl -a myapp -sr

Minimal OpenBSD-style /etc/pf.conf:

# OpenBSD pf.conf — default-deny inbound, stateful
ext_if = "em0"
set skip on lo
block return                       # default block, send RST/ICMP
pass out quick                     # allow all outbound, keep state
pass in on $ext_if proto tcp to port { 22, 80, 443 }
# NAT for an internal network (OpenBSD modern syntax)
match out on $ext_if from 192.168.0.0/24 to any nat-to ($ext_if)
# Redirect (port forward) inbound 80 to an internal host
pass in on $ext_if proto tcp to port 80 rdr-to 192.168.0.10

Ordering: OpenBSD pf is last-matching-rule wins (use quick to stop evaluation). This is the opposite of iptables' first-match. Forgetting this is the classic "my pass rule is overridden by a later block" bug.

ipfw (FreeBSD)

ipfw is FreeBSD-native, rule-numbered, and first-match-wins. It also drives dummynet for traffic shaping.

# Show the ruleset (with rule numbers)
ipfw list
ipfw -a list          # with packet/byte counters

# Add rules (lower numbers evaluated first)
ipfw add 100 allow tcp from any to me 22
ipfw add 200 allow ip from any to any via lo0
ipfw add 65000 deny ip from any to any

# Delete a rule by number
ipfw delete 200

# Flush everything (default policy may then deny — keep console access!)
ipfw flush

# Show dynamic (stateful) rules
ipfw -d list

ipfw's implicit final rule is deny ip from any to any unless the kernel is built with IPFIREWALL_DEFAULT_TO_ACCEPT or net.inet.ip.fw.default_to_accept=1 is set. Flushing the ruleset over SSH can therefore lock you out instantly.

ipf / IPFILTER (legacy, NetBSD)

ipf/ipnat is the older Darren Reed firewall, still present on FreeBSD and NetBSD. Configured via /etc/ipf.conf and /etc/ipnat.conf, managed with ipf, ipnat, and ipfstat. Treat it as legacy on FreeBSD; prefer pf or ipfw for new work.

npf (NetBSD default)

NetBSD's modern firewall is npf, configured in /etc/npf.conf and managed with npfctl.

npfctl validate /etc/npf.conf     # check syntax
npfctl reload                     # load the ruleset
npfctl start                      # enable
npfctl show                       # show active config
npfctl stats                      # counters

Traffic Shaping

There is no tc. BSD shapes traffic through either dummynet (driven by ipfw) or queueing in pf.

dummynet via ipfw (FreeBSD)

dummynet attaches packets to pipes (bandwidth/delay/loss) or queues (weighted sharing).

# Define a pipe: 1 Mbit/s with 50 ms one-way delay
ipfw pipe 1 config bw 1Mbit/s delay 50ms

# Add packet loss and a queue limit
ipfw pipe 1 config bw 1Mbit/s delay 50ms plr 0.01 queue 50

# Send matching traffic into the pipe
ipfw add 100 pipe 1 ip from any to 192.0.2.0/24 out

# Weighted queues sharing a parent pipe
ipfw pipe 10 config bw 10Mbit/s
ipfw queue 1 config pipe 10 weight 100
ipfw queue 2 config pipe 10 weight 10
ipfw add 200 queue 1 tcp from any to any 443 out
ipfw add 210 queue 2 tcp from any to any out

# Inspect
ipfw pipe show
ipfw queue show

Queueing in pf

On FreeBSD, pf shaping uses ALTQ (kernel must have ALTQ compiled in). On OpenBSD, the newer queue syntax (HFSC under the hood) arrived in 5.5 and ALTQ was removed entirely in 5.6.

# OpenBSD modern pf queueing (HFSC) in /etc/pf.conf
queue rootq on em0 bandwidth 100M
  queue ssh parent rootq bandwidth 10M
  queue web parent rootq bandwidth 50M default
pass out on em0 proto tcp to port 22 set queue ssh
pass out on em0 proto tcp to port { 80, 443 } set queue web
# FreeBSD pf with ALTQ (older syntax; requires ALTQ kernel options)
altq on em0 cbq bandwidth 100Mb queue { ssh, web }
queue ssh bandwidth 10% priority 5
queue web bandwidth 50% cbq(default)

This is the sharpest pf divergence: ALTQ syntax (FreeBSD) and the queue syntax (OpenBSD ≥ 5.5, ALTQ removed in 5.6) are mutually incompatible. A pf.conf written for one will not load on the other. Confirm which your target supports.

Sysctl Networking Knobs

BSD sysctl uses the net.inet.* (IPv4) and net.inet6.* (IPv6) trees — not Linux's net.ipv4.* / net.ipv6.*. The tree layout is entirely different, so Linux tuning snippets do not translate verbatim.

# Turn the box into a router (enable IPv4 forwarding) — runtime
sysctl net.inet.ip.forwarding=1

# IPv6 forwarding
sysctl net.inet6.ip6.forwarding=1

# Inspect a subtree
sysctl net.inet.tcp           # all TCP knobs
sysctl net.inet.ip.forwarding # one value

# Common FreeBSD tuning examples
sysctl net.inet.tcp.delayed_ack=0
sysctl net.inet.ip.fw.default_to_accept   # ipfw default policy (read-only after boot)
sysctl net.inet.ip.redirect=0             # don't send ICMP redirects
Purpose BSD sysctl Linux counterpart
IPv4 forwarding net.inet.ip.forwarding net.ipv4.ip_forward
IPv6 forwarding net.inet6.ip6.forwarding net.ipv6.conf.all.forwarding
Send ICMP redirects net.inet.ip.redirect net.ipv4.conf.all.send_redirects
TCP keepalive net.inet.tcp.keepidle (ms) net.ipv4.tcp_keepalive_time (s)

Persist sysctls in /etc/sysctl.conf (all three BSDs). For routing, the correct way to enable forwarding persistently on FreeBSD is gateway_enable="YES" in /etc/rc.conf (which sets the sysctl at boot), not editing the sysctl directly.

Persistence

Runtime ifconfig/route changes vanish on reboot. Each OS persists configuration differently — this is where Linux habits cause the most "it worked until I rebooted" surprises.

FreeBSD: /etc/rc.conf

# /etc/rc.conf
hostname="host.example.com"

# Static IPv4 on em0
ifconfig_em0="inet 192.0.2.10/24"

# Secondary address (alias) — note the _alias0 suffix, numbered
ifconfig_em0_alias0="inet 192.0.2.11/32"

# IPv6
ifconfig_em0_ipv6="inet6 2001:db8::10 prefixlen 64"

# DHCP instead of static
ifconfig_em0="DHCP"

# Default gateway
defaultrouter="192.0.2.1"
ipv6_defaultrouter="2001:db8::1"

# Act as a router (enables net.inet.ip.forwarding at boot)
gateway_enable="YES"
ipv6_gateway_enable="YES"

# Enable pf and point it at its config
pf_enable="YES"
pf_rules="/etc/pf.conf"

# Or enable ipfw instead
firewall_enable="YES"
firewall_script="/etc/ipfw.rules"

# Create a vlan / bridge at boot
cloned_interfaces="vlan0 bridge0"
ifconfig_vlan0="vlan 10 vlandev em0 inet 192.0.2.10/24"

Apply rc.conf network changes without rebooting: service netif restart && service routing restart (FreeBSD). On a remote box, do this carefully — restarting netif drops the connection if you fat-finger the address.

OpenBSD: /etc/hostname.if + /etc/mygate

OpenBSD has one file per interface, named /etc/hostname.<ifname>. The default route lives in /etc/mygate.

# /etc/hostname.em0
inet 192.0.2.10 255.255.255.0
inet alias 192.0.2.11 255.255.255.255
inet6 2001:db8::10 64

# DHCP form (single line)
# dhcp

# /etc/mygate
192.0.2.1
2001:db8::1
# /etc/hostname.vlan10 — VLAN persisted on OpenBSD
inet 192.0.2.10 255.255.255.0
vlan 10 vlandev em0

Enable IP forwarding persistently on OpenBSD via /etc/sysctl.conf:

# /etc/sysctl.conf (OpenBSD)
net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1

pf is on by default on OpenBSD; its config is simply /etc/pf.conf. Apply changes with sh /etc/netstart em0 (re-reads the hostname.if file) or pfctl -f /etc/pf.conf for the firewall.

NetBSD: /etc/rc.conf + /etc/ifconfig.if

NetBSD blends both styles. Simple setups go in /etc/rc.conf; per-interface complexity goes in /etc/ifconfig.<ifname>.

# /etc/rc.conf (NetBSD)
ifconfig_wm0="inet 192.0.2.10 netmask 255.255.255.0"
defaultroute="192.0.2.1"
ip6mode="host"

# Enable the npf firewall
npf=YES

# Router mode: NetBSD has no rc.conf ip_forwarding knob.
# IPv4 forwarding is a sysctl (set it in /etc/sysctl.conf):
#   net.inet.ip.forwarding=1
# IPv6 forwarding is driven by ip6mode:
ip6mode="router"
# /etc/ifconfig.wm0 (NetBSD) — alternative, one directive per line
inet 192.0.2.10/24
inet 192.0.2.11/32 alias

NetBSD's driver names differ again: Intel gigabit is often wm0 (not em0). Always check ifconfig -l on the actual machine rather than assuming.

Diagnostics

The classic diagnostic tools mostly originated on BSD, so they behave as expected — but a few names differ.

# Packet capture (tcpdump is BSD-native; see the tcpdump cheatsheet)
tcpdump -i em0 -nn host 192.0.2.10

# Trace the path to a host
traceroute 8.8.8.8
traceroute6 2001:4860:4860::8888

# Connectivity
ping 8.8.8.8
ping6 2001:4860:4860::8888       # FreeBSD also accepts 'ping -6'

# DNS lookups
host example.com                 # available on all three
dig example.com                  # FreeBSD (bind-tools), NetBSD
drill example.com                # OpenBSD default (ldns; no dig in base)

# Live socket / connection state
sockstat -4 -6 -l                # FreeBSD: what's listening
netstat -an -f inet              # portable

# pf live state and counters
pfctl -ss                        # current state table
pfctl -si                        # status and rule counters

# Interface throughput, live
netstat -I em0 -w 1              # FreeBSD
systat -ifstat 1                 # FreeBSD/OpenBSD curses interface stats

OpenBSD ships drill (from ldns), not dig, in the base system — reaching for dig on a fresh OpenBSD box fails until you install bind-tools. host is present everywhere.

Quick Reference

Task Command
List interface names ifconfig -l
Show all interfaces ifconfig
Set primary IPv4 ifconfig em0 inet 192.0.2.10/24
Add secondary IPv4 ifconfig em0 inet 192.0.2.11/32 alias
Bring interface up/down ifconfig em0 up / down
Set MTU ifconfig em0 mtu 9000
Force media ifconfig em0 media 1000baseT mediaopt full-duplex
Create vlan ifconfig vlan0 create vlan 10 vlandev em0
Create bridge + add member ifconfig bridge0 create ; ifconfig bridge0 addm em0
Show routing table netstat -rn
Add default route route add default 192.0.2.1
Add network route route add -net 10.0.0.0/8 192.0.2.254
Look up a route route get 8.8.8.8
Show ARP cache arp -an
Static ARP entry arp -s 192.0.2.10 00:11:22:33:44:55
Show IPv6 neighbours ndp -an
Interface counters netstat -i (FreeBSD: netstat -ibdh)
Socket statistics netstat -an / sockstat -4 -6 -l (FreeBSD)
Protocol stats netstat -sp tcp
mbuf usage netstat -m
Enable forwarding (runtime) sysctl net.inet.ip.forwarding=1
Load pf rules pfctl -f /etc/pf.conf
Show pf state table pfctl -ss
List ipfw rules ipfw -a list
Shape with dummynet ipfw pipe 1 config bw 1Mbit/s delay 50ms

Common Issues and Solutions

Issue Cause Solution
"Interface eth0 not found" BSD names NICs by driver, not ethN Run ifconfig -l; expect em0, igb0, re0, bge0, wm0 (NetBSD)
Secondary IP silently doesn't stick Adding a second address without alias overwrites the primary Use ifconfig em0 inet 192.0.2.11/32 alias
Config lost after reboot Runtime ifconfig/route changes aren't persistent Write to /etc/rc.conf (FreeBSD/NetBSD) or /etc/hostname.if (OpenBSD)
ip, ss, tc commands not found Those are Linux iproute2 tools Use ifconfig, netstat/sockstat, dummynet/pf queues
pf installed but blocking nothing pf loaded but not enabled FreeBSD: pf_enable="YES" in rc.conf + pfctl -e; OpenBSD: pf is on by default
All forwarded traffic dropped IP forwarding off by default sysctl net.inet.ip.forwarding=1; persist via gateway_enable="YES" (FreeBSD)
pf pass rule ignored OpenBSD pf is last-match-wins; a later block overrides Reorder rules or add quick to the pass rule
Locked out after ipfw flush ipfw default is deny ip from any to any Keep console access; add an allow-SSH rule before flushing, or set default_to_accept
dig not found (OpenBSD) OpenBSD base ships drill, not dig Use drill, or pkg_add bind-tools
pf queue config won't load ALTQ (FreeBSD) vs queue syntax (OpenBSD ≥ 5.5; ALTQ removed in 5.6) are incompatible Use the syntax matching the OS; check man pf.conf
lagg/trunk keyword rejected Aggregation driver differs per OS FreeBSD lagg/laggport; OpenBSD aggr (LACP) or trunk (non-LACP), both via trunkport; NetBSD agr
sockstat not found sockstat is FreeBSD-only OpenBSD/NetBSD: use netstat -an + fstat

Related Topics

The following topics complement this BSD networking cheatsheet:

  1. tcpdump/Wireshark — packet capture, BSD-native, for diagnosing the traffic these tools route
  2. iptables/nftables — the Linux firewall counterpart to pf/ipfw/npf
  3. Nginx/HAProxy — application-layer traffic handling on top of BSD networking
  4. WireGuard / IPsec — VPN tunnels configured via ifconfig/gif/pf on BSD
  5. DNS (BIND/Unbound) — name resolution, with Unbound shipping in OpenBSD/FreeBSD base
  6. ZFS/Jails — FreeBSD jails commonly bridge to the network via bridge/epair/tap