mirror of
https://github.com/stalwartlabs/stalwart.git
synced 2026-11-11 19:37:52 +00:00
Fix DNS: The DNSSEC resolver queries a single nameserver at a time, working around a hickory-resolver race that cancels the TCP retry when two nameservers return a truncated response in parallel
This commit is contained in:
1 parent
1f802ab54e
commit
e82d78be3f
3 files changed
+12
-10
No files matched your search
@@ -11,6 +11,10 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If
|
||||
## Changed
|
||||
|
||||
## Fixed
|
||||
- DNS: The DNSSEC resolver queries a single nameserver at a time, working around a `hickory-resolver` race that cancels the TCP retry when two nameservers return a truncated response in parallel.
|
||||
- Troubleshoot tool:
|
||||
- MX records are resolved through the DNSSEC-validating resolver, matching the resolver used by the delivery path.
|
||||
- A TLSA lookup that fails or returns bogus records stops the delivery attempt for that host, instead of continuing without DANE.
|
||||
- WebUI: A failed update no longer takes an `Application` offline.
|
||||
|
||||
## [0.16.22] - 2026-09-13
|
||||
|
||||
@@ -214,6 +214,7 @@ impl Resolvers {
|
||||
let config_dnssec = resolver_config.clone();
|
||||
let mut opts_dnssec = opts.clone();
|
||||
opts_dnssec.validate = true;
|
||||
opts_dnssec.num_concurrent_reqs = 1;
|
||||
|
||||
let dnssec = DnssecResolver {
|
||||
resolver: TokioResolver::builder_with_config(
|
||||
@@ -343,6 +344,7 @@ impl Default for Resolvers {
|
||||
let config_dnssec = config.clone();
|
||||
let mut opts_dnssec = opts.clone();
|
||||
opts_dnssec.validate = true;
|
||||
opts_dnssec.num_concurrent_reqs = 1;
|
||||
|
||||
Self {
|
||||
dns: MessageAuthenticator::new(config, opts).expect("Failed to build DNS resolver"),
|
||||
|
||||
@@ -230,14 +230,7 @@ async fn delivery_diagnose(
|
||||
|
||||
// Lookup MX
|
||||
let now = Instant::now();
|
||||
let mxs = match server
|
||||
.core
|
||||
.smtp
|
||||
.resolvers
|
||||
.dns
|
||||
.mx_lookup(&domain, Some(&server.inner.cache.dns_mx))
|
||||
.await
|
||||
{
|
||||
let mxs = match server.mx_lookup(domain.as_str()).await {
|
||||
Ok(mxs) => mxs,
|
||||
Err(err) => {
|
||||
tx.send(DeliveryStage::MxLookupError {
|
||||
@@ -419,7 +412,7 @@ async fn delivery_diagnose(
|
||||
})
|
||||
.await?;
|
||||
|
||||
None
|
||||
continue 'outer;
|
||||
}
|
||||
Ok(TlsaResult::Missing) => {
|
||||
tx.send(DeliveryStage::TlsaNotFound {
|
||||
@@ -440,14 +433,17 @@ async fn delivery_diagnose(
|
||||
reason: "No TLSA records found for MX".to_string(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
None
|
||||
} else {
|
||||
tx.send(DeliveryStage::TlsaLookupError {
|
||||
elapsed: now.elapsed_ms(),
|
||||
reason: err.to_string(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
continue 'outer;
|
||||
}
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user