Cram Sheet · Security Operations / Enterprise Security
The complete guide to why rule order decides everything, and how to build a ruleset that actually does what you intend.
Every firewall and ACL on the exam obeys the same rule: rules are evaluated top to bottom, and the first rule that matches the traffic wins. The instant a match fires, evaluation stops. Every rule below it, no matter how correct it looks on its own, is never checked for that packet.
This single fact explains almost every ACL question you will face. The question is never really “is this rule correct.” It is “does this rule ever get reached.”
Rule 1 → match? → apply that rule's action, evaluation stops here, nothing below is read. No match → Rule 2 → match? … and so on down the list.
If a packet reaches the bottom of the list without matching a single rule, it is denied by default. This is the implicit deny, and it is not a rule anyone writes — it is simply how ACLs and firewalls behave. Real devices do not display it as a numbered entry. Exam PBQs often show it explicitly as a final row precisely so you do not forget it is always sitting there.
Because first match wins, rules have to move from most specific to most general. Put a broad rule above a narrow exception and the exception never fires, regardless of how correctly it was written.
Goal: only the NOC jump box (10.0.99.4) may use SSH, and it may reach anything. No other internal host may use SSH. Internal hosts should otherwise reach the network normally.
| # | Source | Destination | Port | Action |
|---|---|---|---|---|
| 1 | 10.0.99.4 | any | 22 | ALLOW |
| 2 | 10.0.0.0/8 | any | 22 | DENY |
| 3 | 10.0.0.0/8 | any | any | ALLOW |
| 4 | any | any | any | DENY |
Trace 1 — packet from 10.0.99.4 to 10.0.50.5:22: Rule 1 source matches exactly → MATCH. Result: ALLOWED. Rules 2–4 never checked.
Trace 2 — packet from 10.0.14.20 to 10.0.50.5:22: Rule 1 source is not 10.0.99.4 → no match. Rule 2: in range, port 22 → MATCH. Result: DENIED.
Every rule is built from five fields. Get one wrong and the rule quietly does not do what you think it does.
| Field | What it controls | Common values |
|---|---|---|
| Source | Where the traffic originates | single IP, CIDR range, “any” |
| Destination | Where the traffic is headed | single IP, CIDR range, “any” |
| Protocol | Transport layer protocol | TCP, UDP, ICMP, “any” |
| Port / Service | Which application service | 22, 443, 3389, “any” |
| Action | What happens on a match | Allow, Deny, Drop, Reject |
The exam draws a real distinction here: Deny / Drop — the packet is silently discarded. The sender gets no response and has to time out. This is the default posture for most security-conscious rules, since it tells an attacker nothing. Reject — the firewall sends a response back (a TCP RST or ICMP unreachable). Faster for legitimate users, but it confirms to a scanner that something is listening there.
A stateful firewall tracks the connection. Allow an outbound request once, and the matching inbound reply is permitted automatically, no second rule required. A stateless ACL (common on routers) has no memory of the conversation. It needs explicit rules for both directions, or return traffic is silently denied. This is one of the most common sources of “the rule looks right but the traffic still fails” on PBQs.
| Port | Service | Port | Service |
|---|---|---|---|
| 21 | FTP | 143 | IMAP |
| 22 | SSH / SFTP | 443 | HTTPS |
| 23 | Telnet | 445 | SMB |
| 25 | SMTP | 3306 | MySQL |
| 53 | DNS | 3389 | RDP |
| 80 | HTTP | 5432 | PostgreSQL |
| 110 | POP3 | 8080 | HTTP alt / proxy |
Symptom: an exception you wrote never seems to apply.
| # | Before — broken | Action |
|---|---|---|
| 1 | 10.0.30.0/24 → 10.0.40.0/24, any port | DENY |
| 2 | 10.0.30.10 → 10.0.40.5:5432 | ALLOW (never reached) |
Rule 1 catches the app server's own traffic too, since 10.0.30.10 sits inside 10.0.30.0/24. Rule 2 is never reached.
| # | After — fixed | Action |
|---|---|---|
| 1 | 10.0.30.10 → 10.0.40.5:5432 | ALLOW |
| 2 | 10.0.30.0/24 → 10.0.40.0/24, any port | DENY |
Symptom: a ruleset ends with no final deny rule, and the assumption is that traffic now passes through by default.
Symptom: a service works from the server's side, but the client never receives a response, or the reverse.
On a stateless device, an inbound allow rule does not automatically permit the matching outbound reply. Both directions have to be accounted for, either with two explicit rules or with a stateful device that tracks the session for you.
Symptom: every rule below a certain point seems to be ignored entirely.
A rule with source = any, destination = any, port = any matches everything. If it sits anywhere but the very last position, nothing below it is ever evaluated again. Scan every ruleset for one of these sitting too high before trusting anything below it.
Symptom: a restriction meant for one subnet accidentally touches a different one too.
10.0.0.0/8 covers every address from 10.0.0.0 through 10.255.255.255. A rule meant to apply only to 10.0.30.0/24 but mistakenly written as 10.0.0.0/8 will match far more traffic than intended. Always confirm the prefix length matches the actual scope you mean to cover.
Scenario: Design a ruleset for a payment application server at 10.0.40.20. The database admin at 10.0.9.12 needs RDP (3389) access for maintenance. Every other host on the internal network (10.0.0.0/8) should reach it only over HTTPS (443). Nothing outside 10.0.0.0/8 should reach it at all.
| # | Source | Destination | Action |
|---|---|---|---|
| 1 | 10.0.9.12 | 10.0.40.20:3389 | ALLOW |
| 2 | 10.0.0.0/8 | 10.0.40.20:443 | ALLOW |
| 3 | any | any | DENY (implicit) |