12 min read

Reverse DNS and PTR Hygiene: Keeping DNS in Sync with IPAM

Build reverse zones that match your address plan, prove forward confirmed reverse DNS, and run a PTR audit that keeps DNS and IPAM from drifting apart.

ByAndré Ribeiro· Founder, Obelinf
Reverse DNS and PTR Hygiene: Keeping DNS in Sync with IPAM
Reverse DNS and PTR Hygiene: Keeping DNS in Sync with IPAM · October 29, 2026
On this page

Forward DNS gets the attention because it is what users type. Reverse DNS is what the rest of the infrastructure reads. Mail servers check it before accepting a message, monitoring systems use it to label an address during an incident, and auditors use it to prove that a server at a given address is the server the inventory says it is. When the PTR is missing, the log shows an address. When the PTR is stale, the log shows the wrong name, which is worse.

The drift is predictable. A server is decommissioned, its A record is removed, and its PTR survives because nobody owned the reverse zone. A new server takes the address, the forward record is created, and the old PTR still points at the retired host. Six months later the address appears in a security review and the first hour is spent proving that the name in the log no longer exists. This guide is the procedure for building the reverse zone correctly, checking it in both directions, and keeping it aligned with the address plan.

How a Reverse Name Is Built

IPv4 reverse DNS lives under in-addr.arpa. The address octets are reversed and appended to that domain, so 203.0.113.25 becomes 25.113.0.203.in-addr.arpa. The zone that contains the record is the part of that name that has been delegated to you. A /24 delegation covers 113.0.203.in-addr.arpa, a /16 covers 0.203.in-addr.arpa, and a /8 covers 203.in-addr.arpa.

IPv6 uses ip6.arpa and reverses the address one hexadecimal nibble at a time. The address 2001:db8:1:2::25 becomes a long sequence of 32 nibbles followed by ip6.arpa, and the zone for a /64 is the last 16 nibbles of that reversed name. That is why IPv6 reverse zones look intimidating: a single /64 zone name is 16 labels long before you reach the PTR.

How an IPv4 address becomes a reverse DNS name and which zone contains the PTR record 203.0.113.25 address 25.113.0.203.in-addr.arpa reverse name, octets reversed 113.0.203.in-addr.arpa zone for a /24 The PTR record inside the zone 25 IN PTR host25.example.com. The owner name is relative to the zone. The full name is what a resolver asks for.

The zone boundary is the part that decides who can fix a broken record. If the zone has been delegated to your team, the PTR is yours to create and delete. If the address comes from an ISP and the ISP holds the reverse zone, the PTR is theirs, and the best you can do is request a change through their portal. Check the delegation before you spend an afternoon editing a zone file that will never be served.

Prefix Reverse zone Addresses covered
/24 113.0.203.in-addr.arpa 203.0.113.0 to 203.0.113.255
/16 0.203.in-addr.arpa 203.0.0.0 to 203.0.255.255
/8 203.in-addr.arpa 203.0.0.0 to 203.255.255.255
/26 from a /24 64-127.113.0.203.in-addr.arpa 203.0.113.64 to 203.0.113.127

The PTR Must Agree With the Forward Record

A PTR on its own is only a hint. The useful property is forward confirmed reverse DNS: the PTR for an address returns a name, and the forward lookup for that name returns the same address. If the PTR points to host25.example.com but the A record for that name points to 203.0.113.99, the reverse lookup is technically present and practically wrong.

Forward confirmed reverse DNS checks the A record and the PTR record and requires both to agree host25.example.com forward name 203.0.113.25 address host25.example.com. PTR target A PTR Both directions must return the same pair. If the PTR points to a name that resolves elsewhere, the check fails even though the PTR record exists. Mail filters, log enrichment, and inventory reconciliation all depend on this loop agreeing.

Check the loop with two queries. The first reads the forward record, the second reads the PTR, and the third confirms that the PTR target resolves back to the original address.

dig +short host25.example.com A
dig +short -x 203.0.113.25
dig +short host25.example.com A

The output should be consistent: the first and third commands return 203.0.113.25, and the second returns host25.example.com. with the trailing dot. A missing trailing dot in a zone file is a common cause of a name being interpreted as relative to the current origin, which is how a PTR ends up pointing at host25.example.com.corp.example.com.

The same check works for IPv6. The record type is AAAA, and the reverse name is built under ip6.arpa.

dig +short host25.example.com AAAA
dig +short -x 2001:db8:1:2::25

