What's a network interface?

I’ve been working with container networking a bunch this week. When learning
about new unfamiliar stuff (like container networking / virtual ethernet
devices / bridges / iptables), I often realize that I don’t fully understand
something much more fundamental.

This week, that thing was: network interfaces!!

You know, when you run ifconfig and it lists devices like lo, eth0,
br0, docker0, wlan0, or whatever. Those.

This is a thing I thought I understood but it turns out there are at least
2 things I didn’t know about them.

I’m not going to try to give you a crisp definition, instead we’re going to
make some observations, do some experiments, ask some questions, and make some
guesses.

What happens if you don’t have any network interfaces?

I was messing around with network namespaces, and I created a new one with:

sudo ip netns add ns1

It turns out that when you create a new network namespace, it doesn’t have any
network interfaces at all! What does that mean? Let’s explore and see what it
looks like:

We can run commands inside this new network namespace with sudo ip netns exec ns1 COMMAND. I’m just going to run a shell inside this network namespace, and then
try out some things.

So let’s start with sudo ip netns exec ns1 bash

$ sudo ip netns exec ns1 bash
$ ifconfig
(no output)

That makes sense, this is a new network namespace so there are no network
interfaces set up yet. Still inside that network namespace, let’s try to make a
webserver and connect to it.

so when we do curl localhost:8900, no packets actually get sent (when I ran tcpdump, no packets show up)

so nc never receives any packets

Let’s do an experiment to try to confirm our hypotheses: let’s add a network
interface! The idea is that if we have a lo network interface, then curl
localhost:8900 will actually send packets, nc will receive them, and
everything will work.

So – if I make a request to 172.17.0.1 (curl 172.17.0.1:8080), it seems like that would end up on the
docker0 device. Right? Wrong, apparently.

If I run tcpdump -i lo packets to 172.17.0.1 show up, and if I run tcpdump -i docker0,
the packets don’t show up. So it seems right now, on my machine,
packets sent to 172.17.0.1 go through the lo device.

The reason they get sent to lo instead of docker0 is that there’s a route
for 172.17.0.1 in my route table that says local – the same reasons that
packets to 127.0.0.1 get sent to lo.

step 2 tcpdump gets the packet

This is pretty straightforward – once there’s a network device attached to the
packet, then tcpdump gets the packet.

That’s all I know for now!

ok so what do we know about network interfaces?

Here’s what I think so far:

they can be physical network interfaces (like eth0) or virtual interfaces (like lo and docker0)

you can list them with ifconfig or ip link list

if you don’t have any network interfaces, your packets don’t enter the linux network stack at all really. To go through the network stack you need network interfaces.

When you send a packet to an IP address, your route table decides which network interface that packet goes through. This is one of the first things that happens in the network stack.

tcpdump captures packets after they’re routed (assigned an interface) Though there’s a PREROUTING chain in iptables that happens before routing!`