Firewall Address Lists
Firewall Address Lists
Section titled “Firewall Address Lists”Address lists are named groups of IP addresses and subnets that can be referenced as match criteria in firewall filter, NAT, and mangle rules. They separate the “what IPs” concern from the “what action” concern, making rulesets easier to read and maintain. Entries can be added statically at configuration time or populated dynamically by firewall rules at runtime.
Quick Start
Section titled “Quick Start”Block a set of IPs and allow a trusted management range using address lists:
# Define the lists/ip firewall address-listadd list=blocked address=203.0.113.10 comment="known bad actor"add list=blocked address=198.51.100.0/24 comment="abusive subnet"add list=mgmt_hosts address=192.168.100.10 comment="admin workstation"add list=mgmt_hosts address=192.168.100.11 comment="admin workstation 2"
# Use the lists in filter rules/ip firewall filteradd chain=input src-address-list=blocked action=drop comment="drop blocked IPs"add chain=input src-address-list=mgmt_hosts action=accept comment="allow mgmt access"Static Address Lists
Section titled “Static Address Lists”Static entries are added manually and persist until explicitly removed. They survive reboots and are stored in the router configuration.
Adding Entries
Section titled “Adding Entries”/ip firewall address-list
# Single hostadd list=trusted_servers address=10.0.0.5 comment="app server"
# Subnetadd list=trusted_servers address=10.0.1.0/24 comment="office LAN"
# IPv6 (use /ipv6 firewall address-list)/ipv6 firewall address-listadd list=trusted_v6 address=2001:db8::/32 comment="trusted IPv6 range"Viewing and Removing Entries
Section titled “Viewing and Removing Entries”# List all entries/ip firewall address-list print
# List entries in a specific list/ip firewall address-list print where list=blocked
# Remove a specific entry/ip firewall address-list remove [find list=blocked address=203.0.113.10]
# Flush all entries from a list/ip firewall address-list remove [find list=blocked]Dynamic Address Lists
Section titled “Dynamic Address Lists”Firewall rules can add IPs to address lists at runtime using the add-src-to-address-list and add-dst-to-address-list actions. Dynamic entries are created when packets match the rule and are automatically removed when their timeout expires.
add-src-to-address-list
Section titled “add-src-to-address-list”Adds the packet’s source IP to a named list:
/ip firewall filteradd chain=input protocol=tcp dst-port=22 \ action=add-src-to-address-list \ address-list=ssh_scanners \ address-list-timeout=1h \ comment="flag SSH connection attempts"add-dst-to-address-list
Section titled “add-dst-to-address-list”Adds the packet’s destination IP to a named list — useful for tracking which internal hosts are being targeted:
/ip firewall mangleadd chain=prerouting src-address-list=suspect_clients \ action=add-dst-to-address-list \ address-list=targeted_hosts \ address-list-timeout=30m \ comment="track destinations reached by suspect clients"Timeout Values
Section titled “Timeout Values”The address-list-timeout parameter accepts durations in NdNhNmNs format, or 0 for no expiry (permanent entry):
| Value | Meaning |
|---|---|
0 | Entry is permanent (survives reboot) |
30s | 30 seconds |
5m | 5 minutes |
1h | 1 hour |
1d | 1 day |
2d3h30m | 2 days, 3 hours, 30 minutes |
TTL-Based Temporary Blocks
Section titled “TTL-Based Temporary Blocks”Combining dynamic population with timeouts implements automatic expiry — addresses are blocked for a set period and then reinstated without manual cleanup.
Simple Timed Block
Section titled “Simple Timed Block”/ip firewall address-list# Manually add a host that should be blocked for 24 hoursadd list=temp_blocked address=203.0.113.55 timeout=1d comment="manual 24h block"Port-Scan Detection and Auto-Expiry
Section titled “Port-Scan Detection and Auto-Expiry”/ip firewall filter
# Stage 1: detect port scan attempt (NEW connection to a port that should be closed)add chain=input protocol=tcp dst-port=23,3389,4899 connection-state=new \ action=add-src-to-address-list \ address-list=port_scanners \ address-list-timeout=10m \ comment="tag port scanner — expires after 10 min"
# Stage 2: drop tagged scannersadd chain=input src-address-list=port_scanners action=drop \ comment="drop port scanners"Multi-Stage SSH Brute Force Protection
Section titled “Multi-Stage SSH Brute Force Protection”A classic “tarpit” pattern: an IP must trigger multiple rules before it is blacklisted. Legitimate users who mistype a password once are not blocked; persistent attackers are.
/ip firewall filter
# Stage 1: first attempt — tag for 1 minuteadd chain=input protocol=tcp dst-port=22 connection-state=new \ src-address-list=!ssh_stage2 \ action=add-src-to-address-list \ address-list=ssh_stage1 \ address-list-timeout=1m \ comment="SSH stage1 — first attempt"
# Stage 2: second attempt within stage1 window — escalate for 1 houradd chain=input protocol=tcp dst-port=22 connection-state=new \ src-address-list=ssh_stage1 \ action=add-src-to-address-list \ address-list=ssh_stage2 \ address-list-timeout=1h \ comment="SSH stage2 — repeated attempt"
# Drop anyone in stage2 (active brute-force)add chain=input src-address-list=ssh_stage2 action=drop \ comment="drop SSH brute-force attackers"Using Lists Across Filter, NAT, and Mangle
Section titled “Using Lists Across Filter, NAT, and Mangle”Address lists are referenced identically across all firewall tables using src-address-list= and dst-address-list= match parameters.
Filter Rules
Section titled “Filter Rules”/ip firewall filter
# Drop outbound traffic to known C2 serversadd chain=forward dst-address-list=known_c2 action=drop \ comment="block traffic to known C2 IPs"
# Accept management access from trusted hosts onlyadd chain=input src-address-list=mgmt_hosts protocol=tcp \ dst-port=22,8291 action=accept \ comment="allow management from trusted hosts"
# Drop all other management attemptsadd chain=input protocol=tcp dst-port=22,8291 action=drop \ comment="drop all other management attempts"NAT Rules
Section titled “NAT Rules”/ip firewall nat
# Masquerade only clients in the allowed_internet listadd chain=srcnat src-address-list=allowed_internet \ out-interface=ether1-wan action=masquerade \ comment="NAT approved clients"
# Port-forward to internal server only from partner IPsadd chain=dstnat src-address-list=partners \ protocol=tcp dst-port=443 \ action=dst-nat to-addresses=10.0.0.20 to-ports=443 \ comment="DNAT partner HTTPS to internal server"Mangle Rules
Section titled “Mangle Rules”/ip firewall mangle
# Mark packets from VoIP handsets for QoS treatmentadd chain=prerouting src-address-list=voip_handsets \ action=mark-packet new-packet-mark=voip passthrough=yes \ comment="mark VoIP traffic for QoS"
# Mark connections from guest VLAN for bandwidth limitingadd chain=prerouting src-address-list=guest_clients \ action=mark-connection new-connection-mark=guest passthrough=yes \ comment="tag guest connections"IP Set-Style Patterns
Section titled “IP Set-Style Patterns”RouterOS address lists function like IP sets — a single named list can be maintained independently of the rules that reference it. This pattern scales well when the same group of IPs needs different treatment in multiple rule tables.
Centralized List, Multiple Rules
Section titled “Centralized List, Multiple Rules”# Maintain one list of CDN egress addresses/ip firewall address-listadd list=cdn_egress address=192.0.2.0/24add list=cdn_egress address=198.51.100.128/25
# Reference from filter (accept bypass)/ip firewall filteradd chain=forward src-address-list=cdn_egress action=accept \ comment="accept CDN egress traffic"
# Reference from mangle (different QoS marking)/ip firewall mangleadd chain=prerouting src-address-list=cdn_egress \ action=mark-packet new-packet-mark=cdn passthrough=yes \ comment="mark CDN traffic for QoS"Negation Matching
Section titled “Negation Matching”Prefix a list name with ! to match packets whose address is not in the list:
/ip firewall filter
# Block SSH from anyone not in the mgmt_hosts listadd chain=input protocol=tcp dst-port=22 \ src-address-list=!mgmt_hosts action=drop \ comment="SSH only from mgmt hosts"Combining Lists with Connection State
Section titled “Combining Lists with Connection State”Match on both address list membership and connection state for more precise control:
/ip firewall filter
# Accept new connections only from known partnersadd chain=input src-address-list=partners \ connection-state=new action=accept \ comment="allow new connections from partners"
# Reject new connections from everyone elseadd chain=input connection-state=new action=reject \ reject-with=icmp-admin-prohibited \ comment="reject all other new inbound"Script-Based Auto-Population
Section titled “Script-Based Auto-Population”Scripts combined with the scheduler can pull external IP lists (threat feeds, blocklists) into an address list on a recurring schedule.
Fetching an External Blocklist
Section titled “Fetching an External Blocklist”/system scriptadd name=update-ext-blacklist source={ :local url "https://example.org/blocklist.txt" :local dstPath "ext-blacklist.txt" :local listName "ext-blacklist"
# Download the latest list /tool fetch url=$url dst-path=$dstPath
# Remove previously imported entries (identified by comment) /ip firewall address-list remove [find list=$listName comment="auto-import"]
# Parse and import each line :local contents [/file get $dstPath contents] :foreach line in=[:toarray $contents] do={ # Skip blank lines and comments starting with # :if ([:len $line] > 0 && [:find $line "#"] = (-1)) do={ /ip firewall address-list add list=$listName address=$line \ comment="auto-import" } }}Scheduling Regular Updates
Section titled “Scheduling Regular Updates”/system scheduleradd name=blacklist-refresh interval=1h on-event=update-ext-blacklist \ comment="refresh external blocklist every hour"Static Seed + Dynamic Refresh Pattern
Section titled “Static Seed + Dynamic Refresh Pattern”Pre-seed the list with known-bad ranges, then let the scheduler top it up:
# Permanent static entries (no timeout = survive reboot)/ip firewall address-listadd list=ext-blacklist address=192.0.2.0/24 comment="static seed — RFC5737"add list=ext-blacklist address=198.51.100.0/24 comment="static seed — RFC5737"
# Drop everything in the list/ip firewall filteradd chain=forward dst-address-list=ext-blacklist action=drop \ comment="block destinations in external blacklist"add chain=forward src-address-list=ext-blacklist action=drop \ comment="block sources in external blacklist"Note:
/tool fetchrequires a reachable DNS resolver and outbound HTTPS. Ensure the firewall does not block the router’s own outbound traffic before enabling scheduled fetches.
Blacklist and Whitelist Patterns
Section titled “Blacklist and Whitelist Patterns”Inbound IP Blacklist
Section titled “Inbound IP Blacklist”Collect known-bad source IPs in one list and drop them early in the input chain:
/ip firewall address-listadd list=ip-blacklist address=203.0.113.10 comment="abusive host"add list=ip-blacklist address=198.51.100.0/24 comment="abusive subnet"
/ip firewall filter# Place this rule near the top of the input chainadd chain=input src-address-list=ip-blacklist action=drop \ comment="drop blacklisted sources"Outbound IP Blacklist (C2 / Malware Blocking)
Section titled “Outbound IP Blacklist (C2 / Malware Blocking)”/ip firewall address-listadd list=c2-blacklist address=192.0.2.50 comment="known C2 server"add list=c2-blacklist address=198.51.100.99 comment="known C2 server"
/ip firewall filteradd chain=forward dst-address-list=c2-blacklist action=drop \ comment="block outbound to known C2 IPs"Trusted Whitelist (Allowlist)
Section titled “Trusted Whitelist (Allowlist)”A whitelist accepts traffic from known-good sources and prevents them from being affected by later drop rules:
/ip firewall address-listadd list=ip-whitelist address=10.0.0.0/8 comment="internal ranges"add list=ip-whitelist address=192.168.0.0/16 comment="RFC1918"
/ip firewall filter# Accept before any blocking rulesadd chain=input src-address-list=ip-whitelist action=accept \ comment="accept trusted whitelist — early return"
# Blacklist rules followadd chain=input src-address-list=ip-blacklist action=drop \ comment="drop blacklisted sources"Combined Whitelist + Dynamic Blacklist
Section titled “Combined Whitelist + Dynamic Blacklist”Whitelisted IPs are never blacklisted; all other repeat offenders are blocked automatically:
/ip firewall filter
# 1. Skip whitelisted sources — they can never be blacklistedadd chain=input src-address-list=ip-whitelist action=accept \ comment="whitelist — bypass all checks"
# 2. Drop confirmed offendersadd chain=input src-address-list=ip-blacklist action=drop \ comment="drop dynamic blacklist"
# 3. Detect offenders (SSH brute force) and promote to blacklistadd chain=input protocol=tcp dst-port=22 connection-state=new \ src-address-list=!ip-whitelist \ action=add-src-to-address-list \ address-list=ssh-attempts \ address-list-timeout=2m \ comment="flag SSH attempt"
add chain=input protocol=tcp dst-port=22 connection-state=new \ src-address-list=ssh-attempts \ action=add-src-to-address-list \ address-list=ip-blacklist \ address-list-timeout=1d \ comment="promote repeat offender to blacklist for 24h"Expiry Management
Section titled “Expiry Management”Dynamic entries created by firewall rules expire automatically based on address-list-timeout. Entries added directly to /ip firewall address-list can also carry a timeout:
# Manual timed block — entry is removed automatically after the timeout/ip firewall address-listadd list=ip-blacklist address=203.0.113.77 timeout=6h \ comment="manual block — expires in 6 hours"
# View current dynamic entries and their remaining TTL/ip firewall address-list print where dynamic=yes
# Remove all expired-ish entries manually (already expired entries are auto-removed;# this removes entries you added with a comment marker)/ip firewall address-list remove [find list=ip-blacklist comment="auto-import"]Reference
Section titled “Reference”/ip firewall address-list Parameters
Section titled “/ip firewall address-list Parameters”| Parameter | Description |
|---|---|
list | Name of the address list |
address | IPv4 address, subnet (CIDR), or range (e.g. 10.0.0.1-10.0.0.10) |
timeout | Optional expiry duration; 0 = permanent |
comment | Free-text annotation |
disabled | If yes, entry is ignored by rules |
Dynamic Action Parameters (in filter/mangle/nat rules)
Section titled “Dynamic Action Parameters (in filter/mangle/nat rules)”| Parameter | Description |
|---|---|
action | add-src-to-address-list or add-dst-to-address-list |
address-list | Name of the list to add the IP to |
address-list-timeout | How long the entry persists; 0 = permanent |
Match Parameters (in filter/mangle/nat rules)
Section titled “Match Parameters (in filter/mangle/nat rules)”| Parameter | Description |
|---|---|
src-address-list=<name> | Match packets whose source IP is in the list |
dst-address-list=<name> | Match packets whose destination IP is in the list |
src-address-list=!<name> | Match packets whose source IP is not in the list |
dst-address-list=!<name> | Match packets whose destination IP is not in the list |