---
title: "How to Disable Recursion in BIND to Stop an Open DNS Resolver"
description: "Turn off recursion and cache access on a BIND server that hosts your domains, so it stops acting as an open DNS resolver while still answering for its zones."
url: "https://docs.noiz.ie/server-administration/how-to-disable-recursion-in-bind-to-stop-an-open-dns-resolver/"
section: "Server Administration"
categories:
  - "Server Administration"
tags:
  - "dns"
  - "bind"
  - "security"
  - "vps"
  - "nameserver"
last_reviewed: "13 October 2026, against the current ISC BIND 9 release"
---

# How to Disable Recursion in BIND to Stop an Open DNS Resolver

An authoritative nameserver answers for the domains it hosts. An **open resolver** also looks up any other name on the internet for anyone who asks, which attackers abuse to amplify denial-of-service traffic. The fix on a BIND server that only needs to answer for its own zones is two statements in the `options` block, `recursion no;` and `allow-query-cache { none; };`, applied with `rndc reconfig` and then tested from outside your network.

This guide is for customers running their own BIND server on a Noiz VPS or dedicated server running Ubuntu or Debian. If your domains use the Noiz nameservers, Noiz runs that DNS service for you and you do not need to change anything. An **open relay** is a different problem, affecting mail servers rather than DNS.

**Last reviewed:** 13 October 2026, against the current ISC BIND 9 release. This guide is written for Noiz hosting and is kept current against BIND. It complements, and does not replace, the official BIND documentation linked below.

### Official Documentation Reference

