Build a TCP/IP Stack from Scratch · Module 02

Setup: Extending the Stack Container

Setup: Extending the Stack Container

Now that you know what a TAP interface does, let's get your environment ready to use one.

We'll tweak your stack container so it can create a virtual network interface (tap0) and run C code that interacts with it.

Step 1 — Install the tools you'll need

Inside your lab/stack.Dockerfile, update the file so it looks like this:

FROM debian:stable-slim
RUN apt-get update && apt-get install -y \
 gcc make iproute2 net-tools tcpdump arping \
 && rm -rf /var/lib/apt/lists/*
 
# We'll copy our source files into /stack
WORKDIR /stack
CMD ["sleep", "infinity"]

You now have:

  • gcc and make → to build your stack
  • iproute2/net-tools → to manage interfaces (ip addr, ifconfig, etc.)
  • tcpdump → to inspect frames

Rebuild your containers:

docker compose build stack

Step 2 — Allow access to /dev/net/tun

By default, containers don't have permission to create TAP interfaces.

We'll give our stack container that ability safely with Docker Compose.

Edit your lab/docker-compose.yml entry for the stack service:

 stack:
 build:
 # build context MUST be the repo root so we can later switch to COPY if we want
 context: ..
 dockerfile: lab/stack.Dockerfile
 command: sleep infinity
 cap_add: [ "NET_ADMIN" ]
 devices:
 - /dev/net/tun
 networks:
 labnet:
 ipv4_address: 10.10.0.4
 volumes:
 # bind-mount host ./stack into container /stack
 - ../stack:/stack

Now your container can open /dev/net/tun and manage its own virtual interfaces — this is key for building your stack.

Step 3 — Create your stack program skeleton

Inside stack/, make a simple file called main.c with this placeholder:

#include <stdio.h>
 
int main(void) {
 printf("Network stack starting up...\n");
 return 0;
}

Then in the same folder, create a quick Makefile:

CC=gcc
CFLAGS=-Wall -O2
 
all: stack
 
stack: main.c
	mkdir -p ./bin
	$(CC) $(CFLAGS) -o bin/stack main.c
 
clean:
	rm -f ./bin/stack

Now you can build it inside the container:

 lab git:(main) docker compose exec stack bash
root@0faeccd16fa5:/stack# make
mkdir -p ./bin
gcc -Wall -O2 -o bin/stack main.c
root@0faeccd16fa5:/stack# ./bin/stack

You should see:

Network stack starting up...

Summary

You've now got everything ready:

  • the permissions,
  • the tools,
  • and a working program stub that'll soon read and write real Ethernet frames.

Next, we'll teach your program how to actually create and attach a TAP device.