[GH-ISSUE #531] Building a recursor with trust-dns-server #224

Closed
opened 2026-03-07 22:52:52 +03:00 by kerem · 2 comments
Owner

Originally created by @kpcyrd on GitHub (Jul 14, 2018).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/531

hey! I'm trying to build a custom dns recursor (similar to unbound), that listens for dns requests and depending on its configuration:

  • serves a static entry
  • forwards to trust-dns-resolver A
  • forwards to trust-dns-resolver B

trust-dns-server seems to be specifically for authoritative dns servers, as DnsHandler is expected to be non-blocking. Naively calling Resolver::lookup_ip inside handle_request panics the thread with Multiple executors at once.

In pseudocode, what I'm trying to do:

impl RequestHandler for DnsHandler {
    fn handle_request<R: ResponseHandler>(&self, request: &Request, response_handle: R) -> SomeFuture {
        info!("dns(req): {}: {:?}", request.src, request.message);
        if is_example_com(&request.message) {
            Ok(HardcodedEntry("192.0.2.3"))
        } else if is_private_zone(&request.message) {
            self.private_resolver(&request.message)
        } else {
            self.default_resolver(&request.message)
        }
    }
}

When using trust-dns-server as a resolver, it might also make sense to make some of the dependencies optional that aren't needed for non-authoritive dns servers, so it doesn't pull in rusqlite, for example. :)

Originally created by @kpcyrd on GitHub (Jul 14, 2018). Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/531 hey! I'm trying to build a custom dns recursor (similar to unbound), that listens for dns requests and depending on its configuration: - serves a static entry - forwards to trust-dns-resolver `A` - forwards to trust-dns-resolver `B` trust-dns-server seems to be specifically for authoritative dns servers, as DnsHandler is expected to be non-blocking. Naively calling `Resolver::lookup_ip` inside handle_request panics the thread with `Multiple executors at once`. In pseudocode, what I'm trying to do: ```rust impl RequestHandler for DnsHandler { fn handle_request<R: ResponseHandler>(&self, request: &Request, response_handle: R) -> SomeFuture { info!("dns(req): {}: {:?}", request.src, request.message); if is_example_com(&request.message) { Ok(HardcodedEntry("192.0.2.3")) } else if is_private_zone(&request.message) { self.private_resolver(&request.message) } else { self.default_resolver(&request.message) } } } ``` When using trust-dns-server as a resolver, it might also make sense to make some of the dependencies optional that aren't needed for non-authoritive dns servers, so it doesn't pull in rusqlite, for example. :)
kerem closed this issue 2026-03-07 22:52:57 +03:00
Author
Owner

@bluejekyll commented on GitHub (Jul 14, 2018):

That makes three of us ;)

Everything you just mentioned sounds about right. Please also see: #483 where there was a bit of discussion on this.

<!-- gh-comment-id:405054003 --> @bluejekyll commented on GitHub (Jul 14, 2018): That makes three of us ;) Everything you just mentioned sounds about right. Please also see: #483 where there was a bit of discussion on this.
Author
Owner

@kpcyrd commented on GitHub (Jul 15, 2018):

As an update (that doesn't really fit into #483), I've worked around Multiple executors at once with a 2nd resolver thread and mrsc, so I'm now able to trigger the resolver from trust-dns-server and get the response back into handle_request (this is blocking though, so I can only reply to one request at a time).

I'm currently stuck with a lifetime error that I can not resolve, as it seems my records need to be able to outlive handle_request (line 132), which is not possible in a recursor.

error[E0597]: `answers` does not live long enough
   --> src/recursor.rs:119:102
    |
119 |                 msg.answers(AuthLookup::Records(LookupRecords::RecordsIter(RrsetRecords::RecordsOnly(answers.iter()))));
    |                                                                                                      ^^^^^^^ borrowed value does not live long enough
120 |                 msg.build(header)
121 |             },
    |             - `answers` dropped here while still borrowed
...
132 |     }
    |     - borrowed value needs to live until here

error: aborting due to previous error

Update: I was able to resolve my lifetime error by defining answers as an empty mutable Vec before creating the MessageResponseBuilder, then extending it with my records.

<!-- gh-comment-id:405057534 --> @kpcyrd commented on GitHub (Jul 15, 2018): As an update (that doesn't really fit into #483), I've worked around `Multiple executors at once` with a 2nd resolver thread and mrsc, so I'm now able to trigger the resolver from trust-dns-server and get the response back into `handle_request` (this is blocking though, so I can only reply to one request at a time). ~~I'm currently stuck with a lifetime error that I can not resolve, as it seems my records need to be able to outlive `handle_request` (line 132), which is not possible in a recursor.~~ ``` error[E0597]: `answers` does not live long enough --> src/recursor.rs:119:102 | 119 | msg.answers(AuthLookup::Records(LookupRecords::RecordsIter(RrsetRecords::RecordsOnly(answers.iter())))); | ^^^^^^^ borrowed value does not live long enough 120 | msg.build(header) 121 | }, | - `answers` dropped here while still borrowed ... 132 | } | - borrowed value needs to live until here error: aborting due to previous error ``` Update: I was able to resolve my lifetime error by defining `answers` as an empty mutable Vec before creating the MessageResponseBuilder, then extending it with my records.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#224
No description provided.