- [BIND: recursion](https://bind9.readthedocs.io/en/stable/reference.html#namedconf-statement-recursion): what `recursion no` does and does not stop.
- [BIND: allow-query-cache](https://bind9.readthedocs.io/en/stable/reference.html#namedconf-statement-allow-query-cache): who may read the server's cache, and its defaults.
- [BIND: allow-recursion](https://bind9.readthedocs.io/en/stable/reference.html#namedconf-statement-allow-recursion): for servers that must keep resolving for trusted clients.
- [BIND tools: named-checkconf](https://bind9.readthedocs.io/en/stable/manpages.html#named-checkconf-named-configuration-file-syntax-checking-tool), [rndc](https://bind9.readthedocs.io/en/stable/manpages.html#rndc-name-server-control-utility) and [dig](https://bind9.readthedocs.io/en/stable/manpages.html#dig-dns-lookup-utility).

Use the manual that matches the BIND version your distribution installs; the statements in this guide behave the same way in current releases.

## Prerequisites

- Root or sudo access to the BIND server over SSH, with a second session kept open.
- A working `rndc` setup (BIND's control tool). Check it with `sudo rndc status`.
- A computer on a different network, such as your office connection, with `dig` installed, for testing from outside.
- If you run two nameservers, confirm the other one answers correctly for every zone before you change this one, and change one server at a time.
- If a control panel or configuration-management tool writes your BIND files, make the change there instead, or the next regeneration will undo it.

## How to Check Whether Your Server Is an Open Resolver

From a computer outside your server's network, ask the server to look up a name it does not host. Replace `192.0.2.53` with your server's public IP address:

```bash
dig @192.0.2.53 example.net A +recurse
```

Look at the `status:` and `flags:` lines in the reply:

- `status: REFUSED` with no `ra` flag: the server is not resolving for you. That is the result you want.
- `status: NOERROR` with an answer and the `ra` (recursion available) flag: the server is an open resolver. Continue with this guide.

A timeout or "connection refused" is not a pass. It usually means a firewall blocked the test, so the server's behaviour is still unknown.

## 1. Decide Whether the Server Should Resolve at All

Check what the server itself uses for DNS lookups:

```bash
cat /etc/resolv.conf
resolvectl status
```

If `/etc/resolv.conf` points at `127.0.0.53`, systemd-resolved is in use and `resolvectl status` shows the real upstream servers. If either points at `127.0.0.1` or the server's own address, then the server, its mail software or its applications rely on BIND to look up outside names. Turning recursion off would break them.

| Server role | What to do |
|---|---|
| Only answers for hosted domains | Follow this guide. |
| Also resolves for its own applications | Point the server at another recursive resolver first (for example your provider's resolvers, set in netplan or systemd-resolved), then follow this guide. |
| Resolver for an internal network | Do not follow this guide. Keep recursion on and limit it with `allow-recursion` to your own networks. |

Note that BIND's built-in `localnets` list means every network the server has an interface on, which can include a public subnet. The `localhost` list means all of the server's own addresses, not only `127.0.0.1`.

## 2. Back Up the Configuration

On Ubuntu and Debian, global options live in `/etc/bind/named.conf.options`. Check the current configuration is valid, then copy the file:

```bash
sudo named-checkconf
sudo rndc status
sudo cp -a /etc/bind/named.conf.options /root/named.conf.options.bak
```

If `named-checkconf` reports an error, fix it before going further. This backup covers the configuration only. Zone files, DNSSEC keys and dynamic-zone data should already be covered by your normal backups; do not restore them as part of undoing this change.

## 3. Turn Off Recursion and Cache Access

Edit `/etc/bind/named.conf.options` and add or correct these two lines inside the **existing** `options { ... };` block:

```text
recursion no;
allow-query-cache { none; };
```

Do not create a second `options` block or duplicate a statement that is already there. If your configuration uses `view` blocks (a BIND feature that serves different answers to different clients), check each view for its own `recursion` or `allow-query-cache` settings, because a view can override the global options.

Why both lines: `recursion no` stops the server doing new lookups for clients, but on its own it does not stop it answering from data already in its cache. With `recursion no`, BIND already defaults `allow-query-cache` to `none`. Setting it explicitly records your intent and overrides any wider `allow-query-cache` set elsewhere, for example inside a view.

Leave everything else alone. In particular, keep `allow-query { any; };` (or no `allow-query` at all) so the world can still look up your hosted domains, keep the server listening on UDP and TCP port 53, and keep zone transfer settings (`allow-transfer`) and keys as they are. If you use a firewall, port 53 must stay open; see [How to Set Up a Firewall with UFW on Ubuntu and Debian](/linux/how-to-set-up-a-firewall-with-ufw-on-ubuntu-and-debian/).

## 4. Check and Apply the Change

```bash
sudo named-checkconf
sudo rndc reconfig
sudo rndc status
```

Only run `rndc reconfig` once `named-checkconf` prints nothing. `reconfig` rereads the configuration without restarting BIND. It does not reload zone files that have changed, so keep any zone edits separate.

After the change, `rndc status` may report fewer zones. That is BIND dropping its built-in empty zones for private address ranges, which it only creates when recursion is on. Your hosted domains are unaffected.

## 5. Test from Outside Your Network

From the outside computer, run both tests over UDP and TCP. Replace `192.0.2.53` with your server's address and `yourdomain.com` with one of the domains it hosts:

```bash
dig @192.0.2.53 yourdomain.com SOA +norecurse
dig @192.0.2.53 yourdomain.com SOA +norecurse +tcp
dig @192.0.2.53 example.net A +recurse
dig @192.0.2.53 example.net A +recurse +tcp
dig @192.0.2.53 example.net A +norecurse
```

| Test | Result you want |
|---|---|
| Your hosted domain | `status: NOERROR`, the `aa` (authoritative answer) flag and your SOA record. |
| `example.net`, with or without recursion requested | `status: REFUSED`, no answer and no `ra` flag. |

The `+norecurse` lookup of `example.net` checks the cache: it asks only for data the server already holds. If the server serves IPv6, repeat the tests against its IPv6 address from an IPv6-capable computer. Read the full reply rather than `+short` output; a `SERVFAIL` or a timeout is not a pass.

Finally, check from the server itself that its own lookups and applications still work, for example `getent hosts example.net`.

## Troubleshooting

- **Symptom: a hosted domain stops answering.** Check `allow-query` and any `view` settings for that zone, and check the BIND log (`sudo journalctl -u named`). Restore the backup if needed.
- **Symptom: mail or applications on the server can no longer look up names.** They were using BIND as their resolver. Point them at another resolver; do not turn public recursion back on.
- **Symptom: `rndc` fails to connect.** Use the existing control configuration and key, and investigate the mismatch. Do not replace the key or open the control port to the internet.

To undo the change, copy the backup back and apply it:

```bash
sudo cp -a /root/named.conf.options.bak /etc/bind/named.conf.options
sudo named-checkconf
sudo rndc reconfig
```

Undoing the change reopens the resolver, so plan a corrected fix promptly. Keep operating-system upgrades separate from this change; see [How to Upgrade Ubuntu Server to a New Release over SSH Safely](/linux/how-to-upgrade-ubuntu-server-to-a-new-release-over-ssh-safely/).

If Noiz manages your server and DNS, [contact Noiz support](/getting-started/how-to-contact-noiz-for-support/) with the nameserver's address, the time of your test and the full `dig` output. Never include keys or passwords.

---
Source: https://docs.noiz.ie/server-administration/how-to-disable-recursion-in-bind-to-stop-an-open-dns-resolver/
