Enterprise Network Simulation

A small enterprise network built in Cisco Packet Tracer: five VLANs behind a layer-3 core switch, an EtherChannel-trunked access layer, RIPv2 between two routers, NAT to an outside network, a wireless VLAN and an access list, built as coursework in 2025. The topology file and the exported device configurations are in the repository, under MIT.

After the build I audited the exported configurations line by line and worked through five findings, including one that explains why a filter placed after address translation can never match the address it was written for.

Topology: access switches S1 and S2 bundled by an EtherChannel, S3 and S4 for management and wireless, all trunked to the S0 core switch, which links to border router R0, then R1, then the server at 10.10.10.2; the addressing table lists five VLAN subnets and three transit links
Five VLANs behind a layer-3 core switch. Trunks carry only the VLANs they need; the core routes between them, R0 translates, R1 filters.

The problem

The brief was a campus-scale network with the usual services: separate user, management and wireless VLANs; redundancy between access switches; routing between VLANs; address translation to an outside network; and a filter that keeps one VLAN away from one server. The interesting constraint is not any single service but where each one lives. Put inter-VLAN routing on a router and every packet between two desks crosses a slow link twice; put the filter on the wrong side of the NAT boundary and it filters nothing. The design decisions are placement decisions.

Design

Every routed service is in a different place on purpose, so each can be examined on its own:

Service Where How
Inter-VLAN routing Core switch S0 ip routing with an SVI per VLAN, so traffic between VLANs never leaves the switch
Link redundancy Access switches S1 – S2 Two ports bundled as Port-channel 1 (mode on), carrying a trunk; PVST sees one logical link and has nothing to block
DHCP Relayed from S0 ip helper-address on the VLAN 4 and VLAN 100 SVIs, pointing at a server in the management VLAN; VLANs 2 and 3 are static by design
NAT Border router R0 Five private ranges translated onto a two-address pool, one-to-one, no overload
Filtering Outside router R1 Extended ACL 100, outbound on the server-facing interface, meant to block VLAN 2's HTTP to 10.10.10.2
Dynamic routing R0 ↔ R1 RIPv2, no auto-summary

Two decisions carry through the whole configuration. Each trunk allows only the VLANs it needs, so a link's allowed list is a statement about what is supposed to cross it rather than a default. And the uplink from S0 to R0 is a routed port (no switchport) rather than yet another VLAN — a point-to-point subnet, 192.168.11.0/24, which puts the boundary between switching and routing where a reader of the configuration can see it.

Following one packet

The clearest way to read the design is to take one frame and watch what each device does to it. Three journeys cover the whole topology, and each of them stops at a different layer.

Desk to desk, same VLAN. A frame from one host in VLAN 2 to another leaves the access switch, crosses the EtherChannel to its neighbour if the destination hangs off the other switch, and is delivered. It is switched the whole way and never reaches a routed interface. The bundle is what makes this path survive a cable: PVST sees Port-channel 1 as one logical link, so there is no second port for it to block and nothing to reconverge when one member drops.

Desk to desk, different VLAN. A frame from VLAN 2 to VLAN 3 goes to its gateway, which is the Vlan2 SVI on the core switch S0. S0 routes it and sends it straight back out on VLAN 3. It never touches a router, and that is the whole reason inter-VLAN routing lives on the core: put it on R0 instead and every packet between two desks crosses the uplink twice.

Desk to the outside server. This is the long path, and it crosses every boundary in the design:

  1. A host in VLAN 2, source 192.168.2.10, sends to 10.10.10.2. Its gateway is the Vlan2 SVI on S0.
  2. S0 routes it. The destination is in none of its five connected subnets, so it takes the default route out of the routed uplink — 192.168.11.0/24, a point-to-point subnet rather than a sixth VLAN, so the packet is visibly leaving the switched domain at this hop.
  3. R0 receives it on the nat inside interface, matches the translation list, and rewrites the source to 20.10.2.100 from the two-address pool. The packet that leaves the nat outside interface no longer carries the address it arrived with.
  4. RIPv2 has given R0 a route to the server subnet through R1, so it forwards; R1 delivers onto its connected 10.10.10.0/24 and applies ACL 100 outbound on the way.

Steps 3 and 4 are the pair worth reading together, because the packet that reaches the filter is no longer the packet that left the host. That is what the audit in the next section is built around.

Auditing the configuration

I audited the exported configurations line by line after the build. The repository's config/ carries the corrected versions, and one case is kept as built with the reasoning written into the file as a comment, because it is the most instructive path in the whole topology.

# Finding Effect Status
1 ACL 100 had a single deny and no permit The implicit deny ip any any dropped all traffic leaving R1's server interface, not just VLAN 2's web traffic Fixed—one line
2 ACL sits downstream of NAT The deny can never match; see below Left in place, documented
3 R1 carried a dead copy of R0's NAT block Never consulted—no interface on R1 is marked inside/outside—but misleading to anyone diffing the routers Removed
4 No route between S0 and R0 S0 had no default route; R0's five RIP network statements matched nothing directly connected and advertised nothing. NAT sessions still appeared to work because the translation table carried replies back Static routes added on both
5 Duplicated interface stanza on R1 Cosmetic; IOS merges them Merged
A VLAN 2 host sends a packet with source 192.168.2.10; R0 rewrites the source to 20.10.2.100 before forwarding; R1's outbound ACL 100 then sees 20.10.2.100, so the rule's source operand 192.168.2.0 0.0.0.255 never matches
Finding 2. The rule is syntactically valid and the interface accepts it; what it matches on has already been translated away.

Where a filter has to sit relative to NAT

ip access-list extended 100
 deny   tcp 192.168.2.0 0.0.0.255 host 10.10.10.2 eq www
 permit ip any any

Even with the permit added, the deny never fires. R0 translates every internal source into the 20.10.2.100–101 pool before forwarding to R1. By the time a packet reaches R1, its source is 20.10.2.100, and a rule matching on 192.168.2.0/24 has nothing to match against. There is no error and no log entry; the rule simply does nothing.

The fix is to move the filter, not edit it: inbound on R0's inside interface, before translation, where the real source addresses still exist. Filter as close to the source as possible, and always before NAT.

Findings 1, 2 and 4 all sit on the same path, which is why a single "can VLAN 2 reach the server" check cannot tell them apart. That is the reason the repository ships a verification order rather than a checklist.

How I isolated it

Three of the findings sit on the same path, so a single “can VLAN 2 reach the server” test cannot tell them apart. I separated them by choosing a test that only one of them could explain.

Reachability first: a ping from a VLAN 2 host to R0 isolates the missing default route on S0, because nothing downstream is involved yet. Translation next: show ip nat translations lists an entry even when the ping never completes, which separates “NAT is working” from “the destination is reachable”; running pings from three hosts at once against a two-address pool shows where that pool runs out. The filter last: in Simulation mode I stopped a packet at R1 and read its source address, 20.10.2.100, which is the whole explanation—the rule was written for an address that no longer exists at that point in the path. Moving it inbound on R0 confirmed it.

The .pkt file is kept exactly as built, so the original behaviour is still there to walk through.

Resources