This article explains what it means when services on your server are reported as open reflectors, and why it matters. It then shows, protocol by protocol, how to reconfigure each service so that it can no longer be abused.
How reflection attacks work
UDP has no handshake, so the sender of a UDP packet can write any source address into it. An attacker sends small requests to many open services and puts the victim's address in as the sender. Every service then answers the victim, not the attacker. When the answer is bigger than the request, the attacker's traffic is multiplied on the way. The ratio of answer size to request size is called the amplification factor.
For you, this has concrete consequences:
- Your server sends attack traffic. It comes from your IP address and uses your bandwidth.
- Your IP address can land on blocklists. Operators of attacked networks report the sources they see, and that is your server.
- Your own services can slow down. During an attack, the reflected traffic competes with your legitimate traffic on the same uplink.
For us as your network operator, an open reflector causes problems beyond your server:
- It uses capacity everyone shares. Reflected attack traffic passes through our routers and our links to other networks. A large attack takes up capacity that other customers' traffic needs.
- It damages the reputation of whole address ranges. Blocklists and the filters of large networks often list an entire range, not just one address. Other customers in that range then find their mail rejected or their services blocked, even though their servers are configured correctly.
- It brings complaints from attacked networks. Their operators send abuse complaints to us as the holder of the address. Repeated complaints strain our relationships with those networks and with our upstream and peering partners.
- We are expected to stop abuse from our network. That is why we act proactively against open reflectors, rather than waiting for incoming complaints.
Reading the report
The report contains a table like this one:
Host Protocol Request Response Amplification-Factor
10.0.0.1 dns 25 486 19.4x
10.0.0.1 snmp 37 512 13.8x
Open reflectors:
10.0.0.1 dns, snmp| column | meaning |
|---|---|
| Host | the address of your server that answered |
| Protocol | the protocol; each has its own chapter below |
| Request | size of the request, in bytes |
| Response | size of your server's answer, in bytes |
| Amplification-Factor | Response divided by Request |
Please fix every protocol in the table, not only the one with the highest factor.
Every protocol chapter explains what the service is and why it is reported, then lists what you must, should and can do:
- Must is what stops the service from being abusable. Without it, the problem remains and the reports continue.
- Should is strongly recommended hardening that goes beyond the report.
- Can is an optional improvement.
How to do it links to the vendor's documentation for the common software, because package names, file locations and service names differ between installations. Questions that apply to every protocol, such as setting up a firewall, are answered in the FAQ at the end.
Overview
| protocol | port | usually found in | typical fix |
|---|---|---|---|
| dns | 53 | resolvers such as BIND, Unbound, dnsmasq, Pi-hole | allow recursion only for your own clients |
| snmp | 161 | snmpd, network devices, management controllers | restrict to the monitoring host, use SNMPv3 |
| cldap | 389 | Active Directory domain controllers | never expose a domain controller |
| portmap | 111 | rpcbind, for NFSv3 | disable, or use NFSv4 only |
| memcached | 11211 | memcached | disable UDP, bind to localhost |
| chargen | 19 | xinetd, inetd, Windows Simple TCP/IP Services | disable |
| ntp | 123 | ntpd, NTPsec | refuse queries with noquery |
| rdp | 3389 | Windows Remote Desktop | restrict access, use TCP only |
| ws-discovery | 3702 | Windows, wsdd, IP cameras | disable discovery on public interfaces |
dns (UDP 53)
A DNS resolver looks up names on behalf of its clients. The problem is an open resolver: one that performs recursive lookups for anyone on the internet. An authoritative server that only answers for your own domains is not the subject of this report, unless it also resolves other names. Typical resolvers are BIND, Unbound, dnsmasq, PowerDNS Recursor, Windows DNS Server, and ad blockers like Pi-hole and AdGuard Home installed on a public server.
Why it is reported. A small query can draw a very large answer, especially when it asks for DNSSEC records. Open resolvers are among the most abused reflectors.
Must
- Allow recursion only for your own clients. On a purely authoritative server, disable recursion entirely.
- On authoritative servers, enable Response Rate Limiting (RRL).
Should
- Only access your resolver through a VPN, or offer DNS over TLS or HTTPS, which run over TCP.
How to do it
- BIND: limit
allow-recursionandallow-query-cacheto your own networks. On a purely authoritative server, setrecursion no;. RRL israte-limit. - Unbound: refuses everyone except localhost by default. Look for an
access-controlline that allows other networks, and check which addressesinterfacelistens on. - dnsmasq:
local-serviceanswers only hosts on directly connected networks, but it has no effect as soon asinterface,except-interface,listen-addressorauth-serveris set. In that case, list only internal interfaces and addbind-interfaces. See the dnsmasq manual. - Windows DNS Server: disable recursion if the server only answers for its own zones. If it has to resolve for your clients, allow recursion only for them with recursion scopes, or restrict who can reach UDP 53.
- PowerDNS Recursor:
incoming.allow_from, calledallow-fromin the older configuration format. The default allows only private ranges, and an empty value allows everyone. - Pi-hole: choose the listening mode Allow only local requests. Permit all origins turns it into an open resolver.
- AdGuard Home: list your own clients in
allowed_clients. - systemd-resolved: its stub resolver listens on
127.0.0.53only. IfDNSStubListenerExtra=adds a public address, remove it. - NSD and Knot DNS: RRL is
rrl-ratelimitin NSD and themod-rrlmodule in Knot DNS.
Check
From a machine outside your network, ask your server for a name it is not authoritative for:
dig @<10.0.0.1> example.com AThe answer must be status: REFUSED or no answer at all. If you get an
ANSWER SECTION with an address, the server still resolves for everyone.
snmp (UDP 161)
SNMP (Simple Network Management Protocol) is used to monitor and
manage systems. You find it in snmpd (net-snmp) on servers, and on hardware:
switches, routers, printers, UPS network cards, and management controllers such
as IPMI, iDRAC or iLO.
Why it is reported. SNMPv1 and v2c authenticate with a plain community
string, and the default public is guessed by everyone. A single bulk request
returns a large part of the device's data. Besides amplifying, the answer also
reveals detailed information about your system.
Must
- Do not expose SNMP to the internet. Only your monitoring host may reach it, through a private address or a firewall rule.
- Remove the default community
public.
Should
- Use SNMPv3 with authentication and encryption, and disable v1 and v2c.
- Keep management controllers on a private network, never on a public address.
How to do it
- net-snmp: unless
agentaddresssays otherwise,snmpdlistens on all IPv4 addresses. Setagentaddressto localhost or to a private address. Give everyrocommunityline the monitoring host's address as its source, and delete the ones forpublic. For SNMPv3, grant users read-only access withrouser … priv. All of these are described in the snmpd.conf manual. The helpernet-snmp-create-v3-usercreates a read-write user with MD5 and DES unless told otherwise. Pass-ro, and choose SHA-256 and AES explicitly. - Network devices, printers and management controllers: switch SNMP off in the web interface, or restrict it to your monitoring server.
Check
From a host that is not your monitoring server:
snmpwalk -v2c -c public <10.0.0.1> systemIt must end with Timeout: No Response.
cldap (UDP 389)
CLDAP (Connectionless LDAP) lets Windows clients locate and query a domain controller. Every Active Directory domain controller answers it, Samba AD domain controllers included.
Why it is reported. The domain controller answers an unauthenticated query with a large description of itself. CLDAP cannot be switched off on a domain controller without breaking the domain.
Must
-
Never expose a domain controller to the internet. Block UDP 389, and all other Active Directory ports, from everywhere except your own networks.
-
Place domain controllers on a private network, for example a Hetzner Cloud Network or a vSwitch, and connect remote sites and users through a VPN.
How to do it
- Windows: restrict the scope of the built-in inbound LDAP rules for UDP 389 to your own networks. This only helps when the Windows Firewall is enabled and no other rule allows the port. Filtering in front of the server, with the Hetzner Cloud Firewall or the Robot Firewall, protects even when the server's own rules are wrong. Microsoft lists the ports in firewall configuration for Active Directory domains and trusts.
- Samba AD DC: see the ports used by a Samba AD DC.
portmap (UDP 111)
The portmapper (rpcbind) tells clients on which port an RPC
service listens. NFS version 3 and NIS need it. Many distributions install it by
default, for example as a dependency of the NFS client tools, even when nothing
uses it.
Why it is reported. A single request returns the list of every registered RPC service. Besides amplifying, it reveals which services run on the server.
Must
- If you use neither NFSv3 nor NIS, stop and disable rpcbind. An NFSv4 client does not need it.
- If you need NFSv3, allow UDP and TCP 111, and the NFS ports, only from your NFS clients.
Should
- On an NFS server, switch to NFSv4 only, which works without rpcbind.
How to do it
- rpcbind: on systems with systemd, disable its socket unit as well, or socket activation starts rpcbind again on the next request. See the rpcbind manual.
- NFSv4 only: Red Hat describes the steps in
Configuring an NFSv4-only server.
The
vers3setting they use is documented in the rpc.nfsd manual.
memcached (UDP 11211)
memcached is an in-memory cache for web applications. Only the application servers need to reach it.
Why it is reported. Over UDP, a tiny request draws a very large answer. memcached was behind some of the largest reflection attacks ever recorded. An open memcached also lets anyone read and change your cached data.
Must
- Disable UDP. Versions since 1.5.6 have it off by default. Update older versions.
- Bind memcached to localhost, or to the private address your application servers use.
- In Docker, never publish the UDP port, and publish TCP only to localhost, as shown in the FAQ.
Should
- Do not expose TCP 11211 to the internet either. memcached has no authentication by default, so the whole cache is readable and writable.
How to do it
- memcached:
-U 0disables UDP, and-lsets the listen address. Where you set them depends on the installation: the package's configuration file, the service definition, or the container's command line. See the networking options and the UDP DDoS advisory.
Check
No UDP listener may be left:
sudo ss -ulnp 'sport = :11211'chargen (UDP 19)
The character generator is a test service from the 1980s. It answers anything it receives with a stream of characters. It has no legitimate use today.
Why it is reported. A single byte draws a large reply.
Must
- Disable it.
Should
- Disable the other "simple services" of the same era as well: echo (7), discard (9), daytime (13) and qotd (17).
How to do it
-
xinetd: set
disable = yesin both chargen entries, the datagram and the stream one, and reload xinetd. Or remove xinetd if nothing else uses it. The attribute is described in the xinetd.conf manual. -
inetd: comment out the
chargenlines in its configuration and restart it. -
Windows: chargen is part of Simple TCP/IP Services. Stop and disable the service:
Stop-Service SimpTcp Set-Service SimpTcp -StartupType DisabledOr remove the feature completely, on Windows Server or on Windows client.
-
Printers and older network devices: look for a Simple TCP/IP services option in their settings.
ntp (UDP 123)
NTP (Network Time Protocol) synchronises clocks. Serving time is
not the problem. The problem is the management interface of the classic ntpd
and of NTPsec, which answers status queries from anyone.
Why it is reported. Status queries return far more data than the request.
The monlist command of old ntpd versions was among the strongest amplifiers
ever abused. The readvar query of current versions still returns a sizeable
system status.
Must
- Refuse management queries from the network, for IPv4 and IPv6. Time service keeps working; only the management queries are refused. RFC 8633, the NTP best-practice document, recommends exactly this for public-facing servers.
- Update ntpd versions older than 4.2.7p26, which still answer
monlist(ntp.org security notice).
Can
- If the server only needs to keep its own clock right, replace ntpd with chrony or systemd-timesyncd. Neither serves time nor answers queries from the network by default.
How to do it
- ntpd: add
noqueryto the defaultrestrictlines. See the access control options, anddisable monitorin the miscellaneous options. - NTPsec: uses the same
restrictcommand with a slightly different set of flags. See its access control. - chrony: only serves clients listed in an
allowdirective.
Check
From a machine outside your network:
ntpq -c rv <10.0.0.1>It must time out.
rdp (UDP 3389)
RDP (Remote Desktop Protocol) is Microsoft's remote desktop. Since Windows 8 and Windows Server 2012, RDP uses UDP 3389 in addition to TCP 3389 to speed up sessions.
Why it is reported. The UDP transport answers a short connection request with a much larger reply, before any login takes place.
Must
- Do not make RDP reachable from the whole internet. It is also a constant target of password guessing and exploits. Allow only your own addresses, connect through a VPN, or use a Remote Desktop Gateway.
- If RDP has to stay reachable for everyone, switch off the UDP transport. Sessions then run over TCP only, which is slightly slower on lossy connections and otherwise unchanged.
How to do it
- Restricting access: Microsoft describes the Remote Desktop Gateway, and gives the same advice for access from outside.
- UDP transport: the setting is the Group Policy Select RDP transport protocols: Computer Configuration, Administrative Templates, Windows Components, Remote Desktop Services, Remote Desktop Session Host, Connections. Set it to Enabled and choose Use only TCP. On a domain member, set it in the domain's Group Policy, since a local setting can be overridden there. Microsoft names the registry value behind it in its Azure Virtual Desktop documentation. Also disable the inbound Windows Firewall rule for Remote Desktop over UDP. The setting takes effect after a restart of the Remote Desktop Services, which disconnects open sessions, or after a reboot.
ws-discovery (UDP 3702)
WS-Discovery lets devices find each other on a local network.
Windows uses it for network discovery, Linux and NAS systems run wsdd or
wsdd2 so Windows can see their shares, and ONVIF IP cameras, video recorders
and printers answer it too.
Why it is reported. A discovery request draws a description of the device. Some devices, cameras and Windows hosts in particular, answer with very large replies, which made WS-Discovery a vector for some very large attacks.
Must
- Never let discovery answer on a public interface.
Should
- Never connect cameras and video recorders directly to a public address. Reach them through a VPN, and keep their firmware up to date.
How to do it
-
Windows: make sure the internet-facing adapter uses the Public network profile, and turn off network discovery for it. On servers, stop and disable Function Discovery Resource Publication, the service that announces the host:
Stop-Service FDResPub Set-Service FDResPub -StartupType Disabled -
wsdd and wsdd2: on an internet-facing server, stop and disable the service. If you need discovery on a private network, restrict
wsddto that interface with--interface. -
Cameras and video recorders: switch off WS-Discovery or ONVIF discovery in the device settings.
After the fix
Once none of the listed services answer any more, no further reports follow for that address. If a service becomes reachable again later, for example after a reinstall or when a new container publishes it, a new report follows.
To check a fix yourself, use the Check step of the chapter, or the service's normal client from a machine outside your network: it must get no answer. Repeat the check over IPv6 if your server has an IPv6 address.
FAQ
What applies to every protocol?
- Decide whether the service needs to be reachable from the internet at all. Most services in this guide are meant for a local network or for administration and never need to be public. If you do not use a service, stop and disable it. That is the cleanest fix.
- Find the program that owns the port. See Which program owns the port?
- Bind local-only services to a local address. A service that only your
server itself or your private network needs should listen on
127.0.0.1or on the private address, not on all addresses. - Filter with a firewall. Allow only the ports you really serve publicly, and allow management ports only from your own addresses. See How do I set up a firewall?
- Do not forget IPv6 and containers. A fix that covers IPv4 only, or a firewall that containers bypass, leaves the service open. See Why can a container bypass my firewall?
Which program owns the port?
On Linux, list all listening sockets with their process:
sudo ss -lnp
sudo ss -lnp 'sport = :161'A local address of 0.0.0.0, * or [::] means the service listens on all
addresses, including the public ones. 127.0.0.1 or [::1] means local only.
A port published by a container shows up as docker-proxy or not at all;
docker ps lists which container publishes which port.
On Windows, in an elevated PowerShell:
Get-NetUDPEndpoint -LocalPort 161 | ForEach-Object { Get-Process -Id $_.OwningProcess }How do I set up a firewall?
A default-deny policy is the most robust protection: everything you forgot about stays closed. Allow the ports you serve, SSH or RDP included, before you switch the policy to deny, or you lock yourself out.
- ufw (Ubuntu, Debian): Ubuntu Server firewall guide and the ufw manual
- firewalld (RHEL, Rocky, Alma, Fedora, openSUSE): zones
- Windows: create an inbound rule
On Windows, also check that the firewall is enabled for every profile, and that the internet-facing adapter uses the Public profile:
Get-NetFirewallProfile | Select-Object Name, Enabled
Get-NetConnectionProfileBesides the firewall on the server itself, you can filter traffic before it reaches the server:
- Cloud servers: the Hetzner Cloud Firewall is stateful, so replies to your server's own connections pass automatically.
- Dedicated servers: the Robot Firewall is stateless. Replies to your server's own outgoing connections need rules of their own, which the linked section explains.
Why can a container bypass my firewall?
Docker writes its own packet-filter rules for published ports, and traffic to
them never passes through the rules of ufw. firewalld lets published ports
through as well unless its StrictForwardPorts option is enabled. A container
published with -p 11211:11211/udp is therefore reachable from the internet
even when your host firewall says otherwise. Publish only to the loopback
address, or not at all when only other containers need the service:
docker run -d -p 127.0.0.1:11211:11211 memcachedIn Compose:
services:
cache:
image: memcached
ports:
- "127.0.0.1:11211:11211"Containers running with network_mode: host listen directly on all host
addresses. This is common for media servers and discovery services, and it
exposes them just like a service installed on the host.
Official documentation:
- Docker: Docker and ufw and publishing ports
- firewalld: strictly filtering Docker containers