-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
DNS bypass #561
Comments
That seems like a fair desire, unsure about the best API to expose. |
So I toyed with this a little by modifying the async_impl/request struct like: pub struct Request {
ip: Option<std::net::Ipv4Addr>,
method: Method,
url: Url,
headers: HeaderMap,
body: Option<Body>,
} and then tried compiling / updating over and over again, making the necessary changes at each step to get past whatever errors were introduced. I tried to stay true to how the rest of the library treated an instance of a
I didn't think it should be merged into request "headers" as its rather part of the IP header, but taking this approach meant I needed to modify the h2, hyper, and http libraries as well, and possibly more? |
Before you go to far down that rabbit hole, I think it'd be best to think about the exposed API to the user. The implementation likely doesn't need to bother touching h2/hyper/http, and would probably just adjust reqwest's |
Ahh. Well it's too late for me I already went down the rabbit hole! Anyhow, I think you're right it's best to avoid changes on any dependent libraries. I'll try again sometime this week hopefully and report back. For the API, I already don't like .skip_dns() because "DNS" is just one of the ways by which an IP could be resolved. I do like that the default behavior is to attempt resolution, since I believe the users of reqwest would prefer not to worry about it. Perhaps skip_resolution would be better? I still like 'skip', since it implies that the standard behavior is to attempt IP resolution, and shows that by calling that function, no subsequent resolution would occur. I don't think support for non-IP protocols would be anything in-scope for this library, so accepting an std::net::IpAddr would be best? Having anything more than a .skip_resolution(std::net::IpAddr) builder method to support this behavior, I think, would be unnecessary. |
Does curl and other libraries provide an easy option to do this? |
curl has Now that I'm looking at it, I can see why curl would have a --resolve as opposed to a skip_resolution, as it would matter with redirects. If you skip resolution on the first host, but then get redirected, do you then use DNS for the redirect if it goes to a new host? In this case, you'd want to simply set up a resolution mask where host A maps to IP A, and let all other names resolve normally. In curls example, they are allowing host A to map to IP A, only on a specific port, otherwise use DNS as normal (I think even for host A on a different port). That seems a bit more complex than what I was envisioning, where I would simply want to establish a static Host->IP resolution, ignoring the port. Now that I've seen how curl does it, I think I'd want to leave DNS resolution "on" for any names that weren't already defined, and have a Since the default resolver is already replaceable with a custom one, maybe all this is really a bogus feature request? All I'd need to do is figure out how to mimic the default resolver and then add my very basic "mask" in front of that resolver for an early return. I'm not sure how to do that, but already it seems that would be a more acceptable direction to take, rather than have all reqwest requests perform a dns cache check for something that probably doesn't exist 99% of the time. |
Maybe I was confused, I'm looking now at the reqwest source and I don't see how to set my own resolver on either the client or the request. Was that part of hyper? |
@seanmonstar Can you reopen this issue? Specifying custom DNS resolution is quite helpful. |
I was the one that closed it, re-opening now. |
A quite useful feature. |
That's really useful, especially for us to bypass DNS spoofing. |
It seems that it involves modifying hyper’s source code for per-request DNS bypassing to work. |
I think that the API presented to users for this could also be useful for #39. |
I've played around with an implementation of this and it's definitely bubbling up to cause some ugliness so I think there are some choices to make. Currently the HttpConnector is an enum with either the GaiResolver or the TrustDNS resolver. Here's my attempt to make a generic wrapper resolver that would allow a user to add specific overrides:
This is the first time I've written this kind of futures + iterators code so this may be unidiomatic (happy to rework if there are better options). NB: this adds tower and itertools as new dependencies of reqwest. The implication of this though is that the resolver becomes a new unnamed type, and there is an overhead for clients that are not using overrides at all. Other options for a design here that I can see:
If anyone has any input on how this could be cleanly implemented I'm happy to take a swing and get a PR up. |
As for user API my suggestion would be:
This would be in keeping with curls API. There is a question as to whether we want to allow custom resolves to map the same domain to multiple IP addresses. The use case I'm motivated by here is for testing against a local running TLS server so this isn't an issue but there may be other use cases that would prefer multiple potential IPs. |
…tar#561) This change allows users to bypass the selected DNS resolver for specific domains. The allows, for example, to make calls to a local TLS server by rerouting a given domain to 127.0.0.1. The approach I've taken for the design is to wrap the resolver in an outer service. This leads to a fair amount of boilerplate code mainly to be able to explain the typing to the compiler. The actual business logic is very simple for the number of lines involved. Closes seanmonstar#561
…tar#561) This change allows users to bypass the selected DNS resolver for specific domains. The allows, for example, to make calls to a local TLS server by rerouting a given domain to 127.0.0.1. The approach I've taken for the design is to wrap the resolver in an outer service. This leads to a fair amount of boilerplate code mainly to be able to explain the typing to the compiler. The actual business logic is very simple for the number of lines involved. Closes seanmonstar#561
…tar#561) This change allows users to bypass the selected DNS resolver for specific domains. The allows, for example, to make calls to a local TLS server by rerouting a given domain to 127.0.0.1. The approach I've taken for the design is to wrap the resolver in an outer service. This leads to a fair amount of boilerplate code mainly to be able to explain the typing to the compiler. The actual business logic is very simple for the number of lines involved. Closes seanmonstar#561
…tar#561) This change allows users to bypass the selected DNS resolver for specific domains. The allows, for example, to make calls to a local TLS server by rerouting a given domain to 127.0.0.1. The approach I've taken for the design is to wrap the resolver in an outer service. This leads to a fair amount of boilerplate code mainly to be able to explain the typing to the compiler. The actual business logic is very simple for the number of lines involved. Closes seanmonstar#561
…tar#561) This change allows users to bypass the selected DNS resolver for specific domains. The allows, for example, to make calls to a local TLS server by rerouting a given domain to 127.0.0.1. The approach I've taken for the design is to wrap the resolver in an outer service. This leads to a fair amount of boilerplate code mainly to be able to explain the typing to the compiler. The actual business logic is very simple for the number of lines involved. Closes seanmonstar#561
…tar#561) This change allows users to bypass the selected DNS resolver for specific domains. The allows, for example, to make calls to a local TLS server by rerouting a given domain to 127.0.0.1. The approach I've taken for the design is to wrap the resolver in an outer service. This leads to a fair amount of boilerplate code mainly to be able to explain the typing to the compiler. The actual business logic is very simple for the number of lines involved. Closes seanmonstar#561
…1277) This change allows users to bypass the selected DNS resolver for specific domains. The allows, for example, to make calls to a local TLS server by rerouting a given domain to 127.0.0.1. The approach I've taken for the design is to wrap the resolver in an outer service. This leads to a fair amount of boilerplate code mainly to be able to explain the typing to the compiler. The actual business logic is very simple for the number of lines involved. Closes #561
* master: add option to disable http2 upgrade (seanmonstar#1292) Fix documentation of http1_title_case_headers() (seanmonstar#1294) CI: make a single final job that depends on all others (seanmonstar#1291) Fix bare url warnings in `multipart` docs (seanmonstar#1289) v0.11.4 Allow overriding of DNS resolution to specified IP addresses(seanmonstar#561) (seanmonstar#1277) WASM: Add `try_clone` implementations to `Request` and `RequestBuilder` (seanmonstar#1286) Add native-tls-alpn feature (seanmonstar#1283)
…tar#561) (seanmonstar#1277) This change allows users to bypass the selected DNS resolver for specific domains. The allows, for example, to make calls to a local TLS server by rerouting a given domain to 127.0.0.1. The approach I've taken for the design is to wrap the resolver in an outer service. This leads to a fair amount of boilerplate code mainly to be able to explain the typing to the compiler. The actual business logic is very simple for the number of lines involved. Closes seanmonstar#561
It would be nice if there were a way we could bypass DNS resolution and connect directly to an IP address we specify during the request. Something like...
client.skip_dns('127.0.0.1').get("https:/google.com").send()
SNI / cert validation could still work off the domain in the URI.
The text was updated successfully, but these errors were encountered: