TT Lab
Get started
Learn Learning paths Courses

Network Fundamentals — Hands-on in a Linux VM

A Small Network with Router, DNS, Firewall and NAT

Continue in TT Lab

This lab runs on a VM

You bring the previous nine labs together into one. Between the namespaces home (the user side) and dmz (the server side), the VM itself stands as the router, and that router also takes on the DNS server, the firewall, and NAT. It is a scaled-down version of what one home router does. It is a 60-minute lab, so you may need to extend the time once — your work disappears together with the VM, so be aware of that in advance.

Goal

Connect two subnets, let clients find the server by name, let only the web through, send the private network out to the internet, confirm all of it with packets, and then leave a report.

Why it matters

Until now you looked at one layer at a time. Real outages have several layers overlapping — the name resolves but the firewall blocks, the firewall is open but there is no return path. Someone who has built a network from start to finish has an order in which to look when they hear "it doesn't work": link → address → neighbor → route → name → port → firewall → response.

Steps

  1. Create the namespaces home·dmz and the veths home0 (in home, 10.40.1.10/24)↔r-home (in root, 10.40.1.1/24) and dmz0 (in dmz, 10.40.2.10/24)↔r-dmz (in root, 10.40.2.1/24), and set the default routes of the two namespaces and ip_forward in root so that ping works from home to dmz.
  2. Create /root/final/www/index.html, start a web server listening on 10.40.2.10:80 inside dmz (log to /root/final/http.log), and make curl http://10.40.2.10/ work from home.
  3. With /etc/dnsmasq.d/lab.conf, make dnsmasq listen on 10.40.1.1, answer web.lab.internal→10.40.2.10, and pass everything else upstream, and with /etc/netns/home/resolv.conf, make home use that server.
  4. Save the response to curl -si http://web.lab.internal/ from home to /root/final/byname.txt.
  5. In root, create a table inet labfw and a forward hook chain (policy drop), and allow only established,related and tcp dport 80 from home to dmz, so that the web works and ping does not.
  6. Put masquerade for 10.40.1.0/24 in the table ip labnat, allow tcp dport { 80, 443 } from home to the uplink in forward, and save the first line of curl -sI http://archive.ubuntu.com/ from home to /root/final/internet.txt.
  7. Capture on r-dmz while fetching the web once more from home, and save the output showing the SYN that 10.40.1.10 sent to 10.40.2.10.80 to /root/final/capture.txt.
  8. Save the complete ruleset to /root/final/ruleset.nft, and in /root/final/report.md write four lines, home_ip=·dmz_ip=·dns=·ping_blocked=, together with the order in which you would look when you receive the report "web.lab.internal won't open".

Notes

Two subnets and a router

Create the namespaces home·dmz and the veths home0 (in home, 10.40.1.10/24)↔r-home (in root, 10.40.1.1/24) and dmz0 (in dmz, 10.40.2.10/24)↔r-dmz (in root, 10.40.2.1/24), and set the default routes of the two namespaces and ip_forward in root so that ping works from home to dmz.

Step 1 of lab 8, twice. The r- end of each veth stays in root. ip -n home route add default via 10.40.1.1, ip -n dmz route add default via 10.40.2.1, sysctl -w net.ipv4.ip_forward=1.

The web server in the DMZ

Create /root/final/www/index.html, start a web server listening on 10.40.2.10:80 inside dmz (log to /root/final/http.log), and make curl http://10.40.2.10/ work from home.

ip netns exec dmz setsid python3 -m http.server 80 --bind 10.40.2.10 --directory /root/final/www > /root/final/http.log 2>&1 < /dev/null &. If you put the word dmz in index.html, it is easier to tell the responses apart later.

The router takes on DNS too

With /etc/dnsmasq.d/lab.conf, make dnsmasq listen on 10.40.1.1, answer web.lab.internal→10.40.2.10, and pass everything else upstream, and with /etc/netns/home/resolv.conf, make home use that server.

Add server=<상류> to the configuration from lab 4 (the placeholder is the upstream address) and keep no-resolv as it is (it means read the upstream from this line, not from resolv.conf). systemctl restart dnsmasq. Put nameserver 10.40.1.1 in /etc/netns/home/resolv.conf. To check: ip netns exec home getent hosts web.lab.internal.

Open it by name

Save the response to curl -si http://web.lab.internal/ from home to /root/final/byname.txt.

ip netns exec home curl -si -m 3 http://web.lab.internal/ > /root/final/byname.txt. -i prints the headers too. 200 OK and the contents of index.html must be visible.

Only the web gets through

In root, create a table inet labfw and a forward hook chain (policy drop), and allow only established,related and tcp dport 80 from home to dmz, so that the web works and ping does not.

nft add table inet labfw; nft 'add chain inet labfw forward { type filter hook forward priority 0; policy drop; }'. Two rules: ct state established,related accept and iifname "r-home" oifname "r-dmz" tcp dport 80 accept. Now ping from home must time out and curl must return 200.

From inside the house to the internet

Put masquerade for 10.40.1.0/24 in the table ip labnat, allow tcp dport { 80, 443 } from home to the uplink in forward, and save the first line of curl -sI http://archive.ubuntu.com/ from home to /root/final/internet.txt.

Exactly step 3 of lab 8 (ip saddr 10.40.1.0/24 oifname "enp1s0" counter masquerade). Then, in forward, iifname "r-home" oifname "enp1s0" tcp dport { 80, 443 } accept. DNS is answered by the router itself (dnsmasq), so it does not pass through forward.

Confirm with packets

Capture on r-dmz while fetching the web once more from home, and save the output showing the SYN that 10.40.1.10 sent to 10.40.2.10.80 to /root/final/capture.txt.

After timeout 5 tcpdump -i r-dmz -nn -l 'tcp port 80' > /root/final/capture.txt 2>&1 &, run ip netns exec home curl -s http://web.lab.internal/. There must be a 10.40.1.10.<포트> > 10.40.2.10.80: Flags [S] line (the port placeholder is the client's port). Notice that the source is unchanged — there is no NAT between the two inner networks.

Rules and report

Save the complete ruleset to /root/final/ruleset.nft, and in /root/final/report.md write four lines, home_ip=·dmz_ip=·dns=·ping_blocked=, together with the order in which you would look when you receive the report "web.lab.internal won't open".

nft list ruleset > /root/final/ruleset.nft. The four values in the report are 10.40.1.10, 10.40.2.10, 10.40.1.1, and yes. The order must include name (getent), route (ip route get), firewall (nft counter), and port (ss).