mirror of
https://github.com/hickory-dns/hickory-dns.git
synced 2026-04-25 11:15:54 +03:00
[GH-ISSUE #2197] TCP fallback is not always used and forcing it is not ergonomic #917
Labels
No labels
blocked
breaking-change
bug
bug:critical
bug:tests
cleanup
compliance
compliance
compliance
crate:all
crate:client
crate:native-tls
crate:proto
crate:recursor
crate:resolver
crate:resolver
crate:rustls
crate:server
crate:util
dependencies
docs
duplicate
easy
easy
enhance
enhance
enhance
feature:dns-over-https
feature:dns-over-quic
feature:dns-over-tls
feature:dnsssec
feature:global_lb
feature:mdns
feature:tsig
features:edns
has workaround
ops
perf
platform:WASM
platform:android
platform:fuchsia
platform:linux
platform:macos
platform:windows
pull-request
question
test
tools
tools
trust
unclear
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/hickory-dns#917
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @TaaviE on GitHub (Apr 26, 2024).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/2197
Describe the bug
There are systems that block all outgoing UDP with their firewall. In such cases
bindsucceeds butsendtoon those sockets returns-1 (EINVAL).This results in a
ResolveError { kind: Proto(ProtoError { kind: Io(Os { code: 22, kind: InvalidInput, message: "Invalid argument" }) }), but the resolver does not fall back to TCP.To Reproduce
Add
ip protocol udp dropto the host's prerouting rules, run one of the examples.Expected behavior
The library should fall back to TCP when
EINVALis returned on UDP writes. (This also likely applies to QUIC connections.)Ideally it would be possible to force TCP with a simple call when configuring the resolver, such as:
Resolver::from_system_conf().force_proto(Protocol::Tcp).It would also be nice if the library would let the host OS choose the ephemeral source port. Either by-default for
from_system_confresolvers or it should be easy to enable. It's quite possible that the host OS is configured to allow a range better (or more suitable in some setups) than what the library uses. Source port ranges and usage can also used for fingerprinting, this would reduce the effectiveness of such approaches.System:
Version:
@djc commented on GitHub (Apr 26, 2024):
This looks like 3 different issues:
This makes sense to me. Want to send a PR? I think we have some code for fallback already so probably just involves adding
io::ErrorKind::InvalidDatain a match arm somewhere.I'm not sure this use case is important enough that we'd want to have specific API for it, but we recently discussed in #2188 that mutating the configuration returned from
from_system_conf()is generally pretty annoying, so I think we could discuss how we could improve on that.I don't know that we can readily get this information? We use the resolv-conf crate on Linux, and from a quick look it doesn't to yield this information. It otherwise sounds reasonable, though.
@TaaviE commented on GitHub (Apr 26, 2024):
Possibly 😅
I'm unfortunately not familiar enough with Rust to contribute such changes.
Fair enough. It would be sufficient if
ResolverConfigwould have something likeget_name_servers, then one could mutate those entries and replace them later withset_name_servers. There's alreadyadd_name_server, so those two would likely be generic enough.I don't think there's an OS-agnostic way of getting this information. This shouldn't however be an obstacle in leaving it to the OS, which is not difficult, unless there's a strong need for otherwise.
@bluejekyll commented on GitHub (May 18, 2024):
I was just looking at this. First, I'm going to simplify the ResolveError, rather than having it wrap IO errors itself, it will always use the interior ProtoError for that, it simplifies some logic. Second, rather than being specific about the IO error, perhaps we always retry on TCP on any IO error... Thoughts?
I figure any IO error on UDP is worth promoting to TCP. That said, I think the complexity here, and the reason we're getting test failures in the other PR is there might be multiple UDP name servers to try before going to TCP. I'm trying to see if there is a good way to do with this scenario.