Not every address needs a PTR, but every address that sends mail does. A mail server with no PTR, or with a PTR that does not confirm forward, is a legitimate sender that looks like a compromised host. The receiving side is not being unreasonable; it has no other cheap way to connect the sending IP to a name that the sender controls.

Delegation Decides Who Can Fix It

Before you edit anything, ask the DNS who is authoritative for the reverse name. The answer comes from the NS records at the zone apex, and the SOA record tells you which server holds the serial you are about to change.

dig +short NS 113.0.203.in-addr.arpa
dig +short SOA 113.0.203.in-addr.arpa

If the NS records point at your name servers, the zone is yours. If they point at an ISP or a cloud provider, the PTR is managed on their side, and a local zone file will never be queried. That is the normal situation for provider aggregatable address space, where the provider owns the reverse zone and delegates it only if you ask. Provider independent space is the opposite: you hold the delegation and you are responsible for keeping it correct.

When a delegation is missing, trace it rather than guessing. The trace starts at the root and shows the point at which the reverse name stops resolving through delegations and starts relying on a record that does not exist.

dig +trace 25.113.0.203.in-addr.arpa PTR

The output is long, but the useful part is the last delegation before the answer. If the trace reaches the parent zone and then returns NXDOMAIN, the child zone is not delegated or the parent has no CNAME for that address. If the trace reaches a server that is not yours, the delegation belongs to someone else.

For a block smaller than a /24, the parent zone cannot delegate on an octet boundary. RFC 2317 solves this with a child zone named after the range and a CNAME for each address in the parent. The example below delegates 203.0.113.64/26 to the same name server, which is enough to show the shape.

$TTL 3600
$ORIGIN 113.0.203.in-addr.arpa.
@       IN  SOA ns1.example.com. hostmaster.example.com. (
            2026102901 3600 900 604800 300 )
@       IN  NS  ns1.example.com.
64-127  IN  NS  ns1.example.com.
$GENERATE 64-127 $ CNAME $.64-127

The child zone holds the actual PTRs. The owner names are relative to the child origin, so 64 means 64.64-127.113.0.203.in-addr.arpa, which is the reverse name for 203.0.113.64.

$TTL 3600
$ORIGIN 64-127.113.0.203.in-addr.arpa.
@   IN  SOA ns1.example.com. hostmaster.example.com. (
        2026102901 3600 900 604800 300 )
@   IN  NS  ns1.example.com.
64  IN  PTR host64.example.com.
65  IN  PTR host65.example.com.

The RFC uses a slash in its examples, such as 64/26, but it also advises against copying the slash because some DNS software handles special characters poorly. This article uses the address range 64-127 as the label instead, which is easier to read and avoids the slash entirely. The parent and child both pass named-checkzone, which is the minimum bar before a reload.

Build and Load the Zone

A reverse zone is a normal zone file with PTR records instead of A records. Start with the SOA and NS records, then add one PTR per address. The example uses a /24 and a naming convention that matches the forward zone.

$TTL 3600
$ORIGIN 113.0.203.in-addr.arpa.
@       IN  SOA ns1.example.com. hostmaster.example.com. (
            2026102901 3600 900 604800 300 )
@       IN  NS  ns1.example.com.
25      IN  PTR host25.example.com.
26      IN  PTR host26.example.com.
27      IN  PTR db01.example.com.

Validate the file before reloading. named-checkzone catches the mistakes that a reload will happily serve, including a missing trailing dot, a duplicate owner name, and an out of zone record.

named-checkzone 113.0.203.in-addr.arpa db.203.113
rndc reload 113.0.203.in-addr.arpa
dig +short -x 203.0.113.25

For a DHCP pool with a predictable naming scheme, $GENERATE writes the repetitive records without a loop in your provisioning tool. This is a BIND feature, so check the equivalent for your DNS server before copying it.

$GENERATE 100-199 $ PTR host-$.dhcp.example.com.

Generated records do not know when a lease ends. If the pool is dynamic, prefer dynamic DNS updates from the DHCP server, or regenerate the zone from the same source that manages the leases. A generated PTR that outlives the lease is the same stale record problem in a different costume.

On Windows DNS, the cmdlets are the equivalent of editing the zone file. The -Name value is the owner relative to the reverse zone, not the full address.

Add-DnsServerResourceRecordPtr `
  -Name "25" `
  -ZoneName "113.0.203.in-addr.arpa" `
  -PtrDomainName "host25.example.com" `
  -TimeToLive 01:00:00

Get-DnsServerResourceRecord `
  -ZoneName "113.0.203.in-addr.arpa" `
  -RRType Ptr |
  Where-Object { $_.HostName -eq "25" } |
  Select-Object HostName, @{n="Target";e={$_.RecordData.PtrDomainName}}

