Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCP fallback is not always used and forcing it is not ergonomic #2197

Open
TaaviE opened this issue Apr 26, 2024 · 2 comments · May be fixed by #2204
Open

TCP fallback is not always used and forcing it is not ergonomic #2197

TaaviE opened this issue Apr 26, 2024 · 2 comments · May be fixed by #2204

Comments

@TaaviE
Copy link

TaaviE commented Apr 26, 2024

Describe the bug
There are systems that block all outgoing UDP with their firewall. In such cases bind succeeds but sendto on 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 drop to the host's prerouting rules, run one of the examples.

Expected behavior
The library should fall back to TCP when EINVAL is 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_conf resolvers 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:

  • OS: Linux
  • Architecture: x86_64
  • rustc version: 1.77.2

Version:

  • Crate: resolver
  • Version: v0.24.1
@djc
Copy link
Collaborator

djc commented Apr 26, 2024

This looks like 3 different issues:

The library should fall back to TCP when EINVAL is returned on UDP writes. (This also likely applies to QUIC connections.)

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::InvalidData in a match arm somewhere.

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).

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.

It would also be nice if the library would let the host OS choose the ephemeral source port. Either by-default for from_system_conf resolvers 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.

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
Copy link
Author

TaaviE commented Apr 26, 2024

This looks like 3 different issues:

Possibly 😅

This makes sense to me. Want to send a PR?

I'm unfortunately not familiar enough with Rust to contribute such changes.

I'm not sure this use case is important enough that we'd want to have specific API for it

Fair enough. It would be sufficient if ResolverConfig would have something like get_name_servers, then one could mutate those entries and replace them later with set_name_servers. There's already add_name_server, so those two would likely be generic enough.

I don't know that we can readily get this information?

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.

@djc djc linked a pull request May 1, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants