Problem
The firewall's logs are the first thing an intruder deletes
Firewall logs are the evidence after an incident: which addresses were blocked, when, and why. Most firewalls keep them as plain text files. An attacker who gets privileged access can edit or delete those files and cover their tracks, and nobody can tell afterwards.
Rule changes have the same weakness. If rules are stored in one place and changed without a record, a wrong or malicious change can go unnoticed.
Goal: block malicious traffic as it arrives, and keep a record of every decision that shows if anyone changes it.
User
Who needs a log they can trust
Small and medium businesses
No budget for enterprise firewalls and threat-intelligence platforms. They need something cheap, script-based and understandable, without blockchain expertise.
Incident responders
Their timeline of an attack is only as good as the logs. They need to know the record wasn't altered after the fact.
Regulated organisations
Finance, healthcare and government must show auditors who was blocked and why (ISO/IEC 27001 logging controls, GDPR accountability).
System administrators
They need blocks to happen without anyone watching, and a clear reason attached to each one.
Research
What the literature showed
- Rule sets drift. Firewall policies collect anomalies over time: rules hidden behind earlier rules (shadowing), duplicates and contradictions. That makes an audit trail of changes essential.
- Logs are evidence. Audit guidance looks for patterns like spikes in dropped traffic and unexpected restarts, which only works if the logs are complete and unaltered.
- Hash chains are already trusted for integrity. Guardtime's KSI, used by the Estonian government, and LogSentinel both use them to make records tamper-evident.
- The gap: plenty of work on blockchain logging, but few systems that combine real-time traffic analysis with blockchain storage on ordinary hardware.
Python plus iptables was a proven pattern. Published intrusion-detection work and tools like Fail2Ban already use scripts that watch traffic and add iptables rules on the fly. That made it a sound base to add a ledger on top of.
Process
From proposal to six controlled tests
- Plan
Proposal, risk assessment, literature review
Aims and objectives, a Gantt chart with milestones, and a risk matrix. Then reading on firewall policy, audit logging and blockchain in security.
- Choose
Tool selection
Compared Cisco ASA, pfSense, UFW and iptables for how well each could be driven from a Python script in real time.
- Detect
The firewall
Scapy captures every incoming packet. Checks run in order: whitelist, blacklist, Nimda worm signature, then a per-address rate limit of 40 packets per second. Anything caught gets an iptables DROP rule.
- Record
The ledger
Each block decision becomes a transaction (address, action, timestamp). Every five are sealed into a block with an index, a timestamp, the previous block's hash and its own SHA-256 hash.
- Protect
Log protection
A readable copy of each log is encrypted with AES (Fernet). On startup, logs older than 30 days are overwritten with random bytes and then deleted.
- Test
Six attack simulations
Whitelisted traffic, blacklisted sources, packet floods, worm payloads, the ledger itself, and encryption with retention. All run in an isolated lab, as the Computer Misuse Act requires.
Decisions
Why this design
iptables
Instead of: Cisco ASA, pfSense or UFW
iptables works at kernel level through netfilter and can be scripted from Python, so a rule can be added the moment a threat is seen. A commercial appliance locks you into its own interface and rule format.
My own hash chain
Instead of: smart contracts on Ethereum or Hyperledger (the original plan)
A full blockchain network needs nodes, fees and set-up that a small business wouldn't run. A local hash chain gives the property that matters here, tamper evidence, in plain Python. The trade-off: it isn't decentralised (see Reflection).
Explainable checks
Instead of: machine-learning anomaly detection
Lists, a known signature and a rate limit give every block a reason an analyst can read. Machine learning was out of scope, to keep the project achievable in the time available.
Store as little as possible
Instead of: capturing full packets
Only addresses, timestamps and actions are kept. Packet contents are stored only when flagged as malicious. That follows GDPR's data-minimisation principle, and the legitimate-interest basis in Article 6(1)(f). Logs expire after 30 days.
Outcome
What the tests showed
Every attack in testing was blocked. The two partial results were both in what the firewall reported, not in what it blocked.
Whitelisted traffic
PassedTrusted addresses skipped every check, even above the rate limit. No DROP rules, no log entries.
Blacklisted addresses
PassedBlocked in real time, logged and added to the ledger. The log said “Blocked” rather than naming the blacklist.
Flood attack
PassedSources sending 58 to 587 packets per second crossed the 40 pkt/s limit and were dropped by iptables, with the rate recorded in the ledger.
Nimda worm signature
PartialThe GET /scripts/root.exe payload was detected and blocked, and the event logged. But the reason, “Nimda Worm”, was missing from the output.
Blockchain logging
PartialA new block was created after every five transactions. But the command to print the chain failed, so the links between blocks couldn't be shown on screen.
Encryption and 30-day retention
PassedThe log files were unreadable without the key. Logs dated 40 days back were overwritten and deleted on restart.
The project met its core aim: a working firewall that blocks attacks automatically and keeps a protected, verifiable record of what it did. I also mapped the design to GDPR, NIS2, ISO/IEC 27001 (Annex A logging, network security and incident controls) and the UK Computer Misuse Act.
Try it
Send traffic, then try to cover your tracks
Send packets through the firewall's checks and watch the decisions fill the ledger. Then play the intruder: edit an old decision and see what the hash chain catches, and where it stops catching it.
An in-browser recreation of the firewall's checks and ledger. It uses the same check order, block format and SHA-256 recipe, with real hashing. Addresses come from documentation ranges, not real hosts.
Reflection
What I'd do differently
Tamper-evident isn't tamper-proof
The ledger lives on the same machine as the firewall. An intruder with root access could rewrite every block and recompute every hash: step 3 in the demo above. Next time I'd copy the latest hash somewhere they can't reach, such as a remote server, a signed timestamp or a second node. I'd also say “tamper-evident”, which is the accurate word.
Measure false alarms, not just catches
A flat 40 pkt/s limit can't tell a flood from a big download. Some addresses it blocked in testing appear to belong to Canonical, the company behind Ubuntu, so it was probably blocking ordinary update traffic. I'd measure on harmless traffic too. That question is what led me to machine learning for detection.
Test what the analyst sees
Both partial results were reporting bugs: a missing label and a chain that wouldn't print. Automated tests on the output text would have caught them before the live tests.
Measure the cost
I planned to compare latency and throughput against a plain firewall but didn't get to it. I'd also keep the encryption key away from the script's folder, readable only by root.
Next steps I proposed: send the logs to a SIEM such as Splunk, add IPv6 support, and update the blacklist automatically from threat-intelligence feeds like AbuseIPDB.