A from-scratch stateful firewall / router appliance written in pure Python. It parses raw Ethernet / IPv4 / TCP / UDP / ICMP frames, makes a per-packet routing decision across four network zones, performs NAT, tracks connection state, and enforces a layered security policy with intrusion-prevention rules.
No frameworks, no libraries beyond the standard library — every routing, NAT and security decision is implemented by hand at the byte level.
The appliance sits (virtually) across four interfaces — internal, DMZ, external and management — and for every packet it decides whether to route, translate (NAT) or drop it, printing the routing decisions, NAT allocations and security alerts as it goes.
internal ──┐ ┌── external (Internet)
│ ┌──────────────┐ │
├──────┤ FIREWALL ├─────┤
DMZ ──────┘ │ route/NAT/IPS│ └── management
└──────────────┘
Routing & addressing
- Longest-prefix-match routing table across the four subnets
- Port Address Translation (NAT/PAT) — internal & DMZ hosts hide behind the firewall's external IP
- Hand-written packet parsing for Ethernet, IPv4, TCP, UDP and ICMP from raw bytes
Stateful inspection
- TCP connection tracking — new vs established via the 3-way handshake, with half-open detection
- UDP flow tracking for DNS
- Only established / related traffic is allowed back through
Intrusion prevention & policy
- ICMP echo handling with crafted echo-reply generation
- Oversize-ping drop (> 64 bytes) and ping rate-limiting
- SYN-flood protection — drops sessions when too many half-open TCP connections accumulate
- DMZ proxy enforcement — inbound HTTP / HTTPS / SSH is forced through the DMZ
- Management plane locked down — SSH permitted only from a single admin host
- Default-deny for unsolicited inbound TCP / UDP
| Component | Responsibility |
|---|---|
Interface |
Per-NIC MAC / IP / netmask / default-route config |
RouteTable |
Longest-prefix-match egress-interface selection |
PatTable |
NAT/PAT allocation and reverse lookup |
Connections |
Stateful connection table (new / established / half-open) |
PacketEngine |
Parses each packet, runs the security policy (check_packet), routes or drops it |
InterfaceHandler |
Feeds packets from a capture file and simulates egress |
python3 appliance.py # processes traffic.spcapor from Python:
from appliance import run_appliance
run_appliance("traffic.spcap")Input format: a .spcap file with one hex-encoded frame per line (the first byte encodes the
ingress interface; # lines are comments). The engine streams packets through and prints routing
decisions, NAT: allocate ... lines, and ALERT drop: ... messages for blocked traffic.
Note: running it also requires the course-provided harness (
support.pyand atraffic.spcapsample), which provide validation helpers and test traffic. This repo contains my own implementation (appliance.py).
Python 3 · raw bytes / struct packet parsing · ipaddress · standard library only.
The mechanics behind a real firewall, implemented packet-by-packet: NAT and address hiding, DMZ segmentation, stateful TCP inspection, and how intrusion-prevention rules — rate limits, flood gates, default-deny — actually get enforced. It's the project that got me into network systems.
Built for CYBR3000 – Cyber Security at the University of Queensland, shared as a learning / portfolio project.