Query the result with Resolve-DnsName before you move on. The record can exist in the console and still fail from a client if the zone is not replicated to the server the client uses.

Resolve-DnsName -Name "25.113.0.203.in-addr.arpa" -Type PTR

Keep PTRs in Sync With IPAM

The durable fix is not a one time cleanup. It is a comparison that runs on a schedule, with the address plan as one side and the DNS as the other. The address plan knows which IP belongs to which host. The reverse zone knows which host the DNS claims. The gap between them is the worklist.

Start with the documented addresses that have a hostname. The IP address management list in Obelinf returns the address, the hostname, the subnet, and the device or interface it belongs to, which is enough to build the expected side of the comparison.

export OBELINF_ORG="acme-netops"
export OBELINF_API_KEY="your_read_only_key"
export API="https://api.obelinf.com/${OBELINF_ORG}"

curl --fail --silent --show-error \
  -H "Authorization: Bearer ${OBELINF_API_KEY}" \
  "${API}/ip-addresses?all=true" \
  | jq -r '.ip_addresses[]
      | select(.hostname != null and .hostname != "")
      | [.address, .hostname, (.subnet_cidr // ""), (.device_name // "")]
      | @tsv' > ipam-hosts.tsv

Then query the PTR for each address and print the rows where the PTR is missing or does not match. The example assumes the hostname field stores a fully qualified name. If it stores a short name, append your domain in the comparison instead of changing the inventory.

while IFS=$'\t' read -r ip host _subnet device; do
  ptr=$(dig +short -x "$ip" | paste -sd ',' -)
  if [ "$ptr" != "${host}." ]; then
    printf '%s\t%s\t%s\t%s\n' "$ip" "$host" "${ptr:-MISSING}" "$device"
  fi
done < ipam-hosts.tsv > ptr-mismatches.tsv

The output has one row per problem: address, documented name, actual PTR, and the device that owns the address. A missing PTR shows MISSING. A stale PTR shows the old name. A PTR that points to the right host but with the wrong domain shows the wrong domain. The fixed column order is deliberate so two runs can be compared with diff.

Classify the rows before fixing them, because each class has a different cause and a different owner.

Finding Evidence Fix Owner
Missing PTR MISSING for a documented server Add the PTR in the reverse zone or request it from the provider DNS team
Stale PTR PTR points to a decommissioned host Delete the old record, add the current one DNS team
Wrong domain PTR returns a name outside the forward zone Correct the target and verify the A record DNS team
Multiple PTRs dig returns more than one target Keep the canonical name, remove the rest DNS team
Forward mismatch PTR target resolves to a different IP Fix the A record or the PTR, then recheck both Application owner
PTR for unassigned IP Address has no IPAM record Remove the PTR or assign the address Network team

The fix itself is small. With BIND and a TSIG key, nsupdate deletes the old record and adds the new one in a single transaction. The send is what makes it happen; without it, the commands sit in the buffer and nothing changes.

nsupdate -k /etc/bind/keys/ddns.key <<'EOF'
server 10.0.0.53
update delete 25.113.0.203.in-addr.arpa. PTR
update add 25.113.0.203.in-addr.arpa. 3600 PTR host25.example.com.
send
EOF

Verify with the same query the audit used. A fix that is not verified is a change that will be rediscovered next quarter.

dig +short -x 203.0.113.25

Prevention matters more than the cleanup. Static addresses should be created in the reverse zone by the same process that creates the forward record. DHCP should register and deregister PTRs through dynamic DNS, with a lease time that matches the address policy. The decommissioning checklist should remove the PTR at the same time it removes the A record, and the reverse zone should have an owner who reviews changes rather than a shared login that nobody admits to using.

IPv6 Reverse Zones

IPv6 reverse zones follow the same idea with a different name format. The address is expanded to 32 hexadecimal nibbles, reversed, and suffixed with ip6.arpa. A /64 delegation gives you one zone per subnet, which is a lot of zones if you number subnets generously.

dig +short -x 2001:db8:1:2::25
dig +short NS 2.0.0.0.1.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa

The first command returns the PTR target. The second asks who is authoritative for the /64 zone that contains the address. The zone name is the last 16 nibbles of the reversed address, and it is easy to get wrong by hand.

python3 - <<'PY'
import ipaddress
print(ipaddress.ip_address("2001:db8:1:2::25").reverse_pointer)
PY

The script prints the full reverse name, which you can compare with the zone you delegated. For a /64 zone, strip the host nibbles from the front of the reversed name and keep the 16 labels that belong to the network. Doing that in a script is more reliable than counting labels in a terminal.

The operational choice is whether to create one zone per /64 or to aggregate at a /48 and let the DNS automation create the child zones. A /48 contains 65,536 /64s, so aggregation only helps if the tooling can generate and maintain the children. If the IPv6 plan is still changing, start with the /64s that hold stable infrastructure and leave the client subnets out until the process is ready.

SLAAC privacy addresses make the problem harder. A client that rotates its interface identifier every few hours will create a stream of AAAA and PTR records if you register every address. Register the stable addresses, such as servers, routers, and anycast services, and decide explicitly whether the client subnets need reverse records at all. A PTR for a temporary address that expires in a day is not an inventory record, it is noise with a TTL.

Run a PTR Audit Every Quarter

A quarterly audit is enough for most organizations, and it is short enough that it actually happens. The procedure is the same one described above, run against a dated directory and compared with the previous run.

  1. Export the documented addresses with hostnames from IPAM.
  2. Query the PTR for each address and write the mismatches to a dated file.
  3. Classify each row with the table above and assign an owner.
  4. Fix the records through the authoritative server, not through a cached resolver.
  5. Recheck the fixed rows and record the count that remains.
  6. Compare the count with the previous quarter and look for a class that keeps coming back.

The metric that matters is not the total number of PTRs. It is the number of mismatches per class and the trend. A stable count of missing PTRs on a guest network may be an accepted decision. A growing count of stale PTRs on server addresses is a decommissioning process that is not finishing its job.

The same comparison does not catch the opposite direction on its own. A PTR for an address that no longer exists in the plan will not appear in the mismatch list, because the list starts from documented addresses. To find those records, enumerate the reverse zone with a zone transfer from the authoritative server, or with an export from the DNS provider, and compare each owner name against the IPAM list. Any owner name whose address has no inventory record is a candidate for removal.

The First Step

Pick one /24 that holds servers or mail senders and run the mismatch query against it today. Count the addresses with no PTR, then count the ones whose PTR points to a name that no longer exists. Fix the smallest set first, which is usually the stale records, and add the query to the quarterly audit before the next migration gives you a new set of addresses to reconcile.

Reverse DNS is not glamorous, but it is one of the few records that other people use to decide whether to trust your infrastructure. Keeping the forward and reverse sides in agreement is a small, repeatable discipline, and it is much cheaper than explaining a log entry for a server that was retired a year ago.

Frequently Asked Questions

What is reverse DNS?
Reverse DNS maps an IP address back to a domain name. IPv4 addresses live under in-addr.arpa and IPv6 addresses live under ip6.arpa, with the address octets or nibbles reversed. A PTR record at 25.113.0.203.in-addr.arpa, for example, answers the question who is 203.0.113.25.
What is a PTR record?
A PTR record is the DNS record type used for reverse lookup. It holds the domain name that an IP address should resolve to. The record belongs in the reverse zone that covers the address, and the name it points to should have a forward A or AAAA record that resolves back to the same address.
Do I need reverse DNS for every IP address?
No. Servers, mail senders, network equipment, and any address that appears in logs or monitoring benefit from a PTR. Short lived DHCP addresses often do not, and creating PTRs for them without an automated cleanup process produces stale records faster than anyone can fix them. Prioritize stable infrastructure addresses and the addresses that send email.
What is forward confirmed reverse DNS?
Forward confirmed reverse DNS, often shortened to FCrDNS, checks both directions. The PTR for an IP must return a name, and the forward A or AAAA lookup for that name must return the same IP. Mail systems use the check as one signal in reputation scoring, and a mismatch is a common reason a legitimate sender gets filtered.
How do I delegate a reverse zone smaller than a /24?
Use classless reverse delegation, described in RFC 2317. The parent zone publishes an NS record for a child zone named after the address range, plus a CNAME for each address that points into the child. The child zone then holds the PTR records. The RFC recommends a hyphen rather than a slash in the child zone label because some DNS software handles the slash poorly.
How do I check a PTR record?
Run `dig +short -x 203.0.113.25` for IPv4 or `dig +short -x 2001:db8:1:2::25` for IPv6. The command builds the reverse name for you and returns the PTR target. Add `+noall +answer` when you want the full record with its TTL, and query the authoritative server directly when a public resolver gives a cached answer.

Stop reaching for a spreadsheet

Obelinf keeps every subnet, device, circuit, and rack in one live source of truth, with audit logs and a topology view. Free for personal use.

Related Articles