Network Fundamentals — Hands-on in a Linux VM
Build a Router from Three Namespaces
This lab runs on a VM
You connect three namespaces — host h1, router r1, and host h2 — with two veth pairs.
It is the smallest network in which two hosts on different subnets communicate through a router.
Goal
Read the routing table, put in a default route and a static route, and confirm what the switch
(ip_forward) that turns a single Linux machine into a router actually changes.
Why it matters
A report that "only a certain range doesn't work" is almost always routing. But routing needs
both sides to be right — even if a path exists going out, if there is no path back it fails the same way,
and the symptoms are indistinguishable. And Linux by default does not forward other hosts'
packets. A single ip_forward line turns a host into a router, and Kubernetes
nodes, Docker hosts, and VPN servers all stand on that one line.
Steps
- Create the namespaces
h1·r1·h2and create the veth pairsh1r↔rh1andh2r↔rh2, puttingh1rinh1,h2rinh2, andrh1·rh2inr1. - Attach
10.20.1.10/24toh1r,10.20.1.1/24torh1,10.20.2.1/24torh2, and10.20.2.10/24toh2r, and bring all interfaces andloUP. - Ping from
h1toh2(10.20.2.10) and save the failure message to/root/route/unreach.txt. - Put each one's router address into
h1andh2as the default route. - Turn
net.ipv4.ip_forwardon to 1 inr1so that theh1→h2ping works. - Save the result of
traceroute -nfromh1toh2to/root/route/trace.txt. - Create a dummy interface
svc0onh2and attach10.99.0.10/24to it, and put a static route10.99.0.0/24 via 10.20.2.10intor1so that10.99.0.10is reachable fromh1. - In
/root/route/report.md, write one linehops=, one line with the result ofip route get 10.99.0.10fromh1, and an explanation of why it does not work withoutip_forward.
Notes
- Creating four interfaces takes many commands. Use a shell for loop.
ip -n h1 route add default via 10.20.1.1. The gateway must be on the same subnet as h1.ip netns exec r1 sysctl -w net.ipv4.ip_forward=1. The value is separate for each namespace.ip route get <주소>asks the kernel directly "Where does this destination go out?" instead of reading the table with your eyes (replace the placeholder with an address).- A common mistake: forgetting h2's default route in step 4. A path exists going out, but the reply cannot come back.
Connect the three
Create the namespaces h1·r1·h2 and create the veth pairs h1r↔rh1 and h2r↔rh2, putting h1r in h1, h2r in h2, and rh1·rh2 in r1.
Create two pairs like ip link add h1r type veth peer name rh1, and move them with ip link set <이름> netns <ns> (replace the placeholders with the interface name and the namespace). The key point is that a router has two interfaces — each leg is in one subnet.
Attach the addresses
Attach 10.20.1.10/24 to h1r, 10.20.1.1/24 to rh1, 10.20.2.1/24 to rh2, and 10.20.2.10/24 to h2r, and bring all interfaces and lo UP.
Do the four like ip -n h1 addr add 10.20.1.10/24 dev h1r. Then run link set … up on the six interfaces (four veth ends plus three lo). To check, run ip netns exec h1 ping -c1 10.20.1.1 — the router on the same subnet must already be reachable.
With no route
Ping from h1 to h2 (10.20.2.10) and save the failure message to /root/route/unreach.txt.
ip netns exec h1 ping -c 1 -W 1 10.20.2.10 > /root/route/unreach.txt 2>&1. Errors come out on standard error, so do not forget 2>&1. There is no default route yet, so it must be Network is unreachable.
Default route
Put each one's router address into h1 and h2 as the default route.
ip -n h1 route add default via 10.20.1.1, ip -n h2 route add default via 10.20.2.1. You need both — if you add only one side, the request goes but there is no path for the reply to come back.
Turn it into a router
Turn net.ipv4.ip_forward on to 1 in r1 so that the h1→h2 ping works.
ip netns exec r1 sysctl -w net.ipv4.ip_forward=1. If this value is 0, the kernel silently drops packets not addressed to itself. It is a separate value for each namespace.
Follow the path
Save the result of traceroute -n from h1 to h2 to /root/route/trace.txt.
ip netns exec h1 traceroute -n -w 1 10.20.2.10 > /root/route/trace.txt. Hop 1 must be the router (10.20.1.1) and hop 2 must be h2. -n is the option that turns off name resolution.
Static route
Create a dummy interface svc0 on h2 and attach 10.99.0.10/24 to it, and put a static route 10.99.0.0/24 via 10.20.2.10 into r1 so that 10.99.0.10 is reachable from h1.
On the h2 side: ip -n h2 link add svc0 type dummy, addr add 10.99.0.10/24 dev svc0, link set svc0 up. On the r1 side: ip -n r1 route add 10.99.0.0/24 via 10.20.2.10. h1 leaves it to r1 through its default route, so there is nothing to touch.
What you learned
In /root/route/report.md, write one line hops=, one line with the result of ip route get 10.99.0.10 from h1, and an explanation of why it does not work without ip_forward.
hops is the hop count from the traceroute in step 6. Paste the first line of ip netns exec h1 ip route get 10.99.0.10 as it is (you will see via 10.20.1.1). Your explanation must include the word ip_forward.