UDP Amplification Attacks: Signatures and Edge Filtering
UDP amplification attacks work by sending small spoofed requests to open servers (DNS, NTP, memcached, CLDAP, SSDP) that reply with much larger responses to the victim's IP. You can stop most of them at the network edge by matching the reflector's source port and packet size in an ACL, a FlowSpec rule, or a flow-based detector that triggers one automatically.
This guide covers how the attack works, what each protocol looks like in flow data, and how to filter it on Juniper, Cisco, MikroTik and Linux without breaking legitimate traffic.
How a UDP amplification attack works
- The attacker sends a small UDP request to a reflector, with the source IP spoofed to be the victim's address.
- The reflector answers the request. The answer is larger than the request, often much larger.
- The victim receives responses it never asked for, from thousands of reflectors, all with the same source port (the service port).
The victim sees no single attacker, only the reflectors. Spoofing is possible because some networks still don't enforce source address validation (BCP 38). That is also why you should check your own outbound filtering: if your customers can spoof, you host the attack's origin.
Common reflectors and what they look like
Amplification factors below are commonly cited ranges (for example from CISA/US-CERT advisories). They vary with the server's configuration and data.
| Protocol | Source port | Typical response | Notes |
|---|---|---|---|
| DNS | UDP/53 | Large ANY/DNSSEC answers, often fragmented | Legitimate traffic uses the same port |
| NTP | UDP/123 | monlist replies, many ~468-byte packets |
Normal NTP packets are small (~76 bytes at L3) |
| memcached | UDP/11211 | Large, heavily fragmented responses | Among the highest known factors |
| CLDAP | UDP/389 | Large directory responses, fragmented | Rarely needed from the internet |
| SSDP | UDP/1900 | UPnP discovery replies | Should never come from the internet to you |
Other reflectors seen in the wild include chargen (UDP/19), SNMP (161), portmap (111), WS-Discovery (3702) and Ubiquiti discovery (10001). The same method applies.
Signatures in flow data
You don't need packet captures to spot amplification. NetFlow, IPFIX or sFlow already contain what you need:
- Protocol UDP with a fixed source port and random destination ports. In normal client traffic it's the other way around.
- Huge pps and bps toward one destination IP from many unique source IPs.
- Large average packet size. Divide bytes by packets per flow. Amplified responses sit near the MTU or are fragmented.
- UDP port 0 entries. Non-initial IP fragments carry no UDP header, so flow exporters report them with ports 0/0. If "UDP port 0" suddenly tops your report, you are probably looking at fragmented memcached, DNS or CLDAP responses.
- Asymmetry. Your customer received a lot of inbound UDP from port 11211 but never sent a request to it.
A practical detection query: group inbound UDP by source port and destination IP, and alert when one pair crosses a pps or bps threshold. See our guide on NetFlow thresholds, baselines and sampling for tuning that without false positives.
Filtering at the edge
Two rules keep this safe.
- Services nobody needs from the internet (memcached, CLDAP, SSDP, chargen, SNMP to customers) can be dropped by source port outright.
- Services customers do use (DNS, NTP) need extra conditions: packet size, destination, or fragment status. Never blanket-drop UDP source port 53 or 123 unless your network has no resolvers or NTP clients.
Apply filters on the ingress of transit and peering interfaces, not on the customer side, so the junk never crosses your backbone.
Juniper (Junos)
firewall {
family inet {
filter AMP-INGRESS {
term block-nolegit {
from {
protocol udp;
source-port [ 11211 389 1900 19 ];
}
then { count amp-drop-fixed; discard; }
}
term ntp-large {
from {
protocol udp;
source-port 123;
packet-length 200-65535;
}
then { count amp-ntp; discard; }
}
term dns-large-not-resolver {
from {
destination-address { 192.0.2.53/32 { except; } 0.0.0.0/0; }
protocol udp;
source-port 53;
packet-length 700-65535;
}
then { count amp-dns; discard; }
}
term accept { then accept; }
}
}
}
Here 192.0.2.53 is an example recursive resolver that is excluded from the DNS rule. Attach the filter with set interfaces xe-0/0/0 unit 0 family inet filter input AMP-INGRESS.
Cisco IOS / IOS XE
ip access-list extended AMP-IN
deny udp any eq 11211 any
deny udp any eq 389 any
deny udp any eq 1900 any
deny udp any eq 19 any
permit ip any any
!
interface TenGigabitEthernet0/0/0
ip access-group AMP-IN in
Classic IOS ACLs can't match packet length on most platforms, so DNS and NTP are better handled with FlowSpec or a scrubbing device.
MikroTik RouterOS v7
/ip firewall raw
add chain=prerouting in-interface-list=WAN protocol=udp \
src-port=11211,389,1900,19 action=drop comment="UDP amp fixed ports"
add chain=prerouting in-interface-list=WAN protocol=udp \
src-port=123 packet-size=200-65535 action=drop comment="NTP monlist"
Using the raw table drops packets before connection tracking, which saves CPU during a flood.
Linux (nftables)
nft add table inet amp
nft add chain inet amp pre '{ type filter hook prerouting priority -300; policy accept; }'
nft add rule inet amp pre iifname "eth0" udp sport { 11211, 389, 1900, 19 } counter drop
nft add rule inet amp pre iifname "eth0" udp sport 123 meta length > 200 counter drop
nft add rule inet amp pre iifname "eth0" ip daddr != 192.0.2.53 udp sport 53 meta length > 700 counter drop
Fragments
Memcached, CLDAP and large DNS responses are fragmented. Only the first fragment has a UDP header, so source-port rules match only that one. Non-initial fragments pass through unless you also handle them:
- On Junos, a term with
is-fragmentplusprotocol udpmatches them. - On Cisco,
deny udp any any fragmentsmatches non-initial fragments.
Dropping all UDP fragments is a blunt tool. It breaks some legitimate traffic (certain DNSSEC and VPN flows). Apply it only to protected destinations, or for the duration of an attack.
Using BGP FlowSpec instead of static ACLs
Static ACLs are fine for ports you never need. For everything else, use a FlowSpec rule scoped to the victim and removed when the attack ends. Example logic for an attack on 203.0.113.10:
- Match: destination 203.0.113.10/32, protocol UDP, source port 11211
- Action: discard (or rate-limit for DNS)
This hits only the targeted address and avoids the collateral damage of RTBH, which drops all traffic to the victim. Read our FlowSpec rules, actions and safety guide before enabling it on production routers, and check your platform's FlowSpec limits.
When filters aren't enough
Filtering at your edge works only while the attack fits within your transit and peering links. If the inbound volume saturates the uplink, dropping packets on your router is too late, because the congestion is upstream. In that case you need to pull traffic into a scrubbing path, or ask your upstream to filter or blackhole. NixGuard Edge handles this for networks with their own ASN and at least one /24: your prefixes are announced from the scrubbing edge and clean traffic comes back over a GRE tunnel with a BGP session inside.
Common mistakes
- Blocking UDP/53 or UDP/123 by source port only. It breaks your own resolvers and time sync.
- Filtering on the wrong interface. Customer-side filters don't protect your transit links.
- Ignoring fragments. The attack continues through non-initial fragments.
- Using RTBH as the first response. It finishes the attacker's job for the victim IP. Prefer FlowSpec or scrubbing first.
- No outbound anti-spoofing. Apply uRPF or ACLs so your customers can't launch reflection attacks.
- Leaving your own services open. Close open resolvers, disable
monlist, and keep memcached off public interfaces. - Static thresholds copied from another network. Baseline your own traffic.
Where NixMon fits
NixMon analyzes NetFlow v5/v9, IPFIX and sFlow, with per-IP and per-prefix bps/pps thresholds. On a threshold breach it can announce a BGP FlowSpec rule or an RTBH route, push a rule to the on-prem NixGuard firewall, or route traffic through NixGuard Edge. You can test it with your own flow exports using the 15-day free trial, no credit card needed.
Frequently asked questions
What ports do UDP amplification attacks use?
The most common source ports are UDP/53 (DNS), 123 (NTP), 11211 (memcached), 389 (CLDAP) and 1900 (SSDP). Others include chargen (19), SNMP (161), portmap (111) and WS-Discovery (3702). The victim sees these as source ports, with random destination ports.
Can I just block UDP source port 53 and 123 at the edge?
Not safely. Your own resolvers and NTP clients receive replies from those source ports. Restrict the rule by packet size, destination (excluding your resolvers) or use a FlowSpec rule scoped to the attacked IP. Ports like 11211, 389, 1900 and 19 can usually be dropped outright.
Why do I see UDP port 0 in my flow records during an attack?
Non-initial IP fragments don't carry a UDP header, so flow exporters record ports as 0. Large UDP port 0 volume usually indicates fragmented amplification responses from memcached, CLDAP or DNS.
Is RTBH or FlowSpec better for amplification attacks?
FlowSpec is usually better because it drops only matching traffic (for example UDP source port 11211 to the victim) and keeps the destination reachable. RTBH drops everything to the victim IP, so use it as a last resort when the link is saturated and FlowSpec or scrubbing isn't available.