A 28-person law firm, two floors, one server closet, and a legal obligation to keep client files secret. We go from the brief to a working Cisco network, built bottom-up in 13 steps and tested at every layer before moving on: VLAN and address plan, an inter-VLAN policy matrix enforced on the core, 802.1X on every desk port, a guest network forced through the firewall and blocked twice, NAT and a zone-based firewall at the edge, dual-WAN failover, full-tunnel VPN for lawyers working remotely, voice QoS, and backups that ransomware can't reach. Then we test it the way an attacker would.
Full network · all steps built
highlighted = lines added in the selected step · earlier steps shown plain · later steps hidden
This is the first post in the Build series. Each one takes one real kind of business and designs its network from nothing. The architecture guides explain the patterns in the abstract, and the labs teach one technology at a time on a made-up network. A Build post goes the other way: it starts from a client brief, and every VLAN, ACL line and line of config has to trace back to something in that brief.
Why a law firm first? It is the smallest kind of business where confidentiality is a legal duty rather than a preference. The firm holds privileged client files, it handles opposing parties' documents, and it has a regulator who will ask how those files were protected. That turns segmentation from a nice-to-have into the core of the design, which makes it a good teaching case.
01
Before any switch is chosen, write down who works there, what they handle, and what would hurt them. The design comes from this list.
The client is a fictional but typical Greek commercial-law practice. There are four partners, eight associates, eight paralegals, two secretaries, a receptionist, two people in accounts, and three trainees: 28 people across two floors of a renovated building. The firm runs a document management system (DMS) that holds every matter file, a Windows domain for identity, hosted VoIP, two multifunction printers that scan to folders, and a CCTV system with door access. Clients come in for meetings and expect Wi-Fi. Partners work from home two days a week and reach court e-filing portals from wherever they are.
| Requirement | Where it comes from, and what it forces in the design |
|---|---|
| R1 Confidentiality | Professional secrecy and GDPR Art. 32. Client files must be reachable only by people with a reason to see them, so the servers sit in their own zone behind a default-deny policy. |
| R2 Visitors | Clients and opposing counsel sit in meeting rooms with laptops, so the guest network must have no route into the firm, not just a firewall rule. |
| R3 Identity at the port | A visitor who plugs into a wall socket in a meeting room or an empty office must not land on the lawyers' network. That means 802.1X on every desk port. |
| R4 Remote work | Partners work from home and hotels, so remote access gets the same controls as the office (full tunnel, MFA). |
| R5 Deadlines | A missed court filing deadline is malpractice, so internet access must survive a fibre cut (dual WAN with automatic failover). |
| R6 Ransomware | Law firms are a favourite ransomware target because they pay. Backups must be unreachable from user machines and immutable offsite. |
| R7 Voice | Hosted VoIP has to stay clear while someone uploads a 2 GB evidence bundle, so voice gets priority queuing at the WAN edge. |
| R8 Small IT | The firm has no IT staff; an outside contractor (us) manages it. The design must be boring, documented, and remotely manageable, with nothing clever that needs a specialist. |
Law firms sometimes have to build an ethical wall (also called a "Chinese wall") between two teams, for example when one partner's former client is now on the other side of a matter. It is tempting to do that in the network with a VLAN per practice group. Don't. Matter-level access belongs in the DMS's own permissions, where it follows the person and the file. The network's job is coarser: keep categories of device apart (people, servers, guests, cameras). Trying to model which lawyer can see which matter with ACLs gives you an unmanageable policy that the first reorganisation of practice groups will break.
02
Most of the design is forced by the brief. These four decisions aren't, and each one is a trade-off worth stating out loud.
With 28 users, two floors and about 60 ports, one L3 core switch with two access switches is plenty (see the topology guide). The core is a single point of failure, and we accept that on purpose: a cold-spare C9200 on the shelf with the config backed up restores service in 20 minutes, while a stacked or redundant core would double the switching budget to protect against a failure that happens perhaps once a decade. The brief's real availability risk is the WAN (R5), so that's where the redundancy money goes.
Inter-VLAN routing could happen on the core switch, at line rate, with stateless ACLs. Or it could happen on R1's zone-based firewall, which is stateful but sends all east-west traffic through a branch router. A C1111 handles a few hundred Mbps with ZBF enabled, while a DMS sync or a scan-to-folder burst easily fills a 1G port. So routing and ACLs live on the core, the stateful firewall guards the internet edge, and step 5 deals honestly with the cost of stateless ACLs.
VLAN 50 (guest) is carried through the core at Layer 2 only and terminates on R1. The core has no address in the guest subnet, so it can never route guest traffic directly into another VLAN. Every guest packet has to go through R1, where it meets the only stateful firewall in the building, with no GUEST→INSIDE zone pair (drop by default). As a second control, an ACL on the core's transit interface drops anything sourced from the guest subnet. A guest reaches a client file only if both of those are wrong at the same time. Step 7 shows why the second control matters.
Every desk port starts in a dead "parking" VLAN. A machine that passes 802.1X (domain machine certificate, checked by NPS on the domain controller) is placed in VLAN 10 or 20 according to its AD group. Phones and printers, which can't do 802.1X, fall back to MAC Authentication Bypass (MAB). Anything else gets nothing. Moving a lawyer to a different office then needs no switch change at all, which matters for R8.
03
One /16 for the site, one /24 per VLAN, and the VLAN number matches the third octet. The contractor who opens this network in three years will thank you.
| VLAN · subnet | Who lives here · gateway · DHCP |
|---|---|
| 10 LAWYERS · 10.20.10.0/24 | Partners, associates, trainees (802.1X dynamic). GW .1 on CORE · DHCP from DC01. |
| 20 STAFF · 10.20.20.0/24 | Paralegals, secretaries, reception, accounts. GW .1 on CORE · DHCP from DC01. |
| 30 SERVERS · 10.20.30.0/24 | DC01 .10 · DMS01 .20 · FS01 .21 · NAS01 .30. Static addresses, GW .1 on CORE. |
| 40 VOICE · 10.20.40.0/24 | Desk phones (voice VLAN via CDP/LLDP). GW .1 on CORE · DHCP from DC01. |
| 45 PRINT · 10.20.45.0/24 | 2× MFP (MAB). DHCP reservations on DC01. |
| 50 GUEST · 10.20.50.0/24 | L2 only on the core. GW .1 and DHCP on R1, public DNS. |
| 60 SECURITY · 10.20.60.0/24 | NVR .10, 6 cameras, door controller. No internet. GW .1 on CORE. |
| 99 MGMT · 10.20.99.0/24 | Switch, AP and UPS management. CORE .1 (also the switch's own address), ACC-1 .11, ACC-2 .12, monitoring box .20, APs .21–.24. All static. |
| 666 PARKING · none | Unauthenticated ports and trunk native VLAN. No SVI, no DHCP: a dead end. |
| 900 TRANSIT · 10.20.255.0/29 | R1 .1 ↔ CORE .2. The only routed link between the LAN and the edge. |
| VPN · 10.20.200.0/24 | IKEv2 client pool on R1, firewalled as its own zone. |
Here is how the plan maps onto the building. Colour is VLAN, and it is the same colour key used in every diagram in this post:
Each desk has one cable run: the phone's built-in switch passes the PC through (PC in VLAN 10/20 untagged, phone in VLAN 40 tagged). Floor 1 needs 16 staff desks + reception + MFP-1 + 4 meeting-room wall ports + 2 APs + 6 cameras + the NVR + the door controller = 32 ports, so ACC-1 is a 48-port switch. Floor 2 needs 12 offices + MFP-2 + 2 APs + 2 meeting-room ports = 17, so a 24-port switch fits. PoE budget: 28 phones at ~5 W, 4 Wi-Fi 6 APs at up to ~20 W, and 6 cameras at ~7 W total roughly 260 W across both switches, inside a 370 W PoE+ budget per switch with room to grow.
04
This table is the actual security design. The build steps that follow just put it into config.
Read each row as "traffic starting from this zone may reach that column". The default is deny; every allow is there because a requirement in section 01 asked for it. "Limited" means allowed only for one host or port, as noted in the cell.
Three cells are worth explaining because they are where real networks go wrong:
04b
Every requirement from the brief, the steps that implement it, the config that does it, and the test that proves it. This is the table a client or an auditor actually asks for.
| Requirement | Implemented in | Key config | Proven by |
|---|---|---|---|
| R1 Confidentiality | step 5 · step 6 · step 13 | Inbound SVI ACLs V10-IN … V60-IN; NPS policies per computer group; NAS reachable from no user VLAN | "Staff sweep" drill, section 19 |
| R2 Visitors | step 1 · step 7 · step 8 | Meeting-room ports fixed to V50; no Vlan50 SVI; V900-IN backstop; no GUEST→INSIDE zone pair | "Guest sweep" drill; step 8 checkpoint with V900-IN removed |
| R3 Identity at the port | step 1 · step 6 | Desk ports in VLAN 666; 802.1X then MAB; critical VLAN 20 | "Unknown laptop" and "NPS down" drills |
| R4 Remote work | step 11 | FlexVPN full tunnel; VPN zone; VPN-TO-INSIDE; RADIUS reply line 72 | Step 11 checkpoint (hotspot test, tracert) |
| R5 Deadlines | step 9 · step 10 | Route-map NAT per WAN; IP SLA + pinned probe + Null0; EEM NAT flush | "Fibre cut" drill |
| R6 Ransomware | step 5 · step 13 | No ACL line to NAS01; NAS pulls; object-lock offsite; GPO host firewall | "Restore" drill (timed) |
| R7 Voice | step 12 | WAN-OUT shaper + LLQ for EF; SIP ALG off | "Upload flood" drill |
| R8 Small IT | step 6 · section 18 | VLAN by identity, not by socket; management baseline; config archive and syslog | Moving a lawyer needs no switch change; config diffs at the monitoring VM |
The build
Build it the way you'd troubleshoot it: start where the users plug in and work up towards the internet, and don't move up until the current layer passes its checkpoint.
Everything above was planning. From here we build in 13 steps, starting with the endpoints and access switches, then the wireless, the core, the servers, the policy on the core, the edge router, the two ISPs, and finally the remote users. Each step opens with the same topology: what's already built is solid, what this step adds is highlighted in orange, and what comes later is faded. Each step ends with a checkpoint. If a checkpoint fails, the fault is in the layer you just added, because everything below it has already been tested.
Test-PC tip: Windows Firewall blocks inbound ping by default. Enable the "File and Printer Sharing (Echo Request – ICMPv4-In)" rule on the test PCs, or every ping checkpoint below will fail for reasons that have nothing to do with the network.
Building bottom-up also means each layer's tests can't be confused by the layers above. When a lawyer's PC can't reach the DMS at step 4, there's no firewall, NAT or VPN yet that could be the cause.
05 · Step 1 of 13
Two switches, every desk, printer and camera plugged in, and every port in its VLAN. No routing yet: each VLAN is still its own island.
▲ Show step 1 in the interactive topology · see what this step adds, and click any device for its config
Rack ACC-1 in the floor-1 closet and ACC-2 in the floor-2 cupboard, and patch every outlet. Both switches get the same VLAN database (VTP transparent, so nothing gets learned by accident) and rapid PVST+. For now the desk ports are statically assigned to their VLAN, which lets us test the cabling and VLANs without depending on anything else. Step 6 replaces this with 802.1X.
hostname ACC-1 vtp mode transparent spanning-tree mode rapid-pvst ! vlan 10 name LAWYERS vlan 20 name STAFF vlan 30 name SERVERS vlan 40 name VOICE vlan 45 name PRINT vlan 50 name GUEST vlan 60 name SECURITY vlan 99 name MGMT vlan 666 name PARKING ! ! desks: PC behind the phone. TEMPORARY static VLAN, replaced in step 6 interface range GigabitEthernet1/0/1 - 16 description DESK staff (phone + PC) switchport mode access switchport access vlan 20 switchport voice vlan 40 spanning-tree portfast spanning-tree bpduguard enable interface GigabitEthernet1/0/17 description RECEPTION PC switchport mode access switchport access vlan 20 spanning-tree portfast spanning-tree bpduguard enable interface GigabitEthernet1/0/25 description MFP-1 switchport mode access switchport access vlan 45 spanning-tree portfast ! ! meeting-room wall sockets: guest, nothing else, no switches interface range GigabitEthernet1/0/41 - 44 description MEETING-ROOM wall ports switchport mode access switchport access vlan 50 switchport port-security maximum 2 switchport port-security violation restrict switchport port-security spanning-tree portfast spanning-tree bpduguard enable ! ! cameras, door controller, NVR: pinned MACs interface range GigabitEthernet1/0/33 - 40 description SECURITY (cams 33-38 · NVR 39 · door controller 40) switchport mode access switchport access vlan 60 switchport port-security mac-address sticky switchport port-security spanning-tree portfast spanning-tree bpduguard enable ! ! anything not patched: shut, parked (Gi1/0/21-22 are the APs, step 2) interface range GigabitEthernet1/0/18 - 20 , GigabitEthernet1/0/23 - 24 , GigabitEthernet1/0/26 - 32 , GigabitEthernet1/0/45 - 48 switchport access vlan 666 shutdown ! interface Vlan99 ip address 10.20.99.11 255.255.255.0 ip default-gateway 10.20.99.1 ! doesn't exist yet: arrives with the core in step 3
# ACC-1 — CRS354-48P-4S+2Q+ (RouterOS 7)
/interface bridge add name=bridge vlan-filtering=no
:for i from=1 to=16 do={
/interface bridge port add bridge=bridge interface=("ether" . $i) pvid=20 \
frame-types=admit-only-untagged-and-priority-tagged comment="desk (PC behind phone)"
}
/interface bridge port add bridge=bridge interface=ether17 pvid=20 comment="reception PC"
/interface bridge port add bridge=bridge interface=ether25 pvid=45 comment="MFP-1"
:for i from=41 to=44 do={ /interface bridge port add bridge=bridge interface=("ether" . $i) pvid=50 comment="meeting room" }
:for i from=33 to=40 do={ /interface bridge port add bridge=bridge interface=("ether" . $i) pvid=60 learn=no comment="security" }
/interface bridge host add bridge=bridge interface=ether33 mac-address=AC:CC:8E:00:00:21 # one per camera
{
:local t "sfp-sfpplus1"
:for i from=1 to=16 do={ :set t ($t . ",ether" . $i) }
/interface bridge vlan add bridge=bridge vlan-ids=40 tagged=$t # voice VLAN on the desk ports
}
/interface bridge vlan add bridge=bridge vlan-ids=10,20,45,50,60 tagged=sfp-sfpplus1
/interface bridge vlan add bridge=bridge vlan-ids=99 tagged=bridge,sfp-sfpplus1
/ip neighbor discovery-settings set lldp-med-net-policy-vlan=40 # phones learn VLAN 40
/interface bridge set bridge vlan-filtering=yes
# no "port-security maximum 2": meeting ports rely on the guest VLAN having nowhere to goACC-2 is the same pattern: Gi1/0/1-12 lawyer desks in VLAN 10 with voice VLAN 40, Gi1/0/15 MFP-2 in VLAN 45, Gi1/0/19-20 meeting-room wall ports in VLAN 50, and management address 10.20.99.12.
CCTV cameras are mounted on the outside of the building, at the entrance, where anyone with a ladder can reach the cable. Unplug the camera, plug in a laptop, and on a typical SMB network you are on the LAN. Here the sticky MAC shuts the port down the moment a different MAC shows up, and VLAN 60 gets no route anywhere once step 5 applies its ACL. This is the cheapest physical-intrusion control in the whole post.
show vlan brief on both switches: every port listed in the VLAN you expect, unused ports in 666.show port-security interface Gi1/0/33: a sticky MAC has been learned for each camera.06 · Step 2 of 13
An SSID is an access port without the cable. Two APs per floor, two SSIDs, each mapped to a VLAN that already exists.
▲ Show step 2 in the interactive topology · see what this step adds, and click any device for its config
Four Catalyst 9115AXI APs, two per floor, with the Embedded Wireless Controller running on one of them, so there is no separate controller to buy. Each AP gets a static management address in VLAN 99 (10.20.99.21–.24), since VLAN 99 deliberately has no DHCP scope. Traffic is switched locally (FlexConnect): each SSID drops onto its VLAN at the AP's own switch port, so the core routes wireless clients exactly like wired ones and the same SVI ACLs apply to both.
| SSID | Security · VLAN · notes |
|---|---|
| FIRM | WPA3-Enterprise (WPA2/3 transition for older laptops) · 802.1X to NPS · AAA override places lawyers in 10 and staff in 20 from the same policies as wired · 5/6 GHz preferred |
| FIRM-GUEST | WPA3-Personal with a PSK rotated monthly and printed on the meeting-room card · VLAN 50 · peer-to-peer blocking on, so one client's laptop can't reach another's · rate-limited at R1 |
| (no third SSID) | Phones are wired. Every additional SSID costs airtime on every channel; two is the right number. |
interface range GigabitEthernet1/0/21 - 22
description AP (FlexConnect local switching)
switchport mode trunk
switchport trunk native vlan 99 ! AP management + CAPWAP to the EWC
switchport trunk allowed vlan 10,20,50,99
switchport nonegotiate
spanning-tree portfast trunkshow cdp neighbors on each access switch shows its two APs on Gi1/0/21-22.show ap summary lists all four APs as registered.show mac address-table vlan 50). It gets no address yet: the guest DHCP server is R1, which arrives in step 7.07 · Step 3 of 13
One L3 switch joins the floors with LACP and gives every routed VLAN a gateway. At this point everything can reach everything; the next steps close that down.
▲ Show step 3 in the interactive topology · see what this step adds, and click any device for its config
hostname CORE vtp mode transparent spanning-tree mode rapid-pvst spanning-tree vlan 1-4094 priority 4096 ! the core is root, always ip routing ! (same VLAN database as the access switches, plus:) vlan 900 name TRANSIT ! interface range GigabitEthernet1/1/1 - 2 description to ACC-1 channel-group 1 mode active interface range GigabitEthernet1/1/3 - 4 description to ACC-2 channel-group 2 mode active interface range Port-channel1 - 2 switchport mode trunk switchport trunk native vlan 666 switchport trunk allowed vlan 10,20,40,45,50,60,99 switchport nonegotiate ! interface Vlan10 description LAWYERS ip address 10.20.10.1 255.255.255.0 no ip redirects no ip proxy-arp interface Vlan20 description STAFF ip address 10.20.20.1 255.255.255.0 interface Vlan40 description VOICE ip address 10.20.40.1 255.255.255.0 interface Vlan45 description PRINT ip address 10.20.45.1 255.255.255.0 interface Vlan60 description SECURITY ip address 10.20.60.1 255.255.255.0 interface Vlan99 description MGMT ip address 10.20.99.1 255.255.255.0 ! deliberately NO "interface Vlan50": guest is switched here, never routed
# CORE — CRS326-24S+2Q+ as a Layer 2 core. # The SVIs move to R1 (a CCR2004): MikroTik switches route in hardware, but not with a firewall # on every inter-VLAN packet, which this design needs. See the appendix. /interface bonding add name=bond-acc1 slaves=sfp-sfpplus1,sfp-sfpplus2 mode=802.3ad transmit-hash-policy=layer-2-and-3 add name=bond-acc2 slaves=sfp-sfpplus3,sfp-sfpplus4 mode=802.3ad transmit-hash-policy=layer-2-and-3 /interface bridge add name=bridge vlan-filtering=no priority=0x1000 # STP root /interface bridge port add bridge=bridge interface=bond-acc1 frame-types=admit-only-vlan-tagged add bridge=bridge interface=bond-acc2 frame-types=admit-only-vlan-tagged add bridge=bridge interface=sfp-sfpplus24 frame-types=admit-only-vlan-tagged comment="R1 (CCR2004)" /interface bridge vlan add bridge=bridge vlan-ids=10,20,30,40,45,50,60,99 tagged=bond-acc1,bond-acc2,sfp-sfpplus24 /interface bridge set bridge vlan-filtering=yes # on R1 (CCR2004): one VLAN interface per routed VLAN replaces each Cisco SVI /interface vlan add name=v10-lawyers interface=bridge vlan-id=10 /ip address add address=10.20.10.1/24 interface=v10-lawyers # … the same for 20, 30, 40, 45, 60, 99
interface range GigabitEthernet1/1/1 - 2 description to CORE channel-group 1 mode active interface Port-channel1 switchport mode trunk switchport trunk native vlan 666 switchport trunk allowed vlan 10,20,40,45,50,60,99 switchport nonegotiate
show etherchannel summary: Po1(SU) and Po2(SU), both member ports flagged (P).show spanning-tree root on an access switch: the root bridge is CORE for every VLAN.ping 10.20.99.11 and ssh to both access switches over VLAN 99.08 · Step 4 of 13
DC01 becomes the source of addresses, names and (later) port authentication. The core relays DHCP to it, and the access switches start trusting only the uplink for DHCP.
▲ Show step 4 in the interactive topology · see what this step adds, and click any device for its config
The servers are VMs on one host (HV01, see the rack in section 22), connected to core ports Gi1/0/5-8 in VLAN 30 with static addresses. DC01 runs AD DS, DNS, DHCP and, from step 6, NPS. On the network side there are two jobs: get DHCP requests from every VLAN to DC01, and stop rogue DHCP servers on the access ports.
interface range GigabitEthernet1/0/5 - 8 description SERVERS (DC01 DMS01 FS01 NAS01) switchport mode access switchport access vlan 30 spanning-tree portfast ! interface Vlan10 ip helper-address 10.20.30.10 interface Vlan20 ip helper-address 10.20.30.10 interface Vlan40 ip helper-address 10.20.30.10 interface Vlan45 ip helper-address 10.20.30.10 interface Vlan30 description SERVERS ip address 10.20.30.1 255.255.255.0
| DC01 DHCP scope | Options (003 router · 006 DNS · 015 domain) |
|---|---|
| 10.20.10.0/24 | .50–.250 · 10.20.10.1 · 10.20.30.10 · firm.local · 8-day lease |
| 10.20.20.0/24 | .50–.250 · 10.20.20.1 · 10.20.30.10 · firm.local |
| 10.20.40.0/24 | .50–.250 · 10.20.40.1 · 10.20.30.10 · plus the VoIP provider's provisioning URL (option 66) |
| 10.20.45.0/24 | reservations only, for MFP-1 and MFP-2 by MAC |
ip dhcp snooping vlan 10,20,40,45,50 no ip dhcp snooping information option ! else Windows DHCP drops relayed option-82 requests ip dhcp snooping interface Port-channel1 ip dhcp snooping trust ip arp inspection trust ! ! APs carry dozens of clients: the default 15 ARP pps on an untrusted port err-disables them interface range GigabitEthernet1/0/21 - 22 ip arp inspection limit rate 100 ! ! only AFTER every client has a real DHCP lease (see gotcha) ip arp inspection vlan 10,20,45,50
Dynamic ARP Inspection drops ARP from any host whose IP/MAC pair isn't in the DHCP snooping binding table. The static test PCs from steps 1–3 aren't in it, so the moment DAI is enabled they go silent, and it looks as if step 4 broke routing. Switch the test PCs to DHCP, confirm they appear in show ip dhcp snooping binding, and only then enable ip arp inspection. Hosts that really are static (the NVR and cameras in VLAN 60) are simply not in a DAI VLAN.
ipconfig /all).show ip dhcp snooping binding on ACC-2 lists it on the right port and VLAN.DHCP_SNOOPING_UNTRUSTED_PORT).nslookup dms01.firm.local resolves.09 · Step 5 of 13
One inbound ACL per SVI, written as "what this zone may start". This is the policy matrix from section 04, written as config.
After step 4, everything inside can reach everything inside. This step applies the matrix. The animation shows the end state: the lawyer's packet is permitted, the staff packet dies at the ingress SVI, and the guest packet never gets routed by the core at all (it crosses at Layer 2 to R1, which arrives in step 7).
The pattern for every user VLAN is the same: let DHCP through, allow the specific internal services from the matrix, deny all private address space (and log it), then allow the internet. Putting the internal deny before the internet permit is the line that does the work; without it, permit ip any any would quietly allow everything inside too.
ip access-list extended V10-IN remark LAWYERS: DC, DMS, files, print, internet. Nothing else inside. 10 permit udp any any eq bootps 15 permit icmp any host 10.20.10.1 ! the helpdesk pings the gateway first 20 permit ip 10.20.10.0 0.0.0.255 host 10.20.30.10 ! DC01: AD needs too many ports to list 30 permit tcp 10.20.10.0 0.0.0.255 host 10.20.30.20 eq 443 40 permit tcp 10.20.10.0 0.0.0.255 host 10.20.30.21 eq 445 50 permit tcp 10.20.10.0 0.0.0.255 10.20.45.0 0.0.0.255 eq 9100 ! raw print only: MFP web UI is MGMT-only 60 permit tcp 10.20.10.0 0.0.0.255 10.20.99.0 0.0.0.255 established ! replies to remote support 70 deny ip any 10.0.0.0 0.255.255.255 log 80 deny ip any 172.16.0.0 0.15.255.255 90 deny ip any 192.168.0.0 0.0.255.255 100 permit ip 10.20.10.0 0.0.0.255 any ! ip access-list extended V20-IN remark STAFF: DC, DMS web only, print, reception->NVR, internet 10 permit udp any any eq bootps 15 permit icmp any host 10.20.20.1 20 permit ip 10.20.20.0 0.0.0.255 host 10.20.30.10 30 permit tcp 10.20.20.0 0.0.0.255 host 10.20.30.20 eq 443 40 permit tcp 10.20.20.0 0.0.0.255 10.20.45.0 0.0.0.255 eq 9100 50 permit tcp host 10.20.20.50 host 10.20.60.10 eq 443 ! reception PC only 60 permit tcp 10.20.20.0 0.0.0.255 10.20.99.0 0.0.0.255 established 70 deny ip any 10.0.0.0 0.255.255.255 log 80 deny ip any 172.16.0.0 0.15.255.255 90 deny ip any 192.168.0.0 0.0.255.255 100 permit ip 10.20.20.0 0.0.0.255 any ! ip access-list extended V40-IN remark VOICE: DNS/NTP from DC01, then hosted PBX on the internet 10 permit udp any any eq bootps 20 permit udp 10.20.40.0 0.0.0.255 host 10.20.30.10 eq domain 30 permit udp 10.20.40.0 0.0.0.255 host 10.20.30.10 eq ntp 40 deny ip any 10.0.0.0 0.255.255.255 log 50 deny ip any 172.16.0.0 0.15.255.255 60 deny ip any 192.168.0.0 0.0.255.255 70 permit ip 10.20.40.0 0.0.0.255 any ! ip access-list extended V45-IN remark PRINT: replies, DNS/NTP, LDAPS, scan-to-folder, scan-to-email 10 permit udp any any eq bootps 20 permit tcp 10.20.45.0 0.0.0.255 10.20.0.0 0.0.255.255 established 30 permit udp 10.20.45.0 0.0.0.255 host 10.20.30.10 eq domain 35 permit udp 10.20.45.0 0.0.0.255 host 10.20.30.10 eq ntp 36 permit tcp 10.20.45.0 0.0.0.255 host 10.20.30.10 eq 636 ! LDAPS address book 40 permit tcp 10.20.45.0 0.0.0.255 host 10.20.30.21 eq 445 ! scan-to-folder 50 deny ip any 10.0.0.0 0.255.255.255 log 60 deny ip any 172.16.0.0 0.15.255.255 70 deny ip any 192.168.0.0 0.0.255.255 80 permit tcp 10.20.45.0 0.0.0.255 any eq 587 ! scan-to-email (M365) 90 deny ip any any log
# R1 (CCR2004) — the same policy as a STATEFUL forward chain /ip firewall address-list add list=DC address=10.20.30.10 add list=DMS address=10.20.30.20 add list=FS address=10.20.30.21 /interface list add name=USERS /interface list member add list=USERS interface=v10-lawyers add list=USERS interface=v20-staff add list=USERS interface=v40-voice /ip firewall filter add chain=forward action=accept connection-state=established,related,untracked add chain=forward action=drop connection-state=invalid add chain=forward action=accept in-interface=v10-lawyers dst-address-list=DC add chain=forward action=accept in-interface=v10-lawyers dst-address-list=DMS protocol=tcp dst-port=443 add chain=forward action=accept in-interface=v10-lawyers dst-address-list=FS protocol=tcp dst-port=445 add chain=forward action=accept in-interface=v10-lawyers out-interface=v45-print protocol=tcp dst-port=9100 add chain=forward action=accept in-interface=v20-staff dst-address-list=DC add chain=forward action=accept in-interface=v20-staff dst-address-list=DMS protocol=tcp dst-port=443 add chain=forward action=accept in-interface=v20-staff out-interface=v45-print protocol=tcp dst-port=9100 add chain=forward action=accept src-address=10.20.20.50 dst-address=10.20.60.10 protocol=tcp dst-port=443 add chain=forward action=accept in-interface-list=USERS out-interface-list=WAN add chain=forward action=drop log=yes log-prefix=FWD-DROP # no "established" flags, no per-UDP-reply lines: connection tracking handles every reply
The server, security and management VLANs are written the other way round. They mostly answer, so their ACLs permit replies plus a short list of things they genuinely need to start:
ip access-list extended V30-IN remark SERVERS: replies to the LAN, plus a short list they may start 10 permit tcp 10.20.30.0 0.0.0.255 10.20.0.0 0.0.255.255 established 20 permit udp host 10.20.30.10 eq domain 10.20.0.0 0.0.255.255 30 permit udp host 10.20.30.10 eq 88 10.20.0.0 0.0.255.255 40 permit udp host 10.20.30.10 eq 389 10.20.0.0 0.0.255.255 50 permit udp host 10.20.30.10 eq ntp 10.20.0.0 0.0.255.255 60 permit udp host 10.20.30.10 eq bootps 10.20.0.0 0.0.255.255 ! DHCP offers to the relay 70 permit udp host 10.20.30.10 eq 1812 10.20.99.0 0.0.0.255 ! RADIUS replies: see gotcha 75 permit udp host 10.20.30.10 eq 1813 10.20.99.0 0.0.0.255 80 permit icmp 10.20.30.0 0.0.0.255 10.20.0.0 0.0.255.255 echo-reply 90 deny ip any 10.0.0.0 0.255.255.255 log 100 deny ip any 172.16.0.0 0.15.255.255 110 deny ip any 192.168.0.0 0.0.255.255 120 permit udp host 10.20.30.10 any eq domain ! DC01 forwarders 130 permit udp host 10.20.30.10 any eq ntp 140 permit tcp 10.20.30.0 0.0.0.255 any eq 443 ! updates + offsite backup 150 deny ip any any log ! ip access-list extended V60-IN remark SECURITY: answers reception, syncs time, otherwise mute 10 permit tcp host 10.20.60.10 eq 443 host 10.20.20.50 established 20 permit udp 10.20.60.0 0.0.0.255 host 10.20.30.10 eq ntp 30 deny ip any any log ! no internet, ever ! ip access-list extended V99-IN 10 permit ip 10.20.99.0 0.0.0.255 10.20.0.0 0.0.255.255 20 permit tcp 10.20.99.0 0.0.0.255 any eq 443 ! firmware downloads 30 deny ip any any log
The first draft of V30-IN had no lines 70–75. The access switches send their RADIUS requests from Vlan99 to DC01; that direction is fine. But NPS's reply comes back into the Vlan30 SVI, and RADIUS is UDP, so established doesn't match it. The ACL dropped every Access-Accept, the switches marked NPS as dead, and every desk port fell into the critical VLAN at once. The log line that gave it away was %SEC-6-IPACCESSLOGP: list V30-IN denied udp 10.20.30.10(1812) -> 10.20.99.11. When a stateless ACL protects a server that answers over UDP, every UDP reply needs its own line.
established only checks that the ACK or RST bit is set. It is not connection tracking. Someone already on the server VLAN can still send crafted ACK packets toward user VLANs (useful for mapping hosts, though it can't open a connection). More importantly, none of these ACLs stop lateral movement inside one VLAN: lawyer-to-lawyer SMB never passes through an SVI. That is where ransomware spreads, so it gets a host-level control: a GPO that turns on the Windows Firewall on every workstation and blocks inbound SMB/RPC/WinRM from anything except the management subnet. The switch handles traffic between categories; the endpoint handles traffic between peers.
interface Vlan10 ip access-group V10-IN in interface Vlan20 ip access-group V20-IN in interface Vlan30 ip access-group V30-IN in interface Vlan40 ip access-group V40-IN in interface Vlan45 ip access-group V45-IN in interface Vlan60 ip access-group V60-IN in interface Vlan99 ip access-group V99-IN in
Test-NetConnection 10.20.30.21 -Port 445 fails, Test-NetConnection 10.20.30.20 -Port 443 succeeds.\\FS01\Scans.show access-lists V20-IN: hit counters rising on line 70 while you test the denies, with matching %SEC-6-IPACCESSLOGP lines in the log.10 · Step 6 of 13
The static desk VLANs from step 1 go away. Every desk port now starts in a dead VLAN, and the device has to prove what it is to get onto the network.
username netadmin privilege 15 secret <local-break-glass> aaa new-model aaa authentication login default local ! set this BEFORE anything else: no lockout ! radius server NPS address ipv4 10.20.30.10 auth-port 1812 acct-port 1813 key <radius-shared-secret> aaa group server radius RAD-NPS server name NPS ip radius source-interface Vlan99 aaa authentication dot1x default group RAD-NPS aaa authorization network default group RAD-NPS aaa accounting dot1x default start-stop group RAD-NPS radius-server dead-criteria time 5 tries 3 radius-server deadtime 10 dot1x system-auth-control ! interface range GigabitEthernet1/0/1 - 17 ! ACC-2: 1 - 12 description DESK (phone + PC behind it) switchport mode access switchport access vlan 666 ! dead end until proven otherwise switchport voice vlan 40 authentication host-mode multi-domain ! one data + one voice device authentication order dot1x mab authentication priority dot1x mab authentication port-control auto authentication periodic authentication timer reauthenticate server authentication event fail action next-method authentication event server dead action authorize vlan 20 authentication event server dead action authorize voice authentication event server alive action reinitialize mab dot1x pae authenticator dot1x timeout tx-period 7 spanning-tree portfast spanning-tree bpduguard enable
# ACC-1 / ACC-2 — RouterOS dot1x server (CRS3xx) with NPS as RADIUS
/radius add service=dot1x address=10.20.30.10 secret="<radius-shared-secret>" src-address=10.20.99.11
/interface dot1x server
add interface=ether1 auth-types=dot1x,mac-auth reject-vlan-id=666 server-fail-vlan-id=20 \
comment="desk 1: machine certificate, or MAC for printers"
# … one entry per desk port. NPS returns the VLAN (Tunnel-Pvt-Group-ID) exactly as for Cisco.
# Check the property names on your release; they've changed between RouterOS 7 versions.
/interface bridge port set [find interface=ether1] pvid=666 # dead end until authenticatedThese are the classic authentication commands. Current IOS-XE still accepts them, and authentication convert-to new-style rewrites them as IBNS 2.0 policy-maps if you prefer that form.
On the NPS side, three network policies do all the work. LAW-WIRED matches the AD group LAW-Lawyer-Computers with EAP-TLS and returns Tunnel-Type = VLAN, Tunnel-Medium-Type = 802, Tunnel-Pvt-Group-ID = 10. STAFF-WIRED does the same with group LAW-Staff-Computers → 20. MAB-DEVICES matches the phones and MFPs and returns VLAN 45 for the printers and cisco-av-pair = device-traffic-class=voice for the phones. Because policies match on computer groups, a lawyer logging into a staff PC stays on the staff VLAN: the machine is what gets authenticated, not the person.
DC01 reboots every Patch Tuesday. If the switches fail closed, every desk goes dark for the duration, and for a firm with a filing deadline at 15:00 that is not acceptable. So the server dead lines put data devices into STAFF (VLAN 20): they can reach the DMS and the internet but not the partner file shares, and voice keeps working. That is a deliberate, written trade-off between R3 and R5. The proper fix is a second domain controller running NPS (section 22 budgets for it), so that "server dead" never actually fires.
NPS authenticates MAB requests as if they were user logins: each MAC needs an AD user object whose name and password are the MAC address. For 2 MFPs that's fine. For 28 phones it is a chore, and the accounts are a weak spot (anyone who reads a phone's MAC from its label can spoof it, which is the inherent weakness of MAB). Contain it: the voice VLAN can only reach DNS and NTP on DC01 plus the internet (step 5), so a spoofed "phone" gets very little. If the firm grows past roughly 50 devices, a small FreeRADIUS server or Cisco ISE handles MAB properly.
show access-session interface Gi1/0/7 details: Authorized, method dot1x, VLAN 10 for a lawyer PC.VOICE domain, method mab.11 · Step 7 of 13
R1 arrives, but only on the inside for now: a transit link to the core, the guest VLAN terminated on its own interface, and a guest DHCP pool. No internet yet.
▲ Show step 7 in the interactive topology · see what this step adds, and click any device for its config
R1 is a C1111-8P: two routed WAN ports and an 8-port switch. The trunk from the core lands on switchport Gi0/1/0 and carries only VLANs 50 and 900. R1 therefore has exactly two inside interfaces: the routed transit link to the core, and the guest network, which never touches the core's routing table.
hostname R1-EDGE vlan 50 name GUEST vlan 666 name PARKING vlan 900 name TRANSIT interface GigabitEthernet0/1/0 description CORE Gi1/0/1 switchport mode trunk switchport trunk native vlan 666 switchport trunk allowed vlan 50,900 ! interface Vlan900 description TRANSIT to CORE ip address 10.20.255.1 255.255.255.248 interface Vlan50 description GUEST (terminates here, not on the core) ip address 10.20.50.1 255.255.255.0 ! ip dhcp excluded-address 10.20.50.1 10.20.50.9 ip dhcp pool GUEST network 10.20.50.0 255.255.255.0 default-router 10.20.50.1 dns-server 9.9.9.9 1.1.1.1 ! guests never touch DC01, not even for DNS lease 0 4 ! ! policy-map first: IOS rejects a service-policy that names an undefined map policy-map GUEST-LIMIT class class-default police cir 50000000 conform-action transmit exceed-action drop interface Vlan50 service-policy input GUEST-LIMIT service-policy output GUEST-LIMIT ! ip route 10.20.0.0 255.255.0.0 10.20.255.2
interface GigabitEthernet1/0/1 description R1-EDGE Gi0/1/0 switchport mode trunk switchport trunk native vlan 666 switchport trunk allowed vlan 50,900 switchport nonegotiate ! ip access-list extended V900-IN remark Backstop: nothing sourced from the guest subnet is ever routed inside 10 deny ip 10.20.50.0 0.0.0.255 any log 20 permit ip any any interface Vlan900 description TRANSIT to R1 ip address 10.20.255.2 255.255.255.248 ip access-group V900-IN in ! ip route 0.0.0.0 0.0.0.0 10.20.255.1
Platform note: if your IOS-XE release won't take a service-policy on the C1111's Vlan interface, apply the same 50 Mb/s limit with a police rate action inside the GUEST→OUTSIDE zone-firewall policy in step 8.
With the guest VLAN terminating on R1, a guest packet for 10.20.30.21 goes to R1, and R1 would happily route it back over the transit link to the core. No SVI on the core only means the core can't take a shortcut for guests; every guest packet has to go through R1. Isolation therefore needs two controls, and this design has them: V900-IN on the core drops anything sourced from 10.20.50.0/24 (from this step on), and R1's zone firewall drops GUEST→INSIDE by default (step 8). Either one alone keeps guests out, so a mistake in one of them doesn't expose the client files.
ping 10.20.255.1. From R1: ping 10.20.10.1 (return route works).ping 10.20.30.21 fails, and show access-lists V900-IN shows line 10 counting. Guests have no internet yet: that comes in step 9.12 · Step 8 of 13
R1 becomes the only stateful firewall in the building. A zone pair that isn't configured means drop, so the most important part of this config is the pairs that aren't there.
Four zones: INSIDE (the transit link), GUEST, VPN (used in step 11) and OUTSIDE (the WAN ports, which get cabled in steps 9 and 10). Once any interface is in a zone, traffic between it and an interface that is not in a zone is dropped. So every interface gets its zone in the same step its cable goes in.
zone security INSIDE zone security GUEST zone security VPN zone security OUTSIDE ! class-map type inspect match-any CM-ANY match protocol tcp match protocol udp match protocol icmp ip access-list extended VPN-TO-INSIDE permit ip 10.20.200.0 0.0.0.255 host 10.20.30.10 permit tcp 10.20.200.0 0.0.0.255 host 10.20.30.20 eq 443 permit tcp 10.20.200.0 0.0.0.255 host 10.20.30.21 eq 445 permit tcp 10.20.200.0 0.0.0.15 10.20.99.0 0.0.0.255 eq 22 ! admins only (.0/28) permit tcp 10.20.200.0 0.0.0.15 10.20.99.0 0.0.0.255 eq 443 class-map type inspect match-all CM-VPN-IN match access-group name VPN-TO-INSIDE ! policy-map type inspect PM-TO-OUT class type inspect CM-ANY inspect class class-default drop log policy-map type inspect PM-VPN-IN class type inspect CM-VPN-IN inspect class class-default drop log ! zone-pair security ZP-IN-OUT source INSIDE destination OUTSIDE service-policy type inspect PM-TO-OUT zone-pair security ZP-GST-OUT source GUEST destination OUTSIDE service-policy type inspect PM-TO-OUT zone-pair security ZP-VPN-OUT source VPN destination OUTSIDE service-policy type inspect PM-TO-OUT zone-pair security ZP-VPN-IN source VPN destination INSIDE service-policy type inspect PM-VPN-IN ! not configured, on purpose: GUEST<->INSIDE, GUEST<->VPN, INSIDE->VPN
# R1 (CCR2004) — zones become interface lists, zone pairs become forward rules
/interface list
add name=INSIDE
add name=GUEST
add name=WAN
/interface list member
add list=GUEST interface=v50-guest
# … v10, v20, v30, v40, v45, v60, v99 into INSIDE
/ip firewall filter
add chain=forward action=accept in-interface-list=INSIDE out-interface-list=WAN
add chain=forward action=accept in-interface-list=GUEST out-interface-list=WAN
add chain=forward action=drop in-interface-list=GUEST log=yes log-prefix=GUEST-DROP \
comment="no GUEST→INSIDE pair = this line"
add chain=input action=accept in-interface-list=WAN protocol=udp dst-port=500,4500 comment="IKE (step 11)"
add chain=input action=accept in-interface-list=WAN protocol=ipsec-espinterface Vlan900 zone-member security INSIDE interface Vlan50 zone-member security GUEST
show zone security: INSIDE contains Vlan900, GUEST contains Vlan50.nmap -sn 10.20.0.0/16 finds only 10.20.50.1. Drops for GUEST→INSIDE show up in R1's log.V900-IN from the core and repeat: the guest is still blocked, now by the zone firewall alone. Put the ACL back.13 · Step 9 of 13
The fibre goes in, the WAN port joins OUTSIDE, and one public IP is shared by the whole firm through port address translation.
▲ Show step 9 in the interactive topology · see what this step adds, and click any device for its config
The whole site shares one public IPv4 address, so R1 uses PAT (port address translation): each inside socket is mapped to the public IP plus a source port. PAT keeps the original source port when it can and picks a new one when two inside hosts happen to use the same one. The animation below shows exactly that collision:
interface GigabitEthernet0/0/0
description FIBRE (static 203.0.113.10/29)
ip address 203.0.113.10 255.255.255.248
ip nat outside
zone-member security OUTSIDE
no cdp enable
interface Vlan900
ip nat inside
interface Vlan50
ip nat inside
!
ip access-list standard NAT-SRC
permit 10.20.0.0 0.0.255.255
route-map NAT-FIBRE permit 10
match ip address NAT-SRC
match interface GigabitEthernet0/0/0
ip nat inside source route-map NAT-FIBRE interface GigabitEthernet0/0/0 overload
no ip nat service sip udp port 5060 ! SIP ALG off: the hosted PBX handles NAT itself
no ip nat service sip tcp port 5060
!
ip route 0.0.0.0 0.0.0.0 203.0.113.9# R1 (CCR2004) — fibre and NAT /interface list member add list=WAN interface=ether1 /ip address add address=203.0.113.10/29 interface=ether1 comment="fibre" /ip firewall nat add chain=srcnat action=masquerade out-interface-list=WAN # masquerade follows whichever WAN a packet leaves on: no per-interface NAT rules needed /ip firewall service-port set sip disabled=yes # SIP ALG off for the hosted PBX
The usual one-line ip nat inside source list NAT-SRC interface Gi0/0/0 overload only knows one outside interface. Add a second one and translations keep using the fibre address even after traffic has failed over to 5G, so the replies go nowhere. Matching on match interface in a route-map ties each translation to the interface the packet actually leaves through. The same applies to SIP: IOS's SIP ALG rewrites SDP bodies, and modern hosted PBXs already handle NAT themselves, so the two fight and you get one-way audio. Turning the ALG off is the first fix to try for hosted VoIP.
show ip nat translations shows its inside-local address mapped to 203.0.113.10.show policy-map type inspect zone-pair ZP-IN-OUT sessions lists the sessions being inspected.14 · Step 10 of 13
A missed court filing deadline costs far more than a 5G router. Probe the fibre path, not just the link light, and let the DHCP default route take over.
▲ Show step 10 in the interactive topology · see what this step adds, and click any device for its config
interface GigabitEthernet0/0/1 description 5G BACKUP (bridge mode) ip address dhcp ! DHCP default route at AD 254 = the floating backup ip nat outside zone-member security OUTSIDE no cdp enable route-map NAT-5G permit 10 match ip address NAT-SRC match interface GigabitEthernet0/0/1 ip nat inside source route-map NAT-5G interface GigabitEthernet0/0/1 overload ! no ip route 0.0.0.0 0.0.0.0 203.0.113.9 ! replaced by the tracked route below
ip sla 1 icmp-echo 1.1.1.1 source-interface GigabitEthernet0/0/0 frequency 5 ip sla schedule 1 life forever start-time now track 1 ip sla 1 reachability delay down 10 up 60 ! fail fast, return slowly (no flapping) ! ip route 0.0.0.0 0.0.0.0 203.0.113.9 track 1 ip route 1.1.1.1 255.255.255.255 203.0.113.9 ip route 1.1.1.1 255.255.255.255 Null0 250 ! the probe may NEVER leave via 5G ! event manager applet WAN-FAILOVER event track 1 state any action 1.0 cli command "enable" action 2.0 cli command "clear ip nat translation *" action 3.0 syslog msg "WAN track 1 changed: NAT translations cleared"
# R1 (CCR2004) — recursive failover replaces IP SLA + track
/ip route
add dst-address=1.1.1.1/32 gateway=203.0.113.9 scope=10 comment="probe via fibre"
add dst-address=0.0.0.0/0 gateway=1.1.1.1 target-scope=11 check-gateway=ping distance=1 comment="main: fibre"
/ip dhcp-client add interface=ether2 default-route-distance=2 use-peer-dns=no comment="5G (bridge mode)"
/interface list member add list=WAN interface=ether2
# netwatch replaces the EEM applet: flush NAT state when the fibre path changes
/tool netwatch add host=1.1.1.1 interval=10s \
down-script="/ip firewall connection remove [find]" up-script="/ip firewall connection remove [find]"1. The probe escapes. If the fibre interface goes down, the pinned /32 disappears with it, the probe to 1.1.1.1 follows the 5G default, gets answered, and track 1 comes back up while the fibre is still dead. The Null0 route at AD 250 stops that. 2. Stale NAT. Existing translations still point at the old outside address, so long-lived sessions (Teams, VoIP registrations) hang until they time out. The EEM applet clears the table on every state change. 3. The VPN goes away. The 5G provider uses CGNAT, so while on backup nobody can reach R1 from outside. Remote lawyers drop until the fibre is back. That is a documented, accepted limitation: if the firm needs remote access during a fibre outage, the fix is a 5G plan with a public IP, not a cleverer config.
show track 1: Reachability is Up.15 · Step 11 of 13
The last device is the furthest one: a partner's laptop in a hotel. It gets the same controls as a desk on floor 2, which means a full tunnel, certificate plus MFA, and its own firewall zone.
▲ Show step 11 in the interactive topology · see what this step adds, and click any device for its config
The full IKEv2 remote-access build (server certificate, EAP, the IPsec profile) is covered step by step in the remote-access VPN post. For this firm, four choices differ from that post's defaults:
ip local pool VPN-POOL 10.20.200.16 10.20.200.250 ! .0/28 = admins, Framed-IP from NPS ! crypto ikev2 authorization policy VPN-POLICY pool VPN-POOL dns 10.20.30.10 def-domain firm.local ! no "route set access-list" = client installs a default route = FULL tunnel ! crypto ikev2 profile VPN-PROFILE match identity remote any authentication local rsa-sig authentication remote eap query-identity ! EAP → NPS → Entra MFA extension pki trustpoint FIRM-VPN aaa authentication eap VPN-EAP aaa authorization group eap list VPN-AUTHZ VPN-POLICY virtual-template 1 ! interface Virtual-Template1 type tunnel ip unnumbered Vlan900 ip nat inside ! full tunnel hairpins out via PAT zone-member security VPN tunnel mode ipsec ipv4 tunnel protection ipsec profile VPN-IPSEC ! ip route 10.20.200.0 255.255.255.0 Null0 ! per-client /32s win; unused pool IPs don't loop via the core
# R1 (CCR2004) — RouterOS also does IKEv2 with EAP via RADIUS, but most MikroTik
# remote-access builds use WireGuard: simpler, faster, one key per laptop.
/interface wireguard add name=wg-lawyers listen-port=13231
/interface wireguard peers add interface=wg-lawyers public-key="<partner laptop 1 key>" \
allowed-address=10.20.200.16/32 comment="partner laptop 1"
/ip address add address=10.20.200.1/24 interface=wg-lawyers
/ip firewall filter add chain=input action=accept in-interface-list=WAN protocol=udp dst-port=13231 \
place-before=0 comment="WireGuard"
# full tunnel: the laptop's config sets AllowedIPs = 0.0.0.0/0
# trade-off: WireGuard has no per-user RADIUS/MFA; MFA moves to the DMS and the EHR-style appsEAP goes from R1 to NPS on DC01, so R1 needs its own RADIUS client config (and NPS needs R1, 10.20.255.1, as a RADIUS client). That brings back step 5's trap: NPS's replies now go to 10.20.255.1, which V30-IN doesn't allow.
radius server NPS
address ipv4 10.20.30.10 auth-port 1812 acct-port 1813
key <radius-shared-secret>
aaa group server radius RAD-NPS
server name NPS
ip radius source-interface Vlan900
aaa authentication login VPN-EAP group RAD-NPS
aaa authorization network VPN-AUTHZ local
!
! on CORE: without this, every VPN login times out
ip access-list extended V30-IN
72 permit udp host 10.20.30.10 eq 1812 host 10.20.255.1The VPN needs IKE and ESP to reach the router itself, which means a policy for the self zone, and that's where step 10 can break without anyone noticing:
ip access-list extended OUT-SELF permit udp any any eq isakmp permit udp any any eq non500-isakmp permit esp any any permit icmp any any echo-reply ! IP SLA probe replies, see gotcha permit udp any eq bootps any eq bootpc ! DHCP on the 5G port class-map type inspect match-any CM-OUT-SELF match access-group name OUT-SELF policy-map type inspect PM-OUT-SELF class type inspect CM-OUT-SELF pass class class-default drop zone-pair security ZP-OUT-SELF source OUTSIDE destination self service-policy type inspect PM-OUT-SELF
Without an OUTSIDE→self zone pair, traffic to the router itself is allowed. As soon as you add one (and you need it, to restrict the VPN), anything not listed is dropped, including the echo replies to R1's own IP SLA probes. Traffic the router originates isn't inspected, so there is no state entry to let the reply back in. Track 1 goes down and stays down, and the site sits on 5G with a perfectly healthy fibre. That's why the echo-reply and DHCP lines are in OUT-SELF. Whenever you change a self-zone policy, run show track 1 immediately afterwards.
Split tunnelling sends only firm-bound traffic through the VPN and everything else straight out of the hotel's network. That is lighter on the firm's 100 Mb/s upload. But a lawyer's laptop carrying privileged documents would then browse, download and fetch email attachments over a network the firm doesn't control, without any of its controls applied. With 12 lawyers, 3–4 concurrent tunnels is the realistic peak and the upload has room for it. If it ever doesn't, a cloud-delivered web filter on the laptop is a better answer than split tunnelling.
tracert 9.9.9.9: the first hop is inside the tunnel (full tunnel works).\\FS01 opens but \\NAS01 doesn't.show track 1 is still Up after adding the self-zone policy.16 · Step 12 of 13
The congested direction is upload. Shape just below the line rate so the queue builds inside R1, then let voice skip it.
class-map match-any VOICE match dscp ef class-map match-any SIGNALLING match dscp cs3 af31 policy-map WAN-CHILD class VOICE priority percent 10 ! ~9.5 Mb/s: about 100 concurrent G.711 calls, policed class SIGNALLING bandwidth percent 5 class class-default fair-queue policy-map WAN-OUT class class-default shape average 95000000 ! just below the 100 Mb/s upload service-policy WAN-CHILD ! interface GigabitEthernet0/0/0 service-policy output WAN-OUT ! no policy on the 5G port: its uplink rate varies too much to shape usefully
# R1 (CCR2004) — queue tree replaces the LLQ policy /ip firewall mangle add chain=postrouting action=mark-packet new-packet-mark=voice out-interface=ether1 dscp=46 passthrough=no add chain=postrouting action=mark-packet new-packet-mark=signal out-interface=ether1 dscp=24 passthrough=no add chain=postrouting action=mark-packet new-packet-mark=rest out-interface=ether1 passthrough=no /queue type add name=fq kind=fq-codel /queue tree add name=WAN-OUT parent=ether1 max-limit=95M add name=voice parent=WAN-OUT packet-mark=voice priority=1 limit-at=10M max-limit=95M add name=signal parent=WAN-OUT packet-mark=signal priority=2 limit-at=5M max-limit=95M add name=rest parent=WAN-OUT packet-mark=rest priority=8 max-limit=95M queue=fq
The Catalyst switches trust DSCP by default, so the phones' EF marking arrives at R1 unchanged. On the download side there is nothing to queue (the ISP sends you what it sends you), and with 500 Mb/s down that is rarely where the problem is. For more detail, see the QoS for VoIP post.
show policy-map interface Gi0/0/0: drops are in class-default, none in VOICE.17 · Step 13 of 13
If a firm loses its client files, it has a problem that lawyers, not IT, will be dealing with. The design rule is that no user machine can reach any copy of the backups.
The network contributes three things. (1) No user VLAN has a rule allowing traffic to NAS01; the only path to it is from inside VLAN 30. (2) The NAS pulls from the servers using its own read-only service account, so a compromised server doesn't have credentials that can write to the NAS. (3) Offsite copies go out over 443 to object storage with object lock, so not even an attacker holding the NAS admin password can delete them early. The NAS admin account is not a domain account, and no routed VLAN except management (99) can reach its web UI. The quarterly test restore (the "0") is on the contractor's calendar, and the result is written down.
Test-NetConnection 10.20.30.30 -Port 445 fails.18
The firm has no IT staff (R8). Every device has to be manageable remotely, from one subnet, and must keep records of what happened to it.
service password-encryption no ip http server no ip http secure-server ip ssh version 2 ip ssh time-out 60 login block-for 120 attempts 5 within 60 ! ip access-list standard MGMT-SRC permit 10.20.99.0 0.0.0.255 permit 10.20.200.0 0.0.0.15 ! VPN admins line vty 0 15 access-class MGMT-SRC in transport input ssh exec-timeout 10 0 ! ntp server 10.20.30.10 logging host 10.20.99.20 ! monitoring VM: syslog + SNMP + config diffs logging trap informational archive path flash:archive write-memory maximum 10 ! ! R1 only: no discovery protocols toward the ISP interface range GigabitEthernet0/0/0 - 1 no cdp enable no lldp transmit no lldp receive
Unused switch ports are shut down and left in VLAN 666. Configs are pulled nightly to the monitoring VM and diffed, so an unexpected change shows up as a diff the next morning rather than being found six months later. The full baselines are in Hardening IOS and Backup & Restore.
19
A config that hasn't been tested is just a guess. Each drill below maps to a requirement from section 01, and the firm gets the results in writing.
CORE# show etherchannel summary | include Po 1 Po1(SU) LACP Gi1/1/1(P) Gi1/1/2(P) 2 Po2(SU) LACP Gi1/1/3(P) Gi1/1/4(P) CORE# show ip interface brief | include Vlan Vlan10 10.20.10.1 YES manual up up Vlan20 10.20.20.1 YES manual up up Vlan30 10.20.30.1 YES manual up up ... ! and NO Vlan50: that's the point ACC-2# show access-session interface Gi1/0/7 details Interface: GigabitEthernet1/0/7 MAC Address: 3c52.82xx.xxxx User-Name: host/LAW-PC07.firm.local Status: Authorized Domain: DATA Vlan Group: Vlan: 10 Method status list: dot1x Authc Success R1-EDGE# show track 1 Track 1 IP SLA 1 reachability Reachability is Up 2 changes, last change 00:41:17 Delay up 60 secs, down 10 secs R1-EDGE# show policy-map type inspect zone-pair ZP-GST-OUT sessions | count Established Number of lines which match regexp = 37 CORE# show access-lists V20-IN | include deny 70 deny ip any 10.0.0.0 0.255.255.255 log (412 matches) ! who is poking where?
| Drill (requirement) | What must happen |
|---|---|
| Guest sweep (R2) | From a meeting-room port: nmap -sn 10.20.0.0/16 finds only 10.20.50.1. ZBF drops appear in R1's log. Then repeat it over FIRM-GUEST Wi-Fi. |
| Unknown laptop (R3) | A non-domain laptop in an empty office stays on VLAN 666 and gets no address. The session shows Unauthorized. |
| Camera swap (R3) | Unplug a camera and plug in a laptop: the port goes err-disabled and a syslog alert reaches the monitoring VM within seconds. |
| Rogue DHCP (R3) | A small router plugged into a desk port as a DHCP server: offers are dropped (DHCP_SNOOPING_UNTRUSTED_PORT) and no client takes its lease. |
| Staff sweep (R1) | From VLAN 20, a scan of 10.20.30.0/24 finds DC01 and DMS01:443 only. FS01, NAS01 and the NVR don't respond. |
| Fibre cut (R5) | Pull the ONT's fibre (not the Ethernet cable). Track down in ~15–20 s, browsing resumes on 5G, calls re-register within a minute, VPN unavailable (as documented). Plug it back: fibre restored after 60 s. |
| NPS down (R3/R5) | Stop the NPS service and re-plug a lawyer PC: it lands in VLAN 20 (critical) and can still reach the DMS. Start NPS again: the port re-authenticates into VLAN 10. |
| Upload flood (R7) | Upload a 2 GB file to cloud storage during a test call: MOS stays above 4, and show policy-map interface Gi0/0/0 shows class-default drops, not VOICE drops. |
| Restore (R6) | Restore one matter folder from offsite object storage to a scratch share. Time it and write it down. If nobody has ever timed it, you don't know whether the backup works. |
20
I test networks like this for a living. Here is what I'd still try against this one, and why each item is a decision rather than an oversight.
permit ip … host 10.20.30.10 is in every user ACL, because AD needs it. That makes DC01 the main target (Kerberoasting, coercion, relay). The defences are AD hygiene, not the network: LAPS, tiered admin accounts, SMB signing, and no domain admin ever logging on to a workstation.\\FS01\Scans.21
Most of this design runs in Packet Tracer. Where it doesn't, use CML or EVE-NG rather than leaving those parts out.
| This post | In Packet Tracer |
|---|---|
| R1 C1111-8P | ISR4331. It has no built-in switchports, so do router-on-a-stick instead: Gi0/0/1.50 and Gi0/0/1.900 with encapsulation dot1Q, and the NAT/zone commands on the subinterfaces. |
| CORE C9200-24T | 3650-24PS with ip routing. Interface names line up (Gi1/0/x). |
| ACC-1 / ACC-2 | 2960-24TT. Desk ports become Fa0/x, uplinks Gi0/1-2. |
| DC01 / DMS01 / NAS01 | Server-PT: enable its DHCP (pools per VLAN for the relay), DNS and HTTP services. |
| Works well | Steps 1–5 completely (VLANs, port-security, AP bridging, LACP, SVIs, DHCP relay to a Server-PT, every ACL), step 7, step 9's PAT, and static routes. That's the whole layer-by-layer build up to the internet, checkpoints included. |
| Partial / varies | Step 6 (802.1X), step 8 (ZBF), step 10 (IP SLA/track), step 11 (FlexVPN), step 12 (hierarchical QoS). Support depends on the Packet Tracer version and is incomplete. Build these on CML or EVE-NG with IOSv/IOSvL2, or a Cat8000v for FlexVPN. |
| Wireless | AccessPoint-PT is a simple bridge: give it one SSID per port/VLAN, or use a WLC-PT with lightweight APs to get closer to the EWC design. |
22
Rough budget figures, not a quote: new hardware, Greek street prices in late 2026, excluding VAT. Refurbished Catalyst gear costs much less; see the buying-used guide.
| Item | Indicative (EUR, ex VAT) |
|---|---|
| R1 · C1111-8P | 700 – 1,000 |
| CORE · C9200-24T-4G | 1,800 – 2,500 incl. the mandatory DNA licence term |
| ACC-1 · C9200L-48P-4G | 2,600 – 3,400 incl. DNA |
| ACC-2 · C9200L-24P-4G | 1,600 – 2,200 incl. DNA |
| 4× C9115AXI (one runs EWC) | 2,400 – 3,200 |
| 5G router + business SIM | 250 – 400, plus ~25/month |
| 2× UPS + network cards | 1,100 – 1,600 |
| HV01 host + Windows Server licences | quoted separately: server, not network, but the DC, DMS and file shares all run on it |
| Rack, patch panels, managers | 400 – 700 |
| NAS01 + disks | 1,200 – 1,800 |
| Offsite immutable storage | ~20 – 40/month for ~4 TB |
| Network hardware total | ≈ 12,000 – 17,000, plus structured cabling (quoted per building, usually the biggest variable) |
Catalyst 9200s are sold with a mandatory DNA subscription term on top of the hardware. When it lapses, the switch keeps switching and routing (the Network Essentials feature set is perpetual), but the line item still surprises clients at renewal time. Put it in the proposal at the start, and check Cisco's current licensing terms before quoting, because they change.
Appendix
Same brief, same VLANs, same matrix, about a fifth of the hardware cost. The Cisco/MikroTik tabs on the config blocks above show the key steps side by side; this appendix covers what changes underneath.
| Role | Cisco (this post) → MikroTik |
|---|---|
| ACC-1 (48 PoE) | C9200L-48P-4G → CRS354-48P-4S+2Q+ |
| ACC-2 (24 PoE) | C9200L-24P-4G → CRS328-24P-4S+ |
| CORE | C9200-24T (L3) → CRS326-24S+2Q+ (Layer 2 only) |
| R1 | C1111-8P (edge only) → CCR2004-16G-2S+ (edge and all inter-VLAN routing) |
| Wi-Fi | 4× C9115AXI with EWC → 4× cAP ax with CAPsMAN on R1 |
| Indicative total | ≈ 12,000–17,000 → ≈ 2,300–2,900 EUR ex VAT, with no licence terms |
| Feature | Cisco IOS-XE → RouterOS 7 |
|---|---|
| VLANs, trunks | switchport → bridge with vlan-filtering, pvid, /interface bridge vlan |
| LACP | channel-group … active → /interface bonding mode=802.3ad |
| SVIs | interface VlanX on the core → /interface vlan on R1 |
| Inter-VLAN policy | stateless SVI ACLs → stateful /ip firewall filter forward chain |
| Zone firewall | ZBF zones and pairs → interface lists and forward rules |
| 802.1X / MAB | authentication/dot1x/mab → /interface dot1x server + /radius |
| Sticky MAC | port-security mac-address sticky → learn=no + /interface bridge host |
| DHCP snooping / DAI | ip dhcp snooping → bridge dhcp-snooping=yes + trusted ports; no direct DAI equivalent |
| PAT | ip nat inside source … overload → masquerade on the WAN interface list |
| IP SLA + track | → recursive routes with check-gateway=ping |
| EEM | → /tool netwatch scripts and /system scheduler |
| FlexVPN | → IKEv2 (/ip ipsec) or, more commonly, WireGuard |
| LLQ + shaper | → mangle packet marks + /queue tree |
| archive / configure replace | → /export, /system backup, and Safe Mode for risky changes |
Routing moves to the router. A CRS can route between VLANs in hardware, but not with a firewall inspecting every packet, and this design depends on that inspection. So the core becomes a pure Layer 2 switch, and the CCR2004 routes and filters everything. Its inter-VLAN capacity (several Gb/s with a firewall) is plenty for 28 people. The firewall becomes stateful. The two biggest gotchas of the Cisco build disappear: no established flags, and no RADIUS-reply line that silently breaks 802.1X. Connection tracking handles every reply. The guest pattern gets simpler. With all routing on R1, "no SVI on the core" is automatic, and the V900-IN backstop becomes one drop rule for the GUEST interface list.
What you give up: per-port "PC behind phone" authentication is simpler on Cisco (RouterOS authenticates the port, so the phone rides the tagged voice VLAN while the PC authenticates), there's no Dynamic ARP Inspection, and WireGuard has no per-user RADIUS/MFA of its own. For a 28-person firm that's a reasonable trade for a fifth of the price; for a regulated firm that must show per-user VPN logs, keep IKEv2 with EAP.
Takeaways
V900-IN on the core is an independent second control.This is part 1 of the Build series. Next: the medical clinic, where the same structure has to deal with a medical-device VLAN, patient-data law, and a reception desk that can't go offline.
This is how I design and build networks for professional offices: segmentation that's tested before handover, guest access that can't reach client files, and a written record of every decision for when the regulator or the insurer asks.
Book a Discovery Call →