nx_acme_dns01_propagation.nx
buildroot/runtime/nx_acme_dns01_propagation.nx
about
nx_acme_dns01_propagation.nx -- real DNS-01 TXT propagation poll.
Replaces the fixed sys_sleep_ms(360000) "hope it propagated" wait in
nx_acme_dns01_issue with an ACTIVE poll: after the _acme-challenge TXT
records are created at Porkbun, query DNS until the expected value(s) are
VISIBLE, then trigger immediately -- bounded by a ~6 min ceiling so a
propagation stall never hangs the renewal (it falls through to trigger,
matching the old behaviour's worst case).
WHY query the AUTHORITATIVE nameserver, not just 1.1.1.1:
The same name _acme-challenge.<domain> is reused every renewal with a
NEW value; a public recursive resolver can serve the PREVIOUS run's
cached TXT RRset (TTL 600s) and report "visible" against stale data, or
cache a negative answer. The authoritative Porkbun NS always serves the
live zone -- exactly what Let's Encrypt's own validators resolve. So we:
1. look up the zone's NS set (recursive resolver),
2. resolve one NS hostname -> IP,
3. query the TXT DIRECTLY at that authoritative IP.
If NS discovery fails we fall back to a public resolver (still bounded).
Sovereign UDP (sys_socket SOCK_DGRAM / sendto / recvfrom) + nx_dns wire
codec + nx_dns_txt parsers. No third-party resolver library.
license_tier: ORIGINAL (composes nx_dns RFC 1035 + the shipped A-resolver)
genealogy_id: international-research-sources/ietf/rfc_1035 + rfc_8555 ยง8.4
dependencies 4 imports · 2 importers
imports: nx_syscalls.nxnx_dns.nxnx_dns_txt.nxnx_dns_resolve_a_record.nx
imported by: nx_acme_dns01_issue.nxnx_acme_dns01_propagation_gate.nx
structs
| none |
consts
| 35 | const NX_DNS01_POLL_INTERVAL_MS: i64 = 5000 |
| 36 | const NX_DNS01_POLL_TIMEOUT_MS: i64 = 360000 |
| 37 | const NX_DNS01_UDP_TIMEOUT_SEC: i64 = 3 |
| 38 | const NX_DNS01_UDP_BUF: i64 = 2048 |
functions
| 41 | func _dns01_sockaddr(out: *u8, ipv4_packed: i64, port: i64) -> i64 called by 1: nx_dns01_udp_query |
| 60 | func nx_dns01_udp_query( |
| 91 | func nx_dns01_txt_present_at( |
| 109 | func nx_dns01_authoritative_ip(domain: *u8, domain_len: i64, now: i64) -> i64 called by 1: nx_dns01_txt_visible calls 4: sys_mmapnx_dns01_udp_querynx_dns_first_nsnx_dns_resolve_default |
| 128 | func nx_dns01_txt_visible( |
| 150 | func nx_dns01_wait_txt_propagated( |
| 189 | func main() -> i64 |