Homelab · Security · 2026-09-03 · 4 min read
When the office router became a weapon
I run a 24/7 monitoring stack for an office network in Córdoba: a MikroTik router and UniFi access points, watched from a single Raspberry Pi running Grafana, VictoriaMetrics and VictoriaLogs, fed by mktxp, unpoller, blackbox and IPFIX exporters — ten containers, all docker-compose, with 17 provisioned alert rules firing into Slack.
One of those rules is embarrassingly simple: active connections above threshold. It's the one that caught this.
The alert
The router's connection count, which idles around 700, spiked to ~2,600 and stayed there. No user complaint preceded the alert — attacks like this rarely announce themselves as anything worse than "the internet feels a bit slow".
The flow data from the WAN interface showed the pattern immediately: a flood of small UDP/53 packets arriving from the internet, and much larger UDP/53 packets leaving. The router was answering DNS queries from the WAN.
The diagnosis: an open resolver
MikroTik's DNS client doubles as a DNS server. The setting that makes the router resolve names for your LAN —
/ip dns
set allow-remote-requests=yes servers=8.8.8.8,...
— makes it resolve names for anyone who can reach UDP/53, unless the firewall says otherwise. And the firewall said nothing.
That's an open resolver, and open resolvers get found fast. Attackers use them as reflectors in a DNS amplification attack: they send a small query with the victim's spoofed source address, and the resolver mails the victim a much larger answer. In our capture: a 132-byte query producing a 4,980-byte answer — roughly 37× amplification. The office router wasn't the target; it was being used as ammunition against someone else, burning our uplink and the router's CPU in the process. (Cloudflare has a good primer on the mechanics: DNS amplification attacks.)
The fix, and where it belongs
The obvious move is a filter rule: drop UDP/53 from WAN in the input chain. It works, but there's a subtlety that matters under attack volume: filter runs after connection tracking. Every spoofed packet still creates a conntrack entry before being dropped — so you keep paying CPU and connection-table space for traffic you've already decided to throw away. The connection count stays inflated and, on a small router, conntrack exhaustion becomes its own denial of service.
RouterOS has a table designed exactly for this: raw, whose prerouting chain runs before conntrack (RouterOS firewall docs). Packets dropped there never touch the connection table:
/ip firewall raw
add action=drop chain=prerouting protocol=udp dst-port=53 \
in-interface-list=WAN \
comment="Anti DNS amplification - drop pre-conntrack"
Note what this doesn't do: it doesn't disable the resolver. The LAN still resolves through the router normally — allow-remote-requests stays on, but the WAN can no longer reach it. The service isn't the problem; its exposure was.
While I was in there: defense in depth
An incident is a terrible thing to waste, so the rest of the firewall got hardened in the same session:
- Staged brute-force ban on the management ports (SSH 22, Winbox 8291, API 8728), fail2ban-style using nothing but address lists: first connection attempt from WAN puts you in
wan_stage1(1 min), a second inwan_stage2(1 min), and the third gets you banned for a week — logged with prefixWAN-BAN:
/ip firewall filter
add action=add-src-to-address-list address-list=wan_stage1 \
address-list-timeout=1m chain=input connection-state=new \
dst-port=22,8291,8728 protocol=tcp in-interface-list=WAN
add action=add-src-to-address-list address-list=wan_stage2 \
address-list-timeout=1m chain=input connection-state=new \
dst-port=22,8291,8728 protocol=tcp in-interface-list=WAN \
src-address-list=wan_stage1
add action=add-src-to-address-list address-list=wan_blacklist \
address-list-timeout=1w chain=input connection-state=new \
dst-port=22,8291,8728 protocol=tcp in-interface-list=WAN \
src-address-list=wan_stage2 log=yes log-prefix=WAN-BAN
add action=drop chain=input src-address-list=wan_blacklist
- Default-drop from the internet: after the explicit accepts (established/related, ICMP, the VPN port), a final
drop everything else from WANrule ininput. - Management off the internet entirely: Winbox, SSH and the API are now reachable only through WireGuard.
- Guest Wi-Fi isolated from the LAN with an explicit forward-chain drop.
Results
- Active connections: 2,600 → ~700 (back to baseline) the moment the raw rule went in.
- Attack traffic: → 0. The reflector was gone, so the attackers moved on — they always have more open resolvers to choose from.
- Management surface on the WAN: zero ports, VPN only.
- And the same Grafana dashboards that raised the alert now show the before/after, which is a satisfying kind of closure.
Takeaways
- 1. An open resolver is a liability at any scale. This wasn't a datacenter — it was one office router with a default-ish DNS config.
- 2. Where you drop matters as much as what you drop. Under flood conditions,
raw/pre-conntrack versusfilteris the difference between shrugging off the attack and melting your connection table. - 3. You can't fix what you can't see. The attack produced no outage, no error, no user report — only a metric that left its baseline. Without the monitoring stack it would have run for months.
- 4. Address lists with timeouts are a whole intrusion-prevention system in four firewall rules.