Every organisation has a security policy that says something like "only authorised traffic is permitted". Nobody disagrees with it, and nobody can implement it. A firewall does not know what "authorised" means. It knows addresses, protocols, ports and, depending on the product, a little more. Somebody has to translate the intent into rules, and that translation is where most network security either works or quietly fails.
The first four parts of this series built the map: packets, addresses, names, routes and the boundaries of a cloud network. This part decides what is allowed to move across that map. It is the first of the intermediate parts, and the shift in thinking is simple to state: stop asking "what should we block?" and start asking "which conversations should exist?"
Hadeda Freight is fictional, and its address ranges and figures are illustrative. Hadeda is the South African logistics company we have been following, building Track, a shipment-tracking portal and public API on a Johannesburg cloud region.
A rule is a precise instruction
A useful firewall rule names eight things: the source, the destination, the protocol, the port, the direction, the reason, the owner, and when it will next be reviewed or expire. Here is one of Hadeda's:
Permit TCP 443 from the public gateway subnet (
10.40.10.0/24) to the Track app subnet (10.40.20.0/24). Reason: customer and driver traffic to the Track API. Owner: Track product team. Review every six months.
The first five fields are what the firewall enforces. The last three are what keep the rule honest over time. A rule without a reason cannot be safely removed, because nobody knows what will break. A rule without an owner is never reviewed. A rule without a review date becomes permanent the day it is created, which is how estates accumulate thousands of rules that each made sense once.
Stateful and stateless controls
A stateful control remembers connections. If it allowed Track's app to open a connection to the database, it recognises the database's replies as part of that same conversation and lets them back without a separate rule. A stateless control judges every packet on its own, in each direction, so you must explicitly allow the return traffic too.
Return traffic is where stateless rules catch people out. When a client opens a connection to port 443, the reply goes back to a temporary ephemeral port on the client, a high-numbered port whose exact range depends on the client's operating system. A stateless rule set that allows inbound 443 but forgets the outbound ephemeral range produces a connection that opens and then hangs.
In the cloud, the common pattern is a stateful control attached to the workload or its network interface (a security group on AWS and Huawei Cloud, a network security group on Azure, firewall rules or policies that target tags or service accounts on Google Cloud), sometimes with a second control at the subnet boundary called a network access control list. Here the similar names hide a real difference: at the time of writing (October 2026), AWS network ACLs are stateless, while Huawei Cloud's network ACLs are stateful. A rule set copied from one to the other can break return traffic or allow more than intended. Check how each provider evaluates rule priority, defaults and return traffic before carrying a design across clouds.
Four layers that see different things
A network firewall is only one layer of control, and it is the one that understands the least about what a request means.
| Control | Understands | Example decision at Hadeda |
|---|---|---|
| Network firewall | Addresses, protocols, ports, sometimes application signatures | Allow TCP 443 from the gateway subnet to the app tier |
| Web application firewall (WAF) | HTTP requests and common web attacks | Block an SQL injection pattern sent to /track |
| API gateway | API routes, tokens, quotas and client identity | Let a valid customer token call /shipments |
| Application authorisation | User, role and the business action | A customer sees only their own shipments |
The point of the stack is not that more layers are better. It is that each question has a natural home. A network firewall cannot tell whether a customer is looking at someone else's delivery address; only the application can. Equally, the application should not be the first thing to notice that a stranger is probing port 5432 on the database. An open port grants reachability, never business permission. A firewall may let a request arrive; the application still decides whether the caller may do what it is asking.
Track handles personal information (names, phone numbers, delivery addresses), so POPIA's security safeguards apply to it. No regulator will specify Hadeda's port numbers. What a reviewer will expect is evidence that access to that data is deliberately limited at more than one layer, and the stack above is how you show it.
The flow matrix: no arrow means no flow
The most useful artefact in network security is not a rule set. It is the flow matrix: a list of every conversation the system needs, written before any rules exist. Rules are then generated from it or reviewed against it.
Track's main path is short. Customers and drivers reach the WAF and API gateway on HTTPS. The gateway forwards to the app service on HTTPS. The app reaches the customer database on its database port. The app calls an approved payment provider and an approved email and SMS provider, both on HTTPS. That is it.
Anything not on the map is denied by default, and that default does a great deal of work. It means the internet cannot reach the database even if someone accidentally gives it a public address. It means the gateway cannot skip the app and query the database directly. It means a compromised app instance cannot call an arbitrary host on the internet.
But a real flow matrix is longer than the main path, because systems need more than their main path to stay alive. For Track, the supporting flows include:
- administrative access, through an identity-aware management route rather than open SSH or RDP;
- monitoring agents sending metrics and logs to the observability platform;
- DNS queries to the platform team's resolvers;
- time synchronisation;
- identity provider calls for token validation;
- operating system and package updates through a controlled mirror or proxy;
- backup traffic from the database to the backup service.
Forgetting these is how "deny by default" gets a bad name. The team writes the main path, everything breaks in the first week, someone opens a broad rule "temporarily", and the matrix never recovers. Write the supporting flows first. They are boring, and they are the ones that cause the outage.
Egress is half the policy
Many organisations control inbound traffic carefully and allow anything outbound. That is backwards from an attacker's point of view. A compromised workload with unrestricted outbound access can download tools, receive instructions from command infrastructure, and send data out, all over ordinary-looking HTTPS.
Egress control for Hadeda's production network looks like this:
- Force outbound traffic through one controlled path. Workloads route internet-bound traffic through a firewall or secure web gateway in the shared hub, not out of their own subnet.
- Allow approved destinations, not the whole internet. The payment provider, the email and SMS provider, and the package mirror. Nothing else by default.
- Reach cloud services privately. Storage and database services are reached through private endpoints, so that traffic never needs an internet path at all. Part 6 covers how.
- Control the software supply path. Container images and packages come from a mirrored or proxied registry the platform team controls.
- Log and govern DNS. Most outbound connections start with a DNS query. Resolver logs show where workloads are trying to go, including where they should not be.
- Use workload identity. Services authenticate to cloud APIs with platform-issued identities rather than stored keys, so a stolen config file is not a stolen credential.
One caution: domain-based firewall rules ("allow payments.provider.example") are convenient but subtle. DNS answers change, and one shared endpoint address may serve many customers of the same provider. Allowing an address because it once belonged to your payment provider may be allowing a lot more than you think. Prefer provider-documented ranges, private connectivity, or a proxy that inspects the requested name.
Rules belong in code
A flow matrix that lives in a spreadsheet and a rule set that lives in a console will drift apart within weeks. Hadeda keeps its security group and firewall definitions in infrastructure as code, in the same repository as the Track service, so a new flow arrives as a reviewed change with its reason in the commit. A pipeline check rejects any rule with a source of 0.0.0.0/0 on anything other than the public gateway. If you are starting from nothing, start small with infrastructure as code rather than waiting for the perfect module library.
Common mistakes
0.0.0.0/0opened "temporarily" and never removed. Temporary rules have no owner, so nothing ever closes them.- Rules copied between environments without checking purpose. A test-environment shortcut becomes a production exposure.
- Wide port ranges opened because ephemeral ports are not understood. The fix is understanding statefulness, not opening 1024 to 65535.
- IP addresses in rules where group or tag references are supported. Addresses change as workloads scale; references to a security group or service account follow the workload.
- A WAF treated as protection for non-HTTP services. It cannot see inside a database protocol or SSH session.
- Rules with no owner or reason. Nobody can safely delete them, so they accumulate forever.
- Flow logs enabled but never queried. Logs that are not retained, searched or alerted on are a storage bill, not a control.
Try it yourself
Write the flow matrix for Track's three tiers: gateway, app and database. Do not stop at the main path. Add administration, monitoring, DNS, time synchronisation, identity, software updates and backup flows. For each, record source, destination, protocol, port, direction, reason and owner. Then mark which flows are stateful returns that need no separate rule, and which would need one if the subnet used a stateless access list.
Test your understanding
A security group allows inbound TCP 443 to the app. Does the app's reply need its own outbound rule?
Answer: Not if the control is stateful, as security groups commonly are. It recognises the reply as part of an allowed connection. A stateless network access list would need an explicit rule for the return traffic to the client's ephemeral port.
The firewall allows a customer's request to reach Track's /shipments endpoint. Is that customer authorised to see a particular shipment?
Answer: The firewall cannot know. It permitted reachability. Only application authorisation can decide whether this customer owns that shipment.
Why is unrestricted outbound access a risk if inbound access is tightly controlled?
Answer: A compromised workload can still download tools, receive commands and exfiltrate data over outbound connections it initiates itself. Inbound controls do nothing about traffic the workload starts.
Why write the flow matrix before the rules?
Answer: Because rules should implement an agreed design. A matrix with reasons and owners can be reviewed by people who do not read firewall syntax, and every rule can be traced back to a line in it.
What to take from this part
A rule needs a reason, an owner and a review date. Without them it can never be safely removed.
Ask which conversations should exist, not what to block. Then deny everything else.
Write the supporting flows first. Monitoring, DNS, identity, updates and backup cause the first-week outages.
Control egress as carefully as ingress. Attackers leave the way you let them.
An open port is not permission. Each layer of control answers a different question, and the application answers the last one.
Next in the series: Internet access, NAT and private endpoints: four questions, not one.
How CloudNala can help
We help teams turn a vague "only authorised traffic" policy into a flow matrix with reasons and owners, then into rules held as code and checked in the pipeline. Where an estate already has years of accumulated rules, we work through them with flow logs to find which rules carry real traffic, which can be retired, and which egress paths nobody knew were open.
Work with CloudNala
CloudNala helps organisations move from technology ambition to practical execution across cloud, AI, data, platform engineering and digital services.
Whether you are exploring AI, modernising your cloud environment, building a public-sector digital service, or turning an idea into a working MVP, we can help you shape the roadmap and deliver the next step.
Request a Cloud Network Review or write to us at consult@cloudnala.co.za