Firewall and QoS Case Studies
Firewall and QoS Case Studies
Section titled “Firewall and QoS Case Studies”Summary
Section titled “Summary”This section provides practical case studies demonstrating how to build comprehensive firewall configurations and implement Quality of Service (QoS) traffic prioritization on MikroTik routers running RouterOS. These case studies cover real-world scenarios including advanced firewall building with RAW filtering, protecting both the router and connected clients, and using connection rate-based traffic detection for intelligent bandwidth management.
The examples illustrate proper usage of firewall features including interface-lists, address-lists, RAW chains, connection tracking, and mangle rules for traffic classification. Each case study presents complete configuration examples that can be adapted to specific network environments while following security best practices and RFC recommendations.
Building an Advanced Firewall
Section titled “Building an Advanced Firewall”This case study demonstrates how to build a comprehensive firewall using multiple firewall features together. The approach uses RAW firewall for high-performance early packet filtering, with regular firewall rules handling only essential filtering tasks. This architecture maximizes router performance while maintaining strong security posture.
Overview
Section titled “Overview”Building an advanced firewall requires combining multiple RouterOS firewall features in a layered approach. RAW firewall chains process packets before connection tracking, allowing early dropping of unwanted traffic without consuming connection tracking resources. Regular firewall filter chains handle stateful inspection for legitimate traffic, while NAT rules provide address translation for outbound connections.
The configuration separates IPv4 and IPv6 handling, applies interface-lists for easier management, and implements defense-in-depth principles with multiple validation layers. Most traffic filtering occurs in RAW chains, with the regular firewall containing minimal rules for established/related connections and final access control.
Interface-Lists Configuration
Section titled “Interface-Lists Configuration”Interface-lists provide a centralized way to manage interface groupings. Create WAN and LAN lists to simplify firewall rule maintenance across multiple interfaces.
/interface list add comment=defconf name=WAN add comment=defconf name=LAN/interface list member add comment=defconf interface=bridge list=LAN add comment=defconf interface=ether1 list=WANAdd all internet-facing interfaces to the WAN list, such as ether1, pppoe-out, or wireless interfaces providing uplink connectivity. Add all internal network interfaces to the LAN list, including bridge interfaces representing internal networks. This abstraction allows firewall rules to reference in-interface-list=LAN rather than individual interface names, simplifying future changes when adding new network segments.
Protecting the Router
Section titled “Protecting the Router”The input chain controls traffic destined for the router itself. Default policy should deny all access except explicitly permitted traffic from trusted networks.
IPv4 Input Rules:
/ip firewall filter add action=accept chain=input comment="defconf: accept ICMP after RAW" protocol=icmp add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked add action=drop chain=input comment="defconf: drop all not coming from LAN" in-interface-list=!LANIPv6 Input Rules:
/ipv6 firewall filteradd action=accept chain=input comment="defconf: accept ICMPv6 after RAW" protocol=icmpv6add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untrackedadd action=accept chain=input comment="defconf: accept UDP traceroute" dst-port=33434-33534 protocol=udpadd action=accept chain=input comment="defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=udp src-address=fe80::/10add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 protocol=udpadd action=accept chain=input comment="defconf: accept IPsec AH" protocol=ipsec-ahadd action=accept chain=input comment="defconf: accept IPsec ESP" protocol=ipsec-espadd action=drop chain=input comment="defconf: drop all not coming from LAN" in-interface-list=!LANThe ICMPv6 rules include UDP traceroute ports, DHCPv6 prefix delegation, and IPsec protocols as recommended by RFC 4890 for proper IPv6 network operation. When using DHCPv6 relay, adjust the source address filter to accept relay addresses instead of link-local addresses.
Protecting Connected Clients
Section titled “Protecting Connected Clients”Client protection focuses on preventing unauthorized access attempts from the internet and blocking traffic to/from non-routable address ranges. Create address-lists containing addresses that should never be forwarded.
IPv4 Block Lists:
/ip firewall address-list add address=0.0.0.0/8 comment="defconf: RFC6890" list=no_forward_ipv4 add address=169.254.0.0/16 comment="defconf: RFC6890" list=no_forward_ipv4 add address=224.0.0.0/4 comment="defconf: multicast" list=no_forward_ipv4 add address=255.255.255.255/32 comment="defconf: RFC6890" list=no_forward_ipv4IPv6 Block Lists:
/ipv6 firewall address-list add address=fe80::/10 comment="defconf: RFC6890 Linked-Scoped Unicast" list=no_forward_ipv6 add address=ff00::/8 comment="defconf: multicast" list=no_forward_ipv6Disable multicast entries if multicast forwarding is required in the network.
Forward Chain Rules:
/ip firewall filter add action=accept chain=forward comment="defconf: accept all that matches IPsec policy" ipsec-policy=in,ipsec disabled=yes add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-state=established,related add action=accept chain=forward comment="defconf: accept established,related, untracked" connection-state=established,related,untracked add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid add action=drop chain=forward comment="defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat connection-state=new in-interface-list=WAN add action=drop chain=forward src-address-list=no_forward_ipv4 comment="defconf: drop bad forward IPs" add action=drop chain=forward dst-address-list=no_forward_ipv4 comment="defconf: drop bad forward IPs"The rule dropping new connections from WAN that are not DSTNATed provides protection against direct attacks on internal clients. Even if RAW rules are misconfigured, this double-layer protection prevents unauthorized access attempts from reaching internal network addresses.
NAT Configuration for Local Networks
Section titled “NAT Configuration for Local Networks”Enable NAT for devices behind the router to access the internet. Use masquerade for dynamic WAN addresses or src-nat for static addresses.
/ip firewall nat add action=accept chain=srcnat comment="defconf: accept all that matches IPsec policy" ipsec-policy=out,ipsec disabled=yes add action=masquerade chain=srcnat comment="defconf: masquerade" out-interface-list=WANEnable the IPsec policy matcher rule when using IPsec tunnels to prevent NAT from modifying encrypted IPsec traffic. This rule is disabled by default and must be explicitly enabled when IPsec is deployed.
RAW Filtering
Section titled “RAW Filtering”RAW chains provide high-performance packet filtering before connection tracking. Use RAW rules to drop unwanted traffic early, reducing CPU load on the regular firewall and connection tracking table.
IPv4 Address Lists for RAW
Section titled “IPv4 Address Lists for RAW”Create address-lists identifying addresses that should be dropped immediately upon detection.
Bogon IPs (Never valid on public internet):
/ip firewall address-list add address=127.0.0.0/8 comment="defconf: RFC6890" list=bad_ipv4 add address=192.0.0.0/24 comment="defconf: RFC6890" list=bad_ipv4 add address=192.0.2.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4 add address=198.51.100.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4 add address=203.0.113.0/24 comment="defconf: RFC6890 documentation" list=bad_ipv4 add address=240.0.0.0/4 comment="defconf: RFC6890 reserved" list=bad_ipv4Non-Globally-Routable IPs:
/ip firewall address-list add address=0.0.0.0/8 comment="defconf: RFC6890" list=not_global_ipv4 add address=10.0.0.0/8 comment="defconf: RFC6890" list=not_global_ipv4 add address=100.64.0.0/10 comment="defconf: RFC6890" list=not_global_ipv4 add address=169.254.0.0/16 comment="defconf: RFC6890" list=not_global_ipv4 add address=172.16.0.0/12 comment="defconf: RFC6890" list=not_global_ipv4 add address=192.0.0.0/29 comment="defconf: RFC6890" list=not_global_ipv4 add address=192.168.0.0/16 comment="defconf: RFC6890" list=not_global_ipv4 add address=198.18.0.0/15 comment="defconf: RFC6890 benchmark" list=not_global_ipv4 add address=255.255.255.255/32 comment="defconf: RFC6890" list=not_global_ipv4Invalid Source and Destination Addresses:
/ip firewall address-list add address=224.0.0.0/4 comment="defconf: multicast" list=bad_src_ipv4 add address=255.255.255.255/32 comment="defconf: RFC6890" list=bad_src_ipv4 add address=0.0.0.0/8 comment="defconf: RFC6890" list=bad_dst_ipv4 add address=224.0.0.0/4 comment="defconf: RFC6890" list=bad_dst_ipv4IPv4 RAW Rules
Section titled “IPv4 RAW Rules”/ip firewall rawadd action=accept chain=prerouting comment="defconf: enable for transparent firewall" disabled=yesadd action=accept chain=prerouting comment="defconf: accept DHCP discover" dst-address=255.255.255.255 dst-port=67 in-interface-list=LAN protocol=udp src-address=0.0.0.0 src-port=68add action=drop chain=prerouting comment="defconf: drop bogon IP's" src-address-list=bad_ipv4add action=drop chain=prerouting comment="defconf: drop bogon IP's" dst-address-list=bad_ipv4add action=drop chain=prerouting comment="defconf: drop bogon IP's" src-address-list=bad_src_ipv4add action=drop chain=prerouting comment="defconf: drop bogon IP's" dst-address-list=bad_dst_ipv4add action=drop chain=prerouting comment="defconf: drop non global from WAN" src-address-list=not_global_ipv4 in-interface-list=WANadd action=drop chain=prerouting comment="defconf: drop forward to local lan from WAN" in-interface-list=WAN dst-address=192.168.88.0/24add action=drop chain=prerouting comment="defconf: drop local if not from default IP range" in-interface-list=LAN src-address=!192.168.88.0/24add action=drop chain=prerouting comment="defconf: drop bad UDP" port=0 protocol=udpadd action=jump chain=prerouting comment="defconf: jump to ICMP chain" jump-target=icmp4 protocol=icmpadd action=jump chain=prerouting comment="defconf: jump to TCP chain" jump-target=bad_tcp protocol=tcpadd action=accept chain=prerouting comment="defconf: accept everything else from LAN" in-interface-list=LANadd action=accept chain=prerouting comment="defconf: accept everything else from WAN" in-interface-list=WANadd action=accept chain=prerouting comment="defconf: accept local traffic between router interfaces" src-address-type=localadd action=drop chain=prerouting comment="defconf: drop the rest"TCP Flag Validation Chain:
/ip firewall rawadd action=drop chain=bad_tcp comment="defconf: TCP flag filter" protocol=tcp tcp-flags=!fin,!syn,!rst,!ackadd action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,synadd action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,rstadd action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,!ackadd action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=fin,urgadd action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=syn,rstadd action=drop chain=bad_tcp comment=defconf protocol=tcp tcp-flags=rst,urgadd action=drop chain=bad_tcp comment="defconf: TCP port 0 drop" port=0 protocol=tcpICMP Validation Chain:
/ip firewall rawadd action=accept chain=icmp4 comment="defconf: echo reply" icmp-options=0:0 limit=5,10:packet protocol=icmpadd action=accept chain=icmp4 comment="defconf: net unreachable" icmp-options=3:0 protocol=icmpadd action=accept chain=icmp4 comment="defconf: host unreachable" icmp-options=3:1 protocol=icmpadd action=accept chain=icmp4 comment="defconf: protocol unreachable" icmp-options=3:2 protocol=icmpadd action=accept chain=icmp4 comment="defconf: port unreachable" icmp-options=3:3 protocol=icmpadd action=accept chain=icmp4 comment="defconf: fragmentation needed" icmp-options=3:4 protocol=icmpadd action=accept chain=icmp4 comment="defconf: echo" icmp-options=8:0 limit=5,10:packet protocol=icmpadd action=accept chain=icmp4 comment="defconf: time exceeded " icmp-options=11:0-255 protocol=icmpadd action=drop chain=icmp4 comment="defconf: drop other icmp" protocol=icmpThe ICMP rate limiting (limit=5,10:packet) restricts ping responses to 5 packets per 10 seconds, preventing ICMP-based DoS attacks while maintaining diagnostic functionality. This strict ICMP filtering is optional and typically unnecessary in most environments since the Linux kernel already limits ICMP to 100 packets per second.
IPv6 Address Lists for RAW
Section titled “IPv6 Address Lists for RAW”Bogon and Invalid IPv6 Addresses:
/ipv6 firewall address-listadd address=::1/128 comment="defconf: RFC6890 lo" list=bad_ipv6add address=::ffff:0:0/96 comment="defconf: RFC6890 IPv4 mapped" list=bad_ipv6add address=2001::/23 comment="defconf: RFC6890" list=bad_ipv6add address=2001:db8::/32 comment="defconf: RFC6890 documentation" list=bad_ipv6add address=2001:10::/28 comment="defconf: RFC6890 orchid" list=bad_ipv6add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6Non-Globally-Routable IPv6 Addresses:
/ipv6 firewall address-listadd address=100::/64 comment="defconf: RFC6890 Discard-only" list=not_global_ipv6add address=2001::/32 comment="defconf: RFC6890 TEREDO" list=not_global_ipv6add address=2001:2::/48 comment="defconf: RFC6890 Benchmark" list=not_global_ipv6add address=fc00::/7 comment="defconf: RFC6890 Unique-Local" list=not_global_ipv6Invalid Source and Destination:
/ipv6 firewall address-listadd address=::/128 comment="defconf: unspecified" list=bad_dst_ipv6add address=::/128 comment="defconf: unspecified" list=bad_src_ipv6add address=ff00::/8 comment="defconf: multicast" list=bad_src_ipv6IPv6 RAW Rules
Section titled “IPv6 RAW Rules”/ipv6 firewall rawadd action=accept chain=prerouting comment="defconf: enable for transparent firewall" disabled=yesadd action=accept chain=prerouting comment="defconf: RFC4291, section 2.7.1" src-address=::/128 dst-address=ff02:0:0:0:0:1:ff00::/104 icmp-options=135 protocol=icmpv6add action=drop chain=prerouting comment="defconf: drop bogon IP's" src-address-list=bad_ipv6add action=drop chain=prerouting comment="defconf: drop bogon IP's" dst-address-list=bad_ipv6add action=drop chain=prerouting comment="defconf: drop packets with bad SRC ipv6" src-address-list=bad_src_ipv6add action=drop chain=prerouting comment="defconf: drop packets with bad dst ipv6" dst-address-list=bad_dst_ipv6add action=drop chain=prerouting comment="defconf: drop non global from WAN" src-address-list=not_global_ipv6 in-interface-list=WANadd action=jump chain=prerouting comment="defconf: jump to ICMPv6 chain" jump-target=icmp6 protocol=icmpv6add action=accept chain=prerouting comment="defconf: accept local multicast scope" dst-address=ff02::/16add action=drop chain=prerouting comment="defconf: drop other multicast destinations" dst-address=ff00::/8add action=accept chain=prerouting comment="defconf: accept everything else from WAN" in-interface-list=WANadd action=accept chain=prerouting comment="defconf: accept everything else from LAN" in-interface-list=LANadd action=drop chain=prerouting comment="defconf: drop the rest"ICMPv6 Validation Chain:
/ipv6 firewall rawadd action=drop chain=icmp6 comment="defconf: rfc4890 drop ll if hop-limit!=255" dst-address=fe80::/10 hop-limit!=255 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: dst unreachable" icmp-options=1:0-255 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: packet too big" icmp-options=2:0-255 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: limit exceeded" icmp-options=3:0-1 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: bad header" icmp-options=4:0-2 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: Mobile home agent address discovery" icmp-options=144:0-255 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: Mobile home agent address discovery" icmp-options=145:0-255 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: Mobile prefix solic" icmp-options=146:0-255 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: Mobile prefix advert" icmp-options=147:0-255 protocol=icmpv6add action=accept chain=icmp6 comment="defconf: echo request limit 5,10" icmp-options=128:0-255 limit=5,10:packet protocol=icmpv6add action=accept chain=icmp6 comment="defconf: echo reply limit 5,10" icmp-options=129:0-255 limit=5,10:packet protocol=icmpv6add action=accept chain=icmp6 comment="defconf: rfc4890 router solic limit 5,10 only LAN" hop-limit=equal:255 icmp-options=133:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6add action=accept chain=icmp6 comment="defconf: rfc4890 router advert limit 5,10 only LAN" hop-limit=equal:255 icmp-options=134:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6add action=accept chain=icmp6 comment="defconf: rfc4890 neighbor solic limit 5,10 only LAN" hop-limit=equal:255 icmp-options=135:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6add action=accept chain=icmp6 comment="defconf: rfc4890 neighbor advert limit 5,10 only LAN" hop-limit=equal:255 icmp-options=136:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6add action=accept chain=icmp6 comment="defconf: rfc4890 inverse ND solic limit 5,10 only LAN" hop-limit=equal:255 icmp-options=141:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6add action=accept chain=icmp6 comment="defconf: rfc4890 inverse ND advert limit 5,10 only LAN" hop-limit=equal:255 icmp-options=142:0-255 in-interface-list=LAN limit=5,10:packet protocol=icmpv6add action=drop chain=icmp6 comment="defconf: drop other icmp" protocol=icmpv6The hop-limit validation ensures that ICMPv6 packets received from off-link sources are dropped, preventing certain types of hop-limit-based attacks. Router and neighbor discovery messages are only accepted from the local link (LAN interface-list) with proper hop-limit of 255.
Connection Rate-Based Traffic Prioritization
Section titled “Connection Rate-Based Traffic Prioritization”The connection-rate matcher enables traffic classification based on connection speed, allowing identification and prioritization of different traffic types for QoS implementation.
Understanding Connection Rate
Section titled “Understanding Connection Rate”Connection Rate calculates the current speed of a connection based on the change in connection-bytes value. The connection rate is recalculated every second without averaging, providing real-time speed measurements. Both connection-bytes and connection-rate work with TCP and UDP traffic when a protocol is specified.
The syntax for connection-rate allows specifying a range: connection-rate=From-To where values range from 0 to 4294967295 bytes per second. Use suffixes like k for kilobytes and M for megabytes for convenience.
Example - Capturing slow connections:
/ip firewall filteradd action=accept chain=forward connection-rate=0-100k protocol=tcpadd action=accept chain=forward connection-rate=0-100k protocol=udpTraffic Prioritization Implementation
Section titled “Traffic Prioritization Implementation”Connection rate detection enables identifying “heavy” connections (P2P, large downloads, streaming) versus “light” connections (VoIP, gaming, web browsing) based on sustained throughput. This allows prioritizing interactive traffic while limiting bulk transfers.
For this example, assume HTTP browsing transfers less than 500KB total and VoIP requires less than 200kbps. Connections exceeding 500KB with sustained speed above 200kbps are classified as heavy traffic.
Mangle Rules for Connection Classification:
/ip firewall mangleadd chain=forward action=mark-connection connection-mark=!heavy_traffic_conn new-connection-mark=all_connadd chain=forward action=mark-connection connection-bytes=500000-0 connection-mark=all_conn connection-rate=200k-100M new-connection-mark=heavy_traffic_conn protocol=tcpadd chain=forward action=mark-connection connection-bytes=500000-0 connection-mark=all_conn connection-rate=200k-100M new-connection-mark=heavy_traffic_conn protocol=udpadd chain=forward action=mark-packet connection-mark=heavy_traffic_conn new-packet-mark=heavy_traffic passthrough=noadd chain=forward action=mark-packet connection-mark=all_conn new-packet-mark=other_traffic passthrough=noThe first rule marks all connections not already classified as heavy. Subsequent rules identify heavy connections based on total bytes transferred (over 500KB) and sustained rate (over 200kbps). Finally, packets are marked according to their connection classification.
Queue Tree Configuration:
/queue treeadd name=upload parent=public max-limit=6Madd name=other_upload parent=upload limit-at=4M max-limit=6M packet-mark=other_traffic priority=1add name=heavy_upload parent=upload limit-at=2M max-limit=6M packet-mark=heavy_traffic priority=8add name=download parent=local max-limit=6Madd name=other_download parent=download limit-at=4M max-limit=6M packet-mark=other_traffic priority=1add name=heavy_download parent=download limit-at=2M max-limit=6M packet-mark=heavy_traffic priority=8Priority 1 (highest) is assigned to other_traffic including VoIP and web browsing, while priority 8 (lowest) is assigned to heavy_traffic. The limit-at guarantees minimum bandwidth while max-limit caps maximum throughput.
Quick Configuration Summary
Section titled “Quick Configuration Summary”The complete configuration for a 6Mbps connection prioritizing interactive traffic:
/ip firewall mangleadd chain=forward action=mark-connection connection-mark=!heavy_traffic_conn new-connection-mark=all_connadd chain=forward action=mark-connection connection-bytes=500000-0 connection-mark=all_conn connection-rate=200k-100M new-connection-mark=heavy_traffic_conn protocol=tcpadd chain=forward action=mark-connection connection-bytes=500000-0 connection-mark=all_conn connection-rate=200k-100M new-connection-mark=heavy_traffic_conn protocol=udpadd chain=forward action=mark-packet connection-mark=heavy_traffic_conn new-packet-mark=heavy_traffic passthrough=noadd chain=forward action=mark-packet connection-mark=all_conn new-packet-mark=other_traffic passthrough=no
/queue treeadd name=upload parent=public max-limit=6Madd name=other_upload parent=upload limit-at=4M max-limit=6M packet-mark=other_traffic priority=1add name=heavy_upload parent=upload limit-at=2M max-limit=6M packet-mark=heavy_traffic priority=8add name=download parent=local max-limit=6Madd name=other_download parent=download limit-at=4M max-limit=6M packet-mark=other_traffic priority=1add name=heavy_download parent=download limit-at=2M max-limit=6M packet-mark=heavy_traffic priority=8Adjust the connection-bytes threshold (500KB) and connection-rate threshold (200kbps) based on actual network usage patterns. HTTP browsing may transfer more than 500KB on modern websites, and VoIP quality may require different bandwidth guarantees.
Related Information
Section titled “Related Information”- RFC 6890: Special-Purpose Address Registries
- RFC 4291: IP Version 6 Addressing Architecture
- RFC 4890: Recommendations for Filtering ICMPv6 Messages
- RAW Firewall: High-performance packet filtering before connection tracking
- Connection Tracking: Stateful inspection and traffic classification
- Queue Trees: Hierarchical token bucket for QoS implementation