Skip to main content

Security Toolbox

Zone Transfer

Test whether a domain's nameservers allow DNS zone transfer (AXFR), and show the zone contents when they do.

Warning: Authorised use only. This tool contacts nameservers and can expose a full zone. Use it only on systems you are allowed to test.

Install

Requires Python 3.10+. Runtime dependencies (dnspython, prettytable, and colored) install with the package.

pip install lupaxa-zone-transfer
zone-transfer --help

You can also run python -m lupaxa.zone_transfer.

CLI

zone-transfer example.com
zone-transfer example.com example.org
zone-transfer example.com --nameserver ns1.example.net --nameserver 203.0.113.10
zone-transfer example.com --format json
zone-transfer example.com --fail-open
zone-transfer example.com --timeout 10 --no-color
python -m lupaxa.zone_transfer --version

Each domain is inspected independently. The tool discovers NS records (or uses --nameserver for every domain and skips discovery), sorts hosts by name with IPv4 before IPv6, and tries AXFR on every address. On a TTY a spinner on stderr shows the current lookup or transfer. --fail-open exits 2 if any server allowed AXFR.

Flag Default Description
--nameserver, -n discover NS Nameserver host or IP (repeatable)
--format, -f table Output format: table or json
--fail-open off Exit 2 if any endpoint allowed AXFR
--timeout 10 DNS and AXFR timeout in seconds (must be > 0)
--no-color off Disable colour in table output
--version — Print the package version and exit

Table output is titled with the domain. Rows are nameserver, address, family, status, and reason. For each allowed attempt a second table lists name, type, TTL, and rdata. On a colour terminal, allowed is red, refused is green, and error is grey. Pass --no-color or set NO_COLOR for plain text.

JSON is a list of {domain, error, attempts} objects. Each attempt has nameserver, address, family, status, reason, and records. Record objects use type (not rtype). error is a string, never null. records is always a list.

[
  {
    "domain": "example.com",
    "error": "",
    "attempts": [
      {
        "nameserver": "ns1.example.net",
        "address": "203.0.113.10",
        "family": "IPv4",
        "status": "allowed",
        "reason": "",
        "records": [
          {"name": "@", "type": "SOA", "ttl": 3600, "rdata": "ns1.example.net. hostmaster. 1 1 1 1 1"}
        ]
      }
    ]
  }
]

Attempt Status

Status Meaning
allowed AXFR succeeded; records holds the zone
refused Server answered not permitted (REFUSED / FORMERR)
error Timeout, connect failure, or no addresses

Exit Codes

Code When
0 Every domain was tested; refused and per-endpoint errors are OK
2 Invalid input, NS discovery failure, or --fail-open + allowed

A domain-level NS discovery failure sets error and exits 2. A refused transfer is a normal result and exits 0 unless --fail-open saw an allowed attempt.

Library

from lupaxa.zone_transfer import inspect_domain, inspect_many

report = inspect_domain("example.com")
pinned = inspect_domain("example.com", nameservers=["203.0.113.10"])
reports = inspect_many(["example.com", "example.org"], timeout=10.0)

for attempt in report.attempts:
    print(attempt.endpoint.address, attempt.status)
    for record in attempt.records:
        print(record.name, record.rtype, record.rdata)

inspect_domain does not raise when AXFR is refused or one address fails. Those become attempt rows. Empty domains, an empty nameserver list, or an empty inspect_many list raise InvalidTargetError. NameserverLookupError is raised by lookup_nameservers; inspect_domain catches it into DomainReport.error. ZoneTransferError is the base class.

Pass on_progress to receive Progress events (domain, phase, message, current, total). Phases are lookup (NS discovery), resolve (A/AAAA expansion), and try (one AXFR). The library does not print; the CLI uses that hook for the spinner.

Development

make init
make python-install-dev
make python-check
The Lupaxa Project Footer

Metadata

Release files for lupaxa-zone-transfer 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lupaxa-zone-transfer 0.1.5
File Size Uploaded
lupaxa_zone_transfer-0.1.5.tar.gz 11.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lupaxa-zone-transfer 0.1.5
File Interpreter ABI Platform
lupaxa_zone_transfer-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 26.9 kB

Release files / lupaxa_zone_transfer-0.1.5.tar.gz

Download URL lupaxa_zone_transfer-0.1.5.tar.gz
Size 11.4 kB
Tags Source
SHA-256 checksum
How to use checksums
0318bb9b709b6744050ffd2ada79986b36008947abb61a93cd66d21a94637628
BLAKE2b-256 checksum
How to use checksums
309c2a9c75309efff0305bf7fdc6bcd096a544a8e22be1361a009b1e271069b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / lupaxa_zone_transfer-0.1.5-py3-none-any.whl

Download URL lupaxa_zone_transfer-0.1.5-py3-none-any.whl
Size 15.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2974907a51c7120ab9f64efed1577a1a912d7eed06d236591da0d08ad75adacb
BLAKE2b-256 checksum
How to use checksums
5de2d322e1624fa1e509dbd5d9ce17a19680fe39cfd7f7317181f40dbe6a9f40
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page