Skip to content

Firewall Filter Rules

The RouterOS firewall filter is the primary mechanism for controlling which packets are allowed to pass through or enter the router. Rules in the filter table are evaluated in order — the first matching rule determines the outcome. Understanding chains, actions, and connection tracking states is essential for building correct and efficient firewall policies.

Minimal stateful firewall protecting the router itself and forwarded traffic:

/ip firewall filter
# Drop invalid packets early
add chain=input connection-state=invalid action=drop comment="drop invalid input"
add chain=forward connection-state=invalid action=drop comment="drop invalid forward"
# Accept established and related (return traffic)
add chain=input connection-state=established,related action=accept comment="accept established/related input"
add chain=forward connection-state=established,related action=accept comment="accept established/related forward"
# Accept ICMP (ping, traceroute, etc.)
add chain=input protocol=icmp action=accept comment="accept ICMP input"
# Accept new connections from LAN to internet
add chain=forward in-interface=ether2 connection-state=new action=accept comment="accept LAN new forward"
# Drop everything else
add chain=input action=drop comment="drop all other input"
add chain=forward action=drop comment="drop all other forward"

RouterOS firewall filter uses three built-in chains. Each chain processes packets at a different point in the packet flow.

ChainProcessesTypical Use
inputPackets destined for the router itselfProtect router management access
forwardPackets routed through the routerControl LAN-to-WAN, inter-VLAN traffic
outputPackets originating from the routerRarely needed; restrict router-generated traffic

The input chain processes packets whose destination is the router itself — management traffic (Winbox, SSH, HTTP, SNMP), DNS queries to the router, ICMP pings to router interfaces.

# Allow Winbox only from management network
/ip firewall filter add chain=input protocol=tcp dst-port=8291 \
src-address=192.168.100.0/24 action=accept comment="allow Winbox from mgmt"
# Allow SSH only from trusted host
/ip firewall filter add chain=input protocol=tcp dst-port=22 \
src-address=192.168.100.10 action=accept comment="allow SSH from admin"

The forward chain processes packets that enter one interface and exit another. This is where LAN-to-internet and inter-VLAN policies are enforced.

# Allow LAN to internet
/ip firewall filter add chain=forward in-interface=bridge-lan \
out-interface=ether1-wan action=accept comment="LAN to WAN"
# Block LAN from reaching a restricted VLAN
/ip firewall filter add chain=forward in-interface=bridge-lan \
dst-address=10.10.20.0/24 action=drop comment="no access to restricted VLAN"

The output chain processes packets that originate from the router itself. This is rarely needed in typical deployments.

# Log all router-originated traffic to a specific host (diagnostic use)
/ip firewall filter add chain=output dst-address=203.0.113.5 \
action=log log-prefix="router-to-host"

You can create custom chains and use jump to send traffic to them. This improves readability and allows reuse of logic.

# Jump to a custom chain
/ip firewall filter add chain=forward connection-state=new \
action=jump jump-target=new-conn-policy
# Rules in the custom chain
/ip firewall filter add chain=new-conn-policy src-address=10.0.0.0/8 \
action=accept
/ip firewall filter add chain=new-conn-policy action=drop
# Use 'return' to exit back to the calling chain without a match
/ip firewall filter add chain=new-conn-policy protocol=tcp dst-port=443 \
action=return

Each filter rule specifies one action to take when a packet matches.

ActionEffect
acceptAllow the packet; stop processing rules in this chain
dropSilently discard the packet; stop processing
rejectDiscard and send ICMP unreachable back to sender
logLog the packet, then continue to the next rule
passthroughLike log — count the packet, continue to next rule
jumpTransfer processing to a named custom chain
returnExit the current chain, resume in the calling chain
fasttrackMark connection for FastTrack acceleration; bypass further processing
add-src-to-address-listAdd source address to an address list
add-dst-to-address-listAdd destination address to an address list
tarpitHold TCP connections open to exhaust attacker resources
# accept — allow traffic silently
/ip firewall filter add chain=forward src-address=192.168.1.0/24 action=accept
# drop — silently discard (preferred for security; gives no information to attacker)
/ip firewall filter add chain=input action=drop
# reject — discard and notify sender (use for internal networks where feedback is useful)
/ip firewall filter add chain=forward dst-address=10.0.0.5 \
action=reject reject-with=icmp-admin-prohibited

