Layer 7 Protocol Matching
Layer 7 Protocol Matching
Section titled “Layer 7 Protocol Matching”RouterOS Layer 7 (L7) protocol matching identifies application-layer traffic by running POSIX extended regex patterns against connection payloads. Unlike port-based matching, L7 can detect protocols regardless of port—useful for P2P, VoIP, and custom application traffic.
:::warning Performance impact L7 matching runs in software on every candidate packet. Apply it only after scoping with cheaper matchers (interface, protocol, port) to prevent CPU saturation on busy links. :::
Quick Start
Section titled “Quick Start”Block BitTorrent on a LAN-to-WAN path:
# 1. Define the pattern/ip firewall layer7-protocol add \ name=bittorrent \ regexp="^(\\x13bittorrent protocol|azver\\x01|get /scrape\\?info_hash=)"
# 2. Accept established/related first (must come before L7 rule)/ip firewall filter add chain=forward \ connection-state=established,related action=accept
# 3. Drop BitTorrent/ip firewall filter add chain=forward \ in-interface-list=LAN out-interface-list=WAN \ protocol=tcp layer7-protocol=bittorrent \ action=drop comment="Block BitTorrent TCP"How L7 Matching Works
Section titled “How L7 Matching Works”RouterOS inspects the first 10 packets or first 2 KB of each connection (whichever threshold is reached first). After that window, no further L7 inspection occurs—the pattern either matched or it did not.
Connection start │ ├── Packet 1 ──▶ regex scan ├── Packet 2 ──▶ regex scan │ ... ├── Packet 10 ─▶ regex scan ◀── last chance to match │ └── Packet 11+ ─▶ NO L7 inspection (window exhausted)Both directions of traffic must pass through the same router. Asymmetric routing causes L7 to see only half the conversation and patterns that depend on bidirectional payloads will never match.
Requirements
Section titled “Requirements”| Requirement | Detail |
|---|---|
| Connection tracking | Must be enabled — L7 uses the connection table to associate packets with flows |
| Bidirectional visibility | Both upstream and downstream must transit the same router |
| Plaintext payload | Regex matches raw bytes — TLS/QUIC encrypted payloads are opaque |
| Inspection window | First 10 packets or 2 KB; nothing matched outside this window |
Defining L7 Patterns
Section titled “Defining L7 Patterns”Patterns live in /ip firewall layer7-protocol. Each entry has a name and a regexp.
Syntax
Section titled “Syntax”/ip firewall layer7-protocol add name=<name> regexp="<posix-extended-regex>"The regex is applied to the raw bytes of the payload. Use \x hex escapes for non-printable bytes.
Example Patterns
Section titled “Example Patterns”# P2P: BitTorrent handshake/ip firewall layer7-protocol add \ name=bittorrent \ regexp="^(\\x13bittorrent protocol|azver\\x01|get /scrape\\?info_hash=)"
# VoIP: SIP signaling/ip firewall layer7-protocol add \ name=sip \ regexp="^(invite|register|ack|bye|options|cancel|message|subscribe|notify).+sip:"
# VoIP: H.323 call signaling/ip firewall layer7-protocol add \ name=h323 \ regexp="h323|q931|ras"
# DNS over plain UDP (for identification, not blocking)/ip firewall layer7-protocol add \ name=dns-query \ regexp="^.{2}\\x01\\x00.{4}"
# HTTP GET/POST requests (plaintext HTTP only)/ip firewall layer7-protocol add \ name=http \ regexp="^(get|post|head|put|delete|options|connect) .+ http/1"Manage Patterns
Section titled “Manage Patterns”# List all defined patterns/ip firewall layer7-protocol print
# Remove a pattern/ip firewall layer7-protocol remove [find name=bittorrent]
# Edit a pattern/ip firewall layer7-protocol set [find name=sip] regexp="<new-pattern>"Tip: Test patterns offline before deploying. Use
echo "payload" | grep -P "pattern"to validate regex syntax. Faulty patterns silently fail to match rather than generating errors.
Using L7 in Firewall Filter Rules
Section titled “Using L7 in Firewall Filter Rules”Reference a pattern by name with the layer7-protocol= matcher in filter rules. L7 can be combined with any other matcher.
Block P2P (TCP and UDP)
Section titled “Block P2P (TCP and UDP)”/ip firewall filter
# Must accept established/related BEFORE L7 rules# (L7 only operates in the 10-packet window; established flows won't be inspected)add chain=forward connection-state=established,related action=acceptadd chain=forward connection-state=invalid action=drop
# Drop BitTorrent TCPadd chain=forward \ in-interface-list=LAN out-interface-list=WAN \ protocol=tcp layer7-protocol=bittorrent \ action=drop comment="Block BitTorrent TCP"
# Drop BitTorrent UDPadd chain=forward \ in-interface-list=LAN out-interface-list=WAN \ protocol=udp layer7-protocol=bittorrent \ action=drop comment="Block BitTorrent UDP"Block SIP from WAN (Anti-Toll Fraud)
Section titled “Block SIP from WAN (Anti-Toll Fraud)”/ip firewall filter add chain=input \ in-interface-list=WAN \ protocol=udp dst-port=5060 \ layer7-protocol=sip \ action=drop comment="Block unsolicited SIP from WAN"Using L7 in Mangle Rules
Section titled “Using L7 in Mangle Rules”Mangle is the preferred place for L7 when the goal is traffic classification rather than blocking. Mark connections during the inspection window, then use the mark in downstream filter, queue, or routing rules.
Mark VoIP for QoS
Section titled “Mark VoIP for QoS”/ip firewall mangle
# Mark SIP connections in prerouting (catches early packets)add chain=prerouting \ protocol=udp dst-port=5060 \ layer7-protocol=sip \ action=mark-connection new-connection-mark=voip-sip passthrough=yes \ comment="Mark SIP connection"
# Mark all packets belonging to the SIP connectionadd chain=prerouting \ connection-mark=voip-sip \ action=mark-packet new-packet-mark=voip-priority passthrough=no \ comment="Mark SIP packets for QoS"Then apply a queue with priority to voip-priority packet-marked traffic.
Mark Application Traffic for Reporting
Section titled “Mark Application Traffic for Reporting”/ip firewall mangle
# Mark HTTP traffic for accountingadd chain=forward \ protocol=tcp dst-port=80 \ layer7-protocol=http \ action=mark-connection new-connection-mark=http-conn passthrough=yes
add chain=forward \ connection-mark=http-conn \ action=mark-packet new-packet-mark=http-traffic passthrough=noPerformance Optimization
Section titled “Performance Optimization”L7 is the most CPU-intensive firewall matcher. Every candidate packet in the inspection window has the regex applied to its payload in software.
Staged Filtering Pattern
Section titled “Staged Filtering Pattern”Pre-filter with cheap matchers to minimize the number of packets reaching the L7 rule:
/ip firewall mangle
# Stage 1: Identify candidates with cheap port-based matchadd chain=forward \ protocol=tcp dst-port=6881-6889 \ action=mark-connection new-connection-mark=bt-candidates passthrough=yes \ comment="Candidate BitTorrent ports"
# Stage 2: Apply L7 only to candidatesadd chain=forward \ connection-mark=bt-candidates \ layer7-protocol=bittorrent \ action=mark-connection new-connection-mark=bt-confirmed passthrough=no \ comment="Confirm with L7 regex"
/ip firewall filter
# Stage 3: Drop confirmed — cheap mark-based matchadd chain=forward \ connection-mark=bt-confirmed \ action=drop comment="Drop confirmed BitTorrent"Optimization Guidelines
Section titled “Optimization Guidelines”| Practice | Reason |
|---|---|
Accept established,related before L7 | Established flows are never inspected anyway — skip them early |
Scope with in-interface-list / out-interface-list | Limit L7 to the relevant traffic path |
Scope with protocol= and dst-port= | Reduce candidate set before regex runs |
Use passthrough=no on final mangle mark | Stop processing once matched |
Use prerouting chain in mangle | Catches packets earlier in the window |
Limitations
Section titled “Limitations”| Limitation | Impact |
|---|---|
| 10-packet / 2 KB window | Protocols with late handshakes may not be caught |
| Encrypted traffic | TLS, QUIC, WireGuard — regex cannot match ciphertext |
| Asymmetric routing | One-sided visibility means patterns that need bidirectional data will fail |
| P2P obfuscation | Modern BitTorrent and other P2P clients randomize or encrypt handshakes |
| CPU cost | On gigabit links with many flows, L7 can saturate a CPU core |
| No protocol versioning | Regex patterns must be updated manually when application protocols change |
L7 vs Other Methods
Section titled “L7 vs Other Methods”| Method | Encrypted | CPU Cost | Accuracy | RouterOS Built-in |
|---|---|---|---|---|
| L7 regex | No | Medium | Good for plaintext | Yes |
| Port-based | N/A | Very low | Protocol-agnostic | Yes |
| Address lists | N/A | Low | IP-level only | Yes |
| DSCP matching | N/A | Very low | Relies on upstream marking | Yes |
| External DPI | Yes (with SSL inspection) | High | High | No |
Troubleshooting
Section titled “Troubleshooting”L7 Rule Never Matches
Section titled “L7 Rule Never Matches”Problem: Rule hit counter stays at 0.
Check connection tracking:
/ip firewall connection tracking print# tracking must be enabled (auto or yes)Check asymmetric routing: Both directions of traffic must pass through the router. Verify with:
/tool traceroute <destination>Check rule ordering: The L7 rule must come before any rule that accepts the connection. If connection-state=established,related action=accept appears first, packets in the inspection window are accepted before reaching the L7 rule.
# Correct order: L7 rule BEFORE the established/related accept/ip firewall filter print# Verify L7 rule number is lower than established/related accept ruleCheck inspection window: If the connection was already established before the rule was added, existing connections won’t be re-inspected. Test with a fresh connection.
Pattern Not Matching Expected Traffic
Section titled “Pattern Not Matching Expected Traffic”Validate regex offline:
# On a Linux machine, test the payload against the patternecho -n "payload bytes here" | grep -P "your-pattern"Use Torch to verify traffic reaches the interface:
/tool torch interface=ether1 src-address=<client-ip>Check rule statistics:
# See hit counts per rule/ip firewall filter print stats/ip firewall mangle print stats
# List defined L7 patterns/ip firewall layer7-protocol printMonitor Matched Connections
Section titled “Monitor Matched Connections”# View connections with a specific mark/ip firewall connection print where connection-mark=bt-confirmed
# Count matched connections/ip firewall connection print count-only where connection-mark=bt-confirmedSee Also
Section titled “See Also”- Firewall Filter Rules — chains, actions, connection-state matchers
- Mangle — connection marks, packet marks, and traffic classification
- Connection Tracking — required for L7 to function
- Address Lists — IP-based blocking as a complement to L7
- Simple Queues — apply QoS to L7-marked traffic