Firewall Address Lists
Firewall Address Lists
Section titled “Firewall Address Lists”TL;DR (Quick Start)
Section titled “TL;DR (Quick Start)”For the impatient: create a whitelist and blacklist.
# Create trusted whitelist (permanent)/ip firewall address-list add list=trusted address=192.168.1.0/24 comment="LAN"/ip firewall address-list add list=trusted address=10.0.0.0/8 comment="VPN"
# Create temporary blacklist entry (expires in 1 day)/ip firewall address-list add list=blacklist address=203.0.113.50 timeout=1d
# Use in firewall rules/ip firewall filter add chain=input action=accept src-address-list=trusted/ip firewall filter add chain=input action=drop src-address-list=blacklistVerify:
/ip firewall address-list print where list=trusted/ip firewall address-list print where list=blacklistOverview
Section titled “Overview”What this does: Address lists group IP addresses, ranges, CIDR blocks, and DNS names under a common name. Firewall rules can then match against the entire list instead of individual addresses, simplifying rule management and enabling dynamic behaviors like brute force protection.
When to use this:
- Whitelisting trusted networks or management IPs
- Blacklisting attackers, spammers, or threat feeds
- Implementing port knocking or brute force protection
- Geographic IP blocking
- Grouping servers for NAT or routing policies
Key Concepts:
| Entry Type | Storage | Survives Reboot | Use Case |
|---|---|---|---|
| Static | Disk (NAND) | Yes | Permanent whitelists, RFC bogons |
| Dynamic | RAM | No | Temporary blocks, threat feeds |
Prerequisites:
- Basic firewall filter rules configured
- Connection tracking enabled (for
connection-statematching) - DNS configured (for FQDN entries)
Configuration Steps
Section titled “Configuration Steps”Step 1: Create Static Address List
Section titled “Step 1: Create Static Address List”Static entries are permanent and survive reboots. Use for trusted networks.
/ip firewall address-list add list=trusted address=192.168.1.0/24 comment="LAN"/ip firewall address-list add list=trusted address=10.0.0.0/8 comment="VPN networks"Supported address formats:
| Format | Example | Notes |
|---|---|---|
| Single IP | 192.168.1.1 | Single host |
| CIDR | 192.168.1.0/24 | Network prefix |
| Range | 192.168.0.0-192.168.1.255 | Auto-converts to CIDR |
| DNS name | office.example.com | Resolved automatically |
Step 2: Create Dynamic Address List
Section titled “Step 2: Create Dynamic Address List”Dynamic entries have a timeout and are stored in RAM. Use for temporary blocks.
# Block for 1 hour/ip firewall address-list add list=temp-block address=203.0.113.50 timeout=1h
# Block for 1 day/ip firewall address-list add list=blacklist address=198.51.100.25 timeout=1dTimeout formats:
30s- 30 seconds10m- 10 minutes2h- 2 hours1d- 1 day2w- 2 weeks1d2h30m- Combined format
Step 3: Add DNS Names
Section titled “Step 3: Add DNS Names”Address lists can resolve DNS names automatically:
/ip firewall address-list add list=allowed address=myoffice.dyndns.orgBehavior:
- RouterOS resolves the FQDN and adds IPs as dynamic entries
- Resolution follows DNS TTL for refresh timing
- The FQDN entry survives reboot; resolved IPs are dynamic
To force re-resolution:
/ip firewall address-list set [find where address~"dyndns.org"] disabled=yes/ip firewall address-list set [find where address~"dyndns.org"] disabled=noStep 4: Use in Firewall Rules
Section titled “Step 4: Use in Firewall Rules”Match traffic against address lists:
# Accept from trusted sources/ip firewall filter add chain=input action=accept src-address-list=trusted
# Drop blacklisted sources/ip firewall filter add chain=input action=drop src-address-list=blacklist
# NAT only for non-internal destinations/ip firewall nat add chain=srcnat action=masquerade out-interface=ether1 \ dst-address-list=!internal-networksMatchers:
src-address-list- Match packet source IPdst-address-list- Match packet destination IP
Common Mistakes
- Only ONE address list can be specified per matcher - to match multiple lists, use separate rules or combine the lists
- Always add your trusted IPs to a whitelist BEFORE enabling blacklist rules to avoid self-lockout
Dynamic List Actions
Section titled “Dynamic List Actions”Firewall rules can automatically add IPs to address lists based on traffic patterns.
add-src-to-address-list
Section titled “add-src-to-address-list”Adds packet’s source IP to a list:
/ip firewall filter add chain=input action=add-src-to-address-list \ address-list=ssh-attempts address-list-timeout=1h \ protocol=tcp dst-port=22 connection-state=newadd-dst-to-address-list
Section titled “add-dst-to-address-list”Adds packet’s destination IP to a list:
/ip firewall mangle add chain=prerouting action=add-dst-to-address-list \ address-list=visited-sites address-list-timeout=1h \ protocol=tcp dst-port=80,443Important: These actions operate in passthrough mode - packets continue to subsequent rules.
SSH Brute Force Protection
Section titled “SSH Brute Force Protection”Staged blocking with escalating timeouts:
# Drop blacklisted first (place at top of input chain)/ip firewall filter add chain=input action=drop \ protocol=tcp dst-port=22 src-address-list=ssh_blacklist
# Stage 1: First connection -> stage1 list (1 min)/ip firewall filter add chain=input action=add-src-to-address-list \ address-list=ssh_stage1 address-list-timeout=1m \ protocol=tcp dst-port=22 connection-state=new
# Stage 2: If in stage1 -> stage2 (1 min)/ip firewall filter add chain=input action=add-src-to-address-list \ address-list=ssh_stage2 address-list-timeout=1m \ protocol=tcp dst-port=22 connection-state=new \ src-address-list=ssh_stage1
# Stage 3: If in stage2 -> stage3 (1 min)/ip firewall filter add chain=input action=add-src-to-address-list \ address-list=ssh_stage3 address-list-timeout=1m \ protocol=tcp dst-port=22 connection-state=new \ src-address-list=ssh_stage2
# Stage 4: If in stage3 -> blacklist (10 days)/ip firewall filter add chain=input action=add-src-to-address-list \ address-list=ssh_blacklist address-list-timeout=10d \ protocol=tcp dst-port=22 connection-state=new \ src-address-list=ssh_stage3How it works: Each new connection advances the attacker through stages. Legitimate users who wait 1 minute between connections start fresh. After 4 rapid connections, the IP is blacklisted for 10 days.
Port Knocking
Section titled “Port Knocking”Sequential port access grants firewall bypass:
# Knock 1: Port 8888 -> added to knock1 for 30s/ip firewall filter add chain=input action=add-src-to-address-list \ address-list=knock1 address-list-timeout=30s \ protocol=tcp dst-port=8888 in-interface-list=WAN
# Knock 2: Port 7777 (only if in knock1) -> knock2 for 30s/ip firewall filter add chain=input action=add-src-to-address-list \ address-list=knock2 address-list-timeout=30s \ protocol=tcp dst-port=7777 in-interface-list=WAN \ src-address-list=knock1
# Knock 3: Port 6666 (only if in knock2) -> secured for 30m/ip firewall filter add chain=input action=add-src-to-address-list \ address-list=secured address-list-timeout=30m \ protocol=tcp dst-port=6666 in-interface-list=WAN \ src-address-list=knock2
# Accept traffic from secured list/ip firewall filter add chain=input action=accept \ in-interface-list=WAN src-address-list=securedClient access (Linux):
for port in 8888 7777 6666; do nmap -Pn -p $port router.example.com; doneInterface Lists
Section titled “Interface Lists”Group interfaces for use in firewall rules:
# Create lists/interface list add name=WAN comment="Internet-facing"/interface list add name=LAN comment="Internal networks"
# Add members/interface list member add interface=ether1 list=WAN/interface list member add interface=bridge list=LAN
# Use in firewall/ip firewall filter add chain=input action=accept in-interface-list=LAN/ip firewall filter add chain=input action=drop in-interface-list=WANMatchers:
in-interface-list- Match incoming interfaceout-interface-list- Match outgoing interface
RFC 6890 Bogon Lists
Section titled “RFC 6890 Bogon Lists”Block invalid source addresses:
/ip firewall address-listadd list=bogons address=0.0.0.0/8 comment="RFC6890: This host"add list=bogons address=127.0.0.0/8 comment="RFC6890: Loopback"add list=bogons address=192.0.0.0/24 comment="RFC6890: IETF Protocol"add list=bogons address=192.0.2.0/24 comment="RFC5737: TEST-NET-1"add list=bogons address=198.51.100.0/24 comment="RFC5737: TEST-NET-2"add list=bogons address=203.0.113.0/24 comment="RFC5737: TEST-NET-3"add list=bogons address=224.0.0.0/4 comment="RFC5771: Multicast"add list=bogons address=240.0.0.0/4 comment="RFC1112: Reserved"
# Private addresses (block from WAN)add list=private address=10.0.0.0/8 comment="RFC1918"add list=private address=172.16.0.0/12 comment="RFC1918"add list=private address=192.168.0.0/16 comment="RFC1918"add list=private address=169.254.0.0/16 comment="RFC3927: Link-local"add list=private address=100.64.0.0/10 comment="RFC6598: CGN"
# Drop bogons from WAN/ip firewall filter add chain=input action=drop in-interface-list=WAN \ src-address-list=bogons comment="Drop bogon sources"/ip firewall filter add chain=input action=drop in-interface-list=WAN \ src-address-list=private comment="Drop private sources from WAN"External Threat Feeds
Section titled “External Threat Feeds”Download and import external blocklists:
# Fetch DShield block list/tool fetch url="https://feeds.dshield.org/block.txt" dst-path=dshield.txt
# Import (requires .rsc format)/import file-name=dshield.rscLimitations:
- Maximum file size: 63 KiB (larger files get truncated)
- Import halts on duplicate entries (pre-filter your lists)
Verification
Section titled “Verification”# View all address lists/ip firewall address-list print
# View specific list/ip firewall address-list print where list=blacklist
# View dynamic entries only/ip firewall address-list print where dynamic=yes
# View with timeout countdown/ip firewall address-list print detail
# Count entries per list/ip firewall address-list print count-only where list=blacklist
# Check firewall rule hit counters/ip firewall filter print stats where src-address-list~"."
# View interface lists/interface list print/interface list member printExpected result: Address list entries visible with appropriate flags (D for dynamic). Firewall rules show hit counters increasing when traffic matches.
Performance Optimization
Section titled “Performance Optimization”RAW vs Filter for Blacklists
Section titled “RAW vs Filter for Blacklists”| Scenario | Use RAW | Use Filter |
|---|---|---|
| DDoS mitigation (high volume) | Yes | No |
| Large blacklist (10k+ entries) | Yes | No |
| Small list, low match rate | No | Yes |
| Need connection state | No | Yes |
| Need TCP reset on reject | No | Yes |
# RAW-based blacklist (most efficient for DDoS)/ip firewall raw add chain=prerouting src-address-list=blacklist action=dropRule Ordering
Section titled “Rule Ordering”- Accept established/related first (most frequent)
- Drop invalid connections
- Accept specific allowed traffic
- Blacklist checks
- Default drop
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Solution |
|---|---|---|
| Self-lockout from SSH | Brute force rules triggered | Add trusted IPs to whitelist first |
| DNS entries not updating | TTL not expired | Disable/enable entry to force refresh |
| Dynamic entries gone after reboot | Timeout entries are RAM-only | Use static entries or recreate on boot |
| Rule not matching list | Typo in list name | Verify exact list name match |
| Import stops partway | Duplicate entries in file | Pre-filter duplicates before import |
| Script removes all entries | Unfiltered find command | Store entry ID before removal |
| Large list slowing router | 27k+ entries | Use RAW, aggregate ranges, optimize order |
| Timeout won’t decrease | By design | Use separate lists if needed |
Common Mistakes
- Don’t omit timeout for large/frequently-updated lists - causes NAND wear with constant writes
- Don’t assume timeout decreases work - they’re ignored by design to prevent rule conflicts
- Don’t initialize lists with network addresses (192.168.1.0/24) - may cause mangle rule issues
- Don’t forget that “bots can come from any country” - geographic filtering is supplementary only
Scripting Examples
Section titled “Scripting Examples”Check Before Adding
Section titled “Check Before Adding”:local ip "1.2.3.4":local listname "blacklist":if ([:len [/ip firewall address-list find address=$ip list=$listname]] = 0) do={ /ip firewall address-list add list=$listname address=$ip timeout=1d}Safe Removal
Section titled “Safe Removal”:local ip "1.2.3.4":local listname "blacklist":local entryID [/ip firewall address-list find address=$ip list=$listname]:if ([:len $entryID] > 0) do={ /ip firewall address-list remove $entryID}Flush Dynamic Entries
Section titled “Flush Dynamic Entries”/ip firewall address-list remove [find where list=blacklist dynamic=yes]Related Topics
Section titled “Related Topics”Firewall Integration
Section titled “Firewall Integration”- Firewall Filter Basics - use address lists in filter rules
- NAT Masquerade - use address lists in NAT rules
- Firewall Mangle - mark traffic by address list
Common Use Cases
Section titled “Common Use Cases”- DHCP Server - dynamic lists from DHCP leases
- Hotspot - hotspot user lists
- L2TP VPN - VPN client address lists
Related Topics
Section titled “Related Topics”- Interface Lists - group interfaces similar to address lists
- Scheduler - scheduled list maintenance