reject-with options: icmp-net-unreachable, icmp-host-unreachable, icmp-port-unreachable, icmp-admin-prohibited, tcp-reset.

log is a non-terminating action — it records the packet and continues evaluating rules.

# Log and then drop
/ip firewall filter add chain=input src-address=203.0.113.0/24 \
action=log log-prefix="blocked-src" log-limit=10/1s
/ip firewall filter add chain=input src-address=203.0.113.0/24 \
action=drop

Use log-limit to prevent log flooding. Format is count/time (e.g., 10/1s = 10 log entries per second).

FastTrack bypasses most firewall processing for established/related connections, offloading them to a faster path.

/ip firewall filter add chain=forward connection-state=established,related \
action=fasttrack connection-mark=no-mark comment="FastTrack established"
/ip firewall filter add chain=forward connection-state=established,related \
action=accept comment="accept established (post-FastTrack)"

Connection tracking maintains a state table of active network connections, allowing the firewall to make decisions based on the state of a flow rather than inspecting each packet independently.

StateMeaning
newFirst packet of a connection not yet in the tracking table
establishedPacket belongs to a connection that has seen traffic in both directions
relatedPacket related to an existing connection (e.g., FTP data channel, ICMP errors for a TCP flow)
invalidPacket does not match any known connection and cannot be identified
untrackedConnection tracking bypassed (RAW table notrack action)
# Match multiple states with a comma-separated list
/ip firewall filter add chain=forward \
connection-state=established,related action=accept
# Match a single state
/ip firewall filter add chain=input \
connection-state=new protocol=tcp dst-port=22 action=accept
# Drop invalid packets (should appear early in ruleset)
/ip firewall filter add chain=input connection-state=invalid action=drop

Packets marked invalid do not belong to any tracked connection and cannot be classified. They may indicate:

  • Port scans sending unexpected ACK/RST packets
  • IP spoofing
  • Misconfigured NAT
  • Out-of-order packets from asymmetric routing

Always drop invalid packets as the first rule (or early) in your filter chains.

# Print all tracked connections
/ip firewall connection print
# Filter by state
/ip firewall connection print where connection-state=established
# Print with details (protocol, addresses, ports, timeout)
/ip firewall connection print detail
# Flush all connections (caution — drops all active sessions)
/ip firewall connection remove [find]
# View current settings
/ip firewall connection tracking print
# Disable connection tracking (advanced — breaks NAT and stateful filtering)
/ip firewall connection tracking set enabled=no
# Adjust TCP timeout for established connections (default: 1 day)
/ip firewall connection tracking set tcp-established-timeout=1d
# UDP timeout (default: 10 seconds for stream, 30s for others)
/ip firewall connection tracking set udp-stream-timeout=1m

Disabling connection tracking prevents all stateful matching (connection-state, connection-mark, NAT). Only disable if you understand the full impact.

Rules are evaluated top to bottom. The first matching rule’s action is applied; subsequent rules are not checked (for terminating actions like accept, drop, reject). Order matters significantly.

1. Drop invalid (early exit — no state to track)
2. Accept established/related (bulk of return traffic — fast exit)
3. Accept loopback/ICMP (if applicable)
4. Specific accept rules for new connections
5. Drop-all (default deny)
# Print rules with rule numbers
/ip firewall filter print
# Move rule #5 before rule #2
/ip firewall filter move 5 destination=2
# Enable/disable a rule without removing it
/ip firewall filter disable 3
/ip firewall filter enable 3
# Show hit counts and bytes per rule
/ip firewall filter print stats
# Reset stats
/ip firewall filter reset-counters [find]

