DNS.Zone (DNS v0.5.0)
View SourceDNS Zone management and operations.
This module provides the core DNS zone functionality including zone creation, management, validation, zone file parsing, and zone transfers.
Zone Types
The following zone types are supported:
:authoritative- Primary authoritative zone with full record management:stub- Stub zone containing only NS records for delegation:forward- Forward zone redirecting queries to specified servers:cache- Cache zone for temporary DNS response caching
Creating Zones
Basic Zone Creation
# Create a basic authoritative zone
zone = DNS.Zone.new("example.com")
# Create a zone with specific type
zone = DNS.Zone.new("example.com", :authoritative)
# Create a zone with options
zone = DNS.Zone.new("example.com", :authoritative, soa_records: [soa_record])Interactive Zone Creation
# Create zone with interactive prompts
{:ok, zone} = DNS.Zone.Editor.create_zone_interactive("example.com")
# Create zone with initial records
{:ok, zone} = DNS.Zone.Editor.create_zone_interactive("example.com",
type: :authoritative,
soa: [
mname: "ns1.example.com",
rname: "admin.example.com",
serial: 2024010101,
refresh: 3600,
retry: 1800,
expire: 604800,
minimum: 300
],
ns: ["ns1.example.com", "ns2.example.com"],
a: ["192.168.1.1"]
)Managing Zone Records
Adding Records
# Add an A record
{:ok, zone} = DNS.Zone.Editor.add_record("example.com", :a,
name: "www.example.com",
ip: {192, 168, 1, 100},
ttl: 300
)
# Add an MX record
{:ok, zone} = DNS.Zone.Editor.add_record("example.com", :mx,
name: "example.com",
preference: 10,
exchange: "mail.example.com"
)
# Add a CNAME record
{:ok, zone} = DNS.Zone.Editor.add_record("example.com", :cname,
name: "ftp.example.com",
target: "www.example.com"
)Listing and Searching Records
# List all records in a zone
{:ok, records} = DNS.Zone.Editor.list_records("example.com")
# Search for specific records
{:ok, a_records} = DNS.Zone.Editor.search_records("example.com", type: :a)
{:ok, www_records} = DNS.Zone.Editor.search_records("example.com", name: "www.example.com")Updating and Removing Records
# Update a record
{:ok, zone} = DNS.Zone.Editor.update_record(
"example.com", :a,
[name: "www.example.com"],
[ttl: 600]
)
# Remove records
{:ok, zone} = DNS.Zone.Editor.remove_record("example.com", :a, name: "old.example.com")Zone Validation
Basic Validation
# Validate a zone
case DNS.Zone.Validator.validate_zone(zone) do
{:ok, result} ->
IO.puts("Zone is valid: #{result.zone_name}")
{:error, result} ->
IO.puts("Zone has errors: #{inspect(result.errors)}")
endComprehensive Diagnostics
# Generate zone diagnostics
diagnostics = DNS.Zone.Validator.generate_diagnostics(zone)
IO.inspect(diagnostics.statistics)
IO.inspect(diagnostics.security_assessment)
IO.inspect(diagnostics.recommendations)Zone File Operations
Parsing Zone Files
# Load zone from BIND format file
{:ok, zone} = DNS.Zone.Loader.load_zone_from_file("example.com", "example.com.zone")
# Load zone from string
zone_content = """
$TTL 3600
$ORIGIN example.com.
@ IN SOA ns1.example.com. admin.example.com. (
2024010101 ; serial
3600 ; refresh
1800 ; retry
604800 ; expire
300 ; minimum
)
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
www IN A 192.168.1.100
mail IN A 192.168.1.200
"""
{:ok, zone} = DNS.Zone.Loader.load_zone_from_string(zone_content)Exporting Zone Files
# Export to BIND format
{:ok, bind_content} = DNS.Zone.Editor.export_zone("example.com", format: :bind)
File.write!("example.com.zone", bind_content)
# Export to JSON
{:ok, json_content} = DNS.Zone.Editor.export_zone("example.com", format: :json)
File.write!("example.com.json", json_content)
# Export to YAML
{:ok, yaml_content} = DNS.Zone.Editor.export_zone("example.com", format: :yaml)
File.write!("example.com.yaml", yaml_content)Zone Transfers
Full Zone Transfer (AXFR)
# Perform AXFR transfer
case DNS.Zone.Transfer.axfr("example.com") do
{:ok, records} ->
IO.puts("Received #{length(records)} records via AXFR")
{:error, reason} ->
IO.puts("AXFR failed: #{reason}")
endIncremental Zone Transfer (IXFR)
# Perform IXFR transfer
case DNS.Zone.Transfer.ixfr("example.com", 2024010101) do
{:ok, changes} ->
IO.puts("Received #{length(changes)} changes via IXFR")
{:error, reason} ->
IO.puts("IXFR failed: #{reason}")
endApplying Zone Transfers
# Apply transferred zone data
records = [...] # Records from AXFR/IXFR
case DNS.Zone.Transfer.apply_transfer("example.com", records, transfer_type: :axfr) do
{:ok, zone} ->
IO.puts("Zone updated successfully")
{:error, reason} ->
IO.puts("Failed to apply transfer: #{reason}")
endDNSSEC Management
Enabling DNSSEC
# Enable DNSSEC for a zone
case DNS.Zone.Editor.enable_dnssec("example.com") do
{:ok, signed_zone} ->
IO.puts("DNSSEC enabled successfully")
{:error, reason} ->
IO.puts("DNSSEC setup failed: #{reason}")
endManual DNSSEC Signing
# Sign zone with custom options
case DNS.Zone.DNSSEC.sign_zone(zone,
algorithm: :rsasha256,
key_size: 2048,
nsec3_enabled: true
) do
{:ok, signed_zone} ->
IO.puts("Zone signed successfully")
{:error, reason} ->
IO.puts("Signing failed: #{reason}")
endZone Cloning
Clone Zone for Testing
# Clone an existing zone
case DNS.Zone.Editor.clone_zone("production.com", "staging.com") do
{:ok, cloned_zone} ->
IO.puts("Zone cloned successfully")
{:error, reason} ->
IO.puts("Cloning failed: #{reason}")
endExamples
Complete Zone Setup
# Create a complete zone with all essential records
{:ok, zone} = DNS.Zone.Editor.create_zone_interactive("company.com",
type: :authoritative,
soa: [
mname: "ns1.company.com",
rname: "admin.company.com",
serial: 2024010101,
refresh: 3600,
retry: 1800,
expire: 604800,
minimum: 300
],
ns: ["ns1.company.com", "ns2.company.com"],
a: [
{"@", "192.168.1.10"},
{"www", "192.168.1.10"},
{"mail", "192.168.1.20"},
{"ns1", "192.168.1.1"},
{"ns2", "192.168.1.2"}
],
mx: [{10, "mail.company.com"}],
txt: [{"@", "v=spf1 mx ~all"}]
)
# Validate the zone
{:ok, validation} = DNS.Zone.Validator.validate_zone(zone)
IO.inspect(validation.summary)
# Export to BIND format
{:ok, zone_file} = DNS.Zone.Editor.export_zone("company.com", format: :bind)
File.write!("company.com.zone", zone_file)
Summary
Functions
Export zone with specified format.
Convert zone AST to DNS.Zone struct.
Parse a zone file from a file path using the new AST-based parser.
Parse a zone file from a string using the new AST-based parser.
Export zone to BIND format string.
Types
@type t() :: %DNS.Zone{ comments: [String.t()], name: DNS.Zone.Name.t(), options: [term()], origin: String.t() | nil, records: [DNS.Zone.RRSet.t()], soa: map() | nil, ttl: integer() | nil, type: zone_type() }
@type zone_type() :: :authoritative | :stub | :forward | :cache
Functions
Export zone with specified format.
Supported formats: :bind, :json, :yaml
@spec from_ast(DNS.Zone.Parser.ZoneFile.t()) :: t()
Convert zone AST to DNS.Zone struct.
@spec hostname(DNS.Zone.Name.t(), DNS.Message.Domain.t()) :: DNS.Zone.Name.t() | false
Parse a zone file from a file path using the new AST-based parser.
Examples
iex> {:ok, zone} = DNS.Zone.parse_zone_file("example.com.zone")
iex> zone.origin
"example.com"
Parse a zone file from a string using the new AST-based parser.
Examples
iex> zone_content = ""
...> $ORIGIN example.com.
...> $TTL 3600
...> @ IN SOA ns1.example.com. admin.example.com. (
...> 2024010101 ; serial
...> 3600 ; refresh
...> 1800 ; retry
...> 604800 ; expire
...> 300 ; minimum
...> )
...> @ IN NS ns1.example.com.
...> @ IN NS ns2.example.com.
...> www IN A 192.168.1.100
...> ""
iex> {:ok, zone} = DNS.Zone.parse_zone_string(zone_content)
iex> zone.origin
"example.com"
iex> length(zone.records)
3
Export zone to BIND format string.