TT Lab
Get started
Learn Learning paths Courses

Network Fundamentals — Hands-on in a Linux VM

Build a Router from Three Namespaces

Continue in TT Lab

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

  1. 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.
  2. 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.
  3. Ping from h1 to h2 (10.20.2.10) and save the failure message to /root/route/unreach.txt.
  4. Put each one's router address into h1 and h2 as the default route.
  5. Turn net.ipv4.ip_forward on to 1 in r1 so that the h1→h2 ping works.
  6. Save the result of traceroute -n from h1 to h2 to /root/route/trace.txt.
  7. 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.
  8. 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.

Notes

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.