Skip to content

P01-T06 - Base Firewall

Objective

Apply the first validated CHR firewall policy so the router is administratively protected, LAN networks can reach the internet, and guest or DMZ traffic is isolated from internal LAN services until explicit service rules are added later.

Inputs

Key Value
Router HQ-CHR01
Mgmt list MGMT
Hypervisor list HYPERVISORS
WAN list WAN
LAN list LAN
Backup list BACKUP
Guest list GUEST
DMZ list DMZ
Servers list SERVERS

Target State

Property Value
Input policy Established, ICMP, management, hypervisors, then WAN/default drop
Forward policy Established, LAN to WAN, backup to servers, guest isolation, DMZ isolation, default drop

Validated lab status

Validated against the live lab on Friday, July 17, 2026:

  • the base input and forward policy was deployed successfully
  • management from VLAN100 was validated
  • HQ-CHR01 retained internet access after firewall application
  • HQ-DC01 retained internet access through the router after firewall application
  • later DHCP relay validation proved that DHCP-specific input rules must be inserted before INPUT - Default Drop, not appended after it

Prechecks

  • Complete P01-T05.
  • Confirm interface lists are populated correctly.
  • Print current filter rules first:
/ip firewall filter print

If the router is clean and has no conflicting default rules, continue. If it already has active rules in production, review before applying anything.

Execution

Deploy the input chain rules as a managed block and enforce order by comment:

:if ([:len [/ip firewall filter find where comment="INPUT - Established"]] = 0) do={
    /ip firewall filter add chain=input action=accept connection-state=established,related comment="INPUT - Established"
}
:if ([:len [/ip firewall filter find where comment="INPUT - Invalid"]] = 0) do={
    /ip firewall filter add chain=input action=drop connection-state=invalid comment="INPUT - Invalid"
}
:if ([:len [/ip firewall filter find where comment="INPUT - ICMP"]] = 0) do={
    /ip firewall filter add chain=input action=accept protocol=icmp comment="INPUT - ICMP"
}
:if ([:len [/ip firewall filter find where comment="INPUT - Management"]] = 0) do={
    /ip firewall filter add chain=input action=accept in-interface-list=MGMT comment="INPUT - Management"
}
:if ([:len [/ip firewall filter find where comment="INPUT - Hypervisors"]] = 0) do={
    /ip firewall filter add chain=input action=accept in-interface-list=HYPERVISORS comment="INPUT - Hypervisors"
}
:if ([:len [/ip firewall filter find where comment="INPUT - Drop WAN"]] = 0) do={
    /ip firewall filter add chain=input action=drop in-interface-list=WAN comment="INPUT - Drop WAN"
}
:if ([:len [/ip firewall filter find where comment="INPUT - Default Drop"]] = 0) do={
    /ip firewall filter add chain=input action=drop comment="INPUT - Default Drop"
}

:local InputEstablished [/ip firewall filter find where comment="INPUT - Established"]
:local InputInvalid [/ip firewall filter find where comment="INPUT - Invalid"]
:local InputIcmp [/ip firewall filter find where comment="INPUT - ICMP"]
:local InputMgmt [/ip firewall filter find where comment="INPUT - Management"]
:local InputHypervisors [/ip firewall filter find where comment="INPUT - Hypervisors"]
:local InputDropWan [/ip firewall filter find where comment="INPUT - Drop WAN"]
:local InputDefaultDrop [/ip firewall filter find where comment="INPUT - Default Drop"]

:foreach RuleId in=$InputDefaultDrop do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$InputDropWan do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$InputHypervisors do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$InputMgmt do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$InputIcmp do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$InputInvalid do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$InputEstablished do={ /ip firewall filter move $RuleId 0 }

Deploy the forward chain rules as a managed block and enforce order by comment:

:if ([:len [/ip firewall filter find where comment="FWD - Established"]] = 0) do={
    /ip firewall filter add chain=forward action=accept connection-state=established,related comment="FWD - Established"
}
:if ([:len [/ip firewall filter find where comment="FWD - Invalid"]] = 0) do={
    /ip firewall filter add chain=forward action=drop connection-state=invalid comment="FWD - Invalid"
}
:if ([:len [/ip firewall filter find where comment="FWD - LAN to Internet"]] = 0) do={
    /ip firewall filter add chain=forward action=accept in-interface-list=LAN out-interface-list=WAN comment="FWD - LAN to Internet"
}
:if ([:len [/ip firewall filter find where comment="FWD - Backup"]] = 0) do={
    /ip firewall filter add chain=forward action=accept in-interface-list=BACKUP out-interface-list=SERVERS comment="FWD - Backup"
}
:if ([:len [/ip firewall filter find where comment="FWD - Guest Isolation"]] = 0) do={
    /ip firewall filter add chain=forward action=drop in-interface-list=GUEST out-interface-list=LAN comment="FWD - Guest Isolation"
}
:if ([:len [/ip firewall filter find where comment="FWD - DMZ Isolation"]] = 0) do={
    /ip firewall filter add chain=forward action=drop in-interface-list=DMZ out-interface-list=LAN comment="FWD - DMZ Isolation"
}
:if ([:len [/ip firewall filter find where comment="FWD - Default Drop"]] = 0) do={
    /ip firewall filter add chain=forward action=drop comment="FWD - Default Drop"
}

:local FwdEstablished [/ip firewall filter find where comment="FWD - Established"]
:local FwdInvalid [/ip firewall filter find where comment="FWD - Invalid"]
:local FwdLanInternet [/ip firewall filter find where comment="FWD - LAN to Internet"]
:local FwdBackup [/ip firewall filter find where comment="FWD - Backup"]
:local FwdGuestIsolation [/ip firewall filter find where comment="FWD - Guest Isolation"]
:local FwdDmzIsolation [/ip firewall filter find where comment="FWD - DMZ Isolation"]
:local FwdDefaultDrop [/ip firewall filter find where comment="FWD - Default Drop"]

:foreach RuleId in=$FwdDefaultDrop do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$FwdDmzIsolation do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$FwdGuestIsolation do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$FwdBackup do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$FwdLanInternet do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$FwdInvalid do={ /ip firewall filter move $RuleId 0 }
:foreach RuleId in=$FwdEstablished do={ /ip firewall filter move $RuleId 0 }

If a comment matches zero rules, the :foreach does nothing. If it matches multiple rules because of duplicates, each one is still moved safely.

Do not permit inter-VLAN business traffic yet. Service-specific flows for AD, DNS, DHCP, and SMB should be added later as explicit rules when Windows services are deployed.

Important: when Windows DHCP is hosted on a server in another VLAN, the later service runbooks must add both:

  • a DHCP relay entry on CHR
  • explicit input rules for relay client requests and server replies before INPUT - Default Drop

Without those input rules, the relay can be configured correctly and still fail at runtime. This failure mode was reproduced in the live lab until the DHCP relay rules were moved above INPUT - Default Drop.

Validation

Run:

/ip firewall filter print stats
/ping 1.1.1.1
/ping google.com

From H1:

ping 172.20.100.1

Pass criteria:

  • Filter counters increase on active rules.
  • H1 still reaches 172.20.100.1.
  • CHR has outbound connectivity.
  • Guest and DMZ networks are blocked from generic LAN access.
  • No broad admin access exists from WAN.
  • Input chain order is:
  • INPUT - Established
  • INPUT - Invalid
  • INPUT - ICMP
  • INPUT - Management
  • INPUT - Hypervisors
  • INPUT - Drop WAN
  • INPUT - Default Drop
  • Forward chain order is:
  • FWD - Established
  • FWD - Invalid
  • FWD - LAN to Internet
  • FWD - Backup
  • FWD - Guest Isolation
  • FWD - DMZ Isolation
  • FWD - Default Drop

Evidence

  • Output of /ip firewall filter print stats
  • Output of ping 172.20.100.1 from H1
  • Output of /ping 1.1.1.1
  • Output of /ping google.com

Rollback

  • Remove only the newly added filter rules if access breaks in a known way.
  • If rule order is corrupted, restore from the last known backup before firewall application.