Rules with zero hits may be unreachable (shadowed by earlier rules) or never triggered.

/ip firewall filter
# Drop invalid
add chain=input connection-state=invalid action=drop comment="drop invalid"
# Accept established/related
add chain=input connection-state=established,related action=accept \
comment="accept established/related"
# Accept ICMP
add chain=input protocol=icmp action=accept comment="accept ICMP"
# Accept from loopback
add chain=input in-interface=lo action=accept comment="accept loopback"
# Management access (restrict to admin network)
add chain=input protocol=tcp dst-port=22,8291,80,443 \
src-address=192.168.100.0/24 action=accept comment="allow mgmt from admin net"
# Drop everything else
add chain=input action=drop comment="drop all input"
/ip firewall filter
# Drop invalid
add chain=forward connection-state=invalid action=drop comment="drop invalid forward"
# FastTrack established (optional, performance)
add chain=forward connection-state=established,related \
action=fasttrack connection-mark=no-mark comment="FastTrack"
# Accept established/related
add chain=forward connection-state=established,related \
action=accept comment="accept established/related"
# Accept new from LAN to WAN
add chain=forward in-interface=bridge-lan out-interface=ether1-wan \
connection-state=new action=accept comment="LAN to WAN new"
# Drop all other forward
add chain=forward action=drop comment="drop all other forward"
/ip firewall filter
# Drop packets claiming to be from LAN arriving on WAN
add chain=forward in-interface=ether1-wan \
src-address=192.168.0.0/16 action=drop comment="anti-spoof LAN range"
add chain=forward in-interface=ether1-wan \
src-address=10.0.0.0/8 action=drop comment="anti-spoof RFC1918"
add chain=forward in-interface=ether1-wan \
src-address=172.16.0.0/12 action=drop comment="anti-spoof RFC1918"
/ip firewall filter
# Block SMB from reaching WAN
add chain=forward out-interface=ether1-wan \
protocol=tcp dst-port=139,445 action=drop comment="block SMB to WAN"
# Block incoming Telnet from WAN
add chain=input in-interface=ether1-wan \
protocol=tcp dst-port=23 action=drop comment="block Telnet from WAN"

Common matchers used in firewall filter rules:

MatcherExampleDescription
chainchain=forwardWhich chain the rule applies to
connection-stateconnection-state=new,establishedConnection tracking state
protocolprotocol=tcpIP protocol (tcp, udp, icmp)
src-addresssrc-address=192.168.1.0/24Source IP or subnet
dst-addressdst-address=10.0.0.1Destination IP or subnet
src-portsrc-port=1024-65535Source port or range
dst-portdst-port=80,443Destination port or comma list
in-interfacein-interface=ether1Incoming interface
out-interfaceout-interface=ether2Outgoing interface
src-address-listsrc-address-list=blocklistMatch against address list
connection-markconnection-mark=voipMatch connections marked by mangle
tcp-flagstcp-flags=synTCP flag matching
limitlimit=10,5:packetRate limiting matcher
# Check rule order and hit counts
/ip firewall filter print stats
# Trace a packet through the firewall (RouterOS 7+)
/tool/packet-sniffer quick interface=ether1 ip-address=203.0.113.1
# Check if connection tracking is enabled
/ip firewall connection tracking print
# Add a temporary log rule before the drop-all to see what's being dropped
/ip firewall filter add chain=input action=log log-prefix="INPUT-DROP" place-before=[find action=drop chain=input]
# Watch the log
/log print follow where topics~"firewall"

Remove the log rule after diagnosis.

FastTrack established/related connections to bypass full rule evaluation:

/ip firewall filter add chain=forward connection-state=established,related \
action=fasttrack connection-mark=no-mark place-before=0

Check for rules with broad matchers early in the chain that force all packets through slow processing.