Skip to content

Forwarding, blocklist and dynamic DNS with Terraform

These resources control how DTM resolves names it is not authoritative for, plus the DNS blocklist and dynamic-update settings. See forwarders and stub zones for the concepts.

dtm_default_forwarder (role: editor or admin) is a cluster-wide singleton: where DTM sends queries that match no authoritative zone, conditional forwarder, or stub zone.

resource "dtm_default_forwarder" "this" {
upstreams = ["168.63.129.16"]
enabled = true
}

Set enabled = false to answer non-matching queries with REFUSED instead of forwarding them.

dtm_forwarder (role: editor or admin) forwards one domain to specific upstreams.

resource "dtm_forwarder" "ad" {
domain = "corp.contoso.com."
upstreams = ["10.0.0.1:53"]
comment = "Active Directory DNS"
}
Attribute Required Description
domain Yes FQDN with trailing dot. Changing it replaces the resource.
upstreams Yes Resolvers as ip:port or bare IP.
comment No Free-form note.
enabled No Defaults to true.

dtm_stub_zone (role: editor or admin) tracks a delegated domain’s nameservers from a set of hints.

resource "dtm_stub_zone" "partner" {
domain = "partner.local."
hints = ["10.5.0.1:53"]
}
Attribute Required Description
domain Yes FQDN with trailing dot. Changing it replaces the resource.
hints Yes Bootstrap nameserver IPs.
comment No Free-form note.
enabled No Defaults to true.
refresh_interval_seconds No How often to refresh the NS list (0 = server default).

dtm_blocklist (role: editor or admin) is a cluster-wide singleton that sinks matching names to NXDOMAIN (suffix match).

resource "dtm_blocklist" "this" {
domains = [
"doubleclick.net",
"trackers.example",
]
}

The computed entry_count reports the deduplicated number of entries.

dtm_tsig_key (role: editor or admin) authorises RFC 2136 dynamic updates to specific zones. Every attribute forces replacement, so rotate by creating a new key.

resource "dtm_tsig_key" "dhcp" {
name = "dhcp-update."
algorithm = "hmac-sha256"
secret = var.tsig_secret # sensitive, base64, >=128 bits decoded
zone_ids = [dtm_zone.example.id]
lifecycle {
create_before_destroy = true
}
}
Attribute Required Description
name Yes Key name, e.g. dhcp-update. (trailing dot optional). Used as the API key.
algorithm Yes hmac-sha256 (recommended), hmac-sha384, or hmac-sha512.
secret Yes Base64 shared secret, at least 128 bits decoded. Sensitive.
zone_ids Yes IDs of the zones this key may update.

When a signed dynamic update or zone transfer arrives, DTM matches the wire key name against the stored name case-insensitively and with or without the trailing dot. A key stored bare (the form nsupdate and dnssec-keygen use) therefore authorises the same operations as its dotted equivalent.

Import a TSIG key by its name (not ID): terraform import dtm_tsig_key.dhcp dhcp-update.

Both are admin singletons, with one scope difference: the AXFR record applies live and replicates cluster-wide, while the dynamic-DNS record configures only the node the provider’s endpoint targets, so declare one dtm_dynamic_dns_config per provider endpoint for each node that should accept RFC 2136 updates (see dynamic DNS).

# Enable RFC 2136 dynamic updates on the endpoint's node, requiring TSIG.
resource "dtm_dynamic_dns_config" "this" {
enabled = true
require_tsig = true
}
# Allow zone transfers (AXFR) from a CIDR, requiring TSIG, and send
# RFC 1996 DNS NOTIFY to a mirroring secondary on every zone change.
resource "dtm_axfr_config" "this" {
enabled = true
allowed_cidrs = ["10.0.0.0/8"]
require_tsig = true
notify_targets = ["10.20.0.10:53"]
notify_tsig_key_name = "mirror-key"
notify_debounce_seconds = 5
}

The three notify_* attributes drive outbound DNS NOTIFY: each target gets one NOTIFY per zone per quiet window (notify_debounce_seconds, so a bulk import does not storm the mirror), optionally signed with a stored TSIG key (a missing key fails closed rather than sending unsigned). Like the rest of the record, they apply live and replicate cluster-wide.

dtm_forwarder_hardening_config (role: admin, per-node singleton: it hardens only the node the provider endpoint targets, like dtm_dynamic_dns_config above; apply it via each node’s endpoint to cover the cluster) constrains the default forwarder with an optional allowlist and per-client rate cap.

resource "dtm_forwarder_hardening_config" "this" {
qname_allowlist = ["microsoft.com.", "azure.net."]
per_client_qps = 50
per_client_burst = 100
}

An empty qname_allowlist forwards everything; per_client_qps = 0 means no per-client cap.