What runs on port 53
Port 53 is DNS, the Domain Name System (RFC 1035). It is one of the few common services that uses both UDP and TCP on the same port:
- UDP 53 carries most queries: one small packet out, one back.
- TCP 53 is used when an answer is too large for UDP (the response comes back truncated and the client retries over TCP), for zone transfers between name servers (AXFR/IXFR), and by some clients by choice. RFC 7766 makes TCP support mandatory for DNS servers.
Classic DNS on port 53 is not encrypted. Encrypted variants use other ports: DNS over TLS on 853 and DNS over HTTPS on 443.
Two kinds of DNS server
| Role | Answers | Port 53 open to |
|---|---|---|
| Authoritative (BIND, NSD, PowerDNS, Knot) | Only for your own zones | Everyone, UDP and TCP |
| Recursive resolver (Unbound, dnsmasq, Pi-hole) | Any name, by asking other servers | Only your own networks |
An authoritative server listed in your NS records must accept queries from the whole internet on both protocols. Blocking TCP 53 there breaks large responses, such as DNSSEC-signed answers or long TXT records.
Don't run an open resolver
A recursive resolver that answers anyone is an open resolver. Attackers use them for DNS amplification: they send small queries with a forged source address, and your server floods the victim with large answers. Restrict recursion to your networks. In Unbound:
server:
interface: 0.0.0.0
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: 192.168.1.0/24 allow
And at the firewall:
sudo ufw allow from 192.168.1.0/24 to any port 53
Without proto, that ufw rule covers both TCP and UDP. For an authoritative server, use sudo ufw allow 53 to open both to everyone.
See what is listening
sudo ss -tulnp 'sport = :53'
sudo lsof -i :53
Note the -u for UDP. A port scanner that only makes TCP connections, like ours, sees TCP 53 but not UDP; to test UDP directly, send a real query: dig @203.0.113.5 example.com.
"Port 53 already in use"
On Ubuntu and other systemd distributions, systemd-resolved runs a stub resolver on 127.0.0.53:53. Pi-hole, dnsmasq, BIND or a Docker container that wants port 53 then fails with "address already in use". Turn off the stub listener:
# /etc/systemd/resolved.conf
[Resolve]
DNSStubListener=no
sudo systemctl restart systemd-resolved
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
The symlink points the system at the real upstream servers instead of the stub that is no longer running. Alternatively, bind your server only to a specific interface address rather than 0.0.0.0.
Security notes
- Disable zone transfers to anyone but your secondaries (
allow-transferin BIND). - Rate-limit responses on authoritative servers (BIND and NSD support response rate limiting).
- Keep recursion off on authoritative servers.
Related
- NS record: which servers are authoritative for a domain.
- DNS TTL: how long resolvers cache answers.
- Port 443 (HTTPS): where DNS over HTTPS runs.
Look up how your domain resolves with the DNS Lookup, and check TCP 53 on your name server with the Port Scanner.