Packet Filtering & Proxies
Put web01 on the internet: close every port, open only what the shop needs, hide the backend behind nginx, and read timeouts and refusals like a log.
An interactive Linux lesson: 18 steps, about 32 minutes, on a live simulation in your browser.
The shop is moving web01 to a public address. It serves the site with nginx on port 80, reads the database on db01, and calls a small order app on app01 (192.168.1.32, port 8080). Your workstation sits at 192.168.1.50.
Run the survey first. ss -tlnp lists every listening socket: nginx on 0.0.0.0:80 answers on all addresses, so the whole internet will soon be able to reach it. curl localhost/ shows the welcome page, which proves the server works before you touch anything.
What you will learn
web01 goes public
- Every open port is a public door: A server on a public address answers every listening port, so you start by listing what listens and then decide what may stay reachable.
- Close everything, then open three doors: Default deny means every incoming port is closed unless a rule opens it, so you allow SSH before you enable or you lock yourself out.
Chains and order
- INPUT, FORWARD, OUTPUT: A chain is a rule list for one direction: INPUT for packets to you, OUTPUT for packets from you, FORWARD for packets through you.
- Two rules for one port: First match wins: a chain is read top to bottom, the first matching rule decides, and the rest never see the packet.
- Let the answers back in
SSH for the office only
- Break it: a DROP above your SSH rule: A broad DROP above a narrow ACCEPT swallows the ACCEPT. When SSH times out after a firewall change, read the chain top to bottom.
- Drill: SSH from the office only
Verdicts and NAT
- DROP waits, REJECT answers: DROP is silence, so the client times out. REJECT is an answer, so the client is refused at once.
- One public address for the back room
nginx as a reverse proxy
- Hide the app behind nginx: A reverse proxy is a server that answers by asking another server: the client sees nginx, and only nginx sees the app.
- Break it: the app logs 127.0.0.1
- The backend goes quiet: 502 means the proxy is fine and its upstream is not: your connection worked, the proxy's onward connection did not.
- Forward who asked: X-Forwarded-For carries the client address through the proxy, so the app can log who asked instead of logging the proxy.
- Drill: pass the Host through
- Break it: your OUTPUT rule hits nginx
Recap & playground
- Read it in thirty seconds: A reachable port needs two yeses: something listening (ss) and a rule letting it in (ufw); either list alone lies by omission.
- Cheat sheet
- Playground