omjadas / hudsucker

Intercepting HTTP/S proxy
https://crates.io/crates/hudsucker
Apache License 2.0
209 stars 37 forks source link

Is there way to parse basic auth? #31

Closed 0xFar5eer closed 2 years ago

0xFar5eer commented 2 years ago

Hello, your crate is amazing! Love it! I am providing user pass for the proxy i.e http://user:pass@localhost:3000/some/random/path Is it possible to parse URI of the proxy /some/random/path and basic auth user:pass ? Stuck here, need some help to figure this out...

0xFar5eer commented 2 years ago

This is the test code I use:

use std::time::Duration;

#[tokio::main]
async fn main() {
    let client = reqwest::Client::builder()
        .danger_accept_invalid_certs(true)
        .proxy(reqwest::Proxy::all("http://user:pass@localhost:3000/some/path").unwrap())
        .build()
        .unwrap();
    let rest_request_url = "https://www.test-site.com/foo/bar/123";
    let resp = client
        .get(rest_request_url)
        .timeout(Duration::from_secs(180))
        .send()
        .await;

    println!("{:#?}", resp);
}

This is the parameters output:

req: Request {
    method: GET,
    uri: https://www.test-site.com/foo/bar/123,
    version: HTTP/1.1,
    headers: {
        "accept": "*/*",
        "host": "www.test-site.com",
    },
    body: Body(
        Empty,
    ),
}
ctx: HttpContext {
    client_addr: 127.0.0.1:64685,
}
0xFar5eer commented 2 years ago

Based on auth I would like to throw 407 errors if user is not authenticated. And based on path uri load different settings. Appears these parameters are passed on HTTP1.1 Connect request but I don't see how to handle those here. Can you suggest me any tricks to do that with less blood?

omjadas commented 2 years ago

What you would want to look at would be the Proxy-Authorization header. I think at the moment this would only really work for HTTP (not HTTPS) traffic, since CONNECT requests are not currently passed through the handle_request handler.

async fn handle_request(
    &mut self,
    _ctx: &HttpContext,
    req: Request<Body>,
) -> RequestOrResponse {
    use hudsucker::hyper::{self, http};

    if req.uri().scheme() == Some(&http::uri::Scheme::HTTP) {
        let auth = req.headers().get(hyper::header::PROXY_AUTHORIZATION);

        match auth {
            Some(auth) => {
                todo!("verify auth header");
            }
            None => {
                todo!("407")
            }
        }
    } else {
        todo!();
    }
}

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Proxy-Authorization

In regards to using a path, I don't believe it is possible to specify a path for a HTTP proxy, I assume reqwest would just be discarding it. A few things that could be done would be to have different proxies hosted on different ports, or to use a custom header instead of a path (assuming you are able to add a custom header in your use case).

0xFar5eer commented 2 years ago

What you would want to look at would be the Proxy-Authorization header. I think at the moment this would only really work for HTTP (not HTTPS) traffic, since CONNECT requests are not currently passed through the handle_request handler.

async fn handle_request(
    &mut self,
    _ctx: &HttpContext,
    req: Request<Body>,
) -> RequestOrResponse {
    use hudsucker::hyper::{self, http};

    if req.uri().scheme() == Some(&http::uri::Scheme::HTTP) {
        let auth = req.headers().get(hyper::header::PROXY_AUTHORIZATION);

        match auth {
            Some(auth) => {
                todo!("verify auth header");
            }
            None => {
                todo!("407")
            }
        }
    } else {
        todo!();
    }
}

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Proxy-Authorization

In regards to using a path, I don't believe it is possible to specify a path for a HTTP proxy, I assume reqwest would just be discarding it. A few things that could be done would be to have different proxies hosted on different ports, or to use a custom header instead of a path (assuming you are able to add a custom header in your use case).

Yeah I guess CONNECT handling for https traffic would be nice feature to have.

omjadas commented 2 years ago

Yeah I guess CONNECT handling for https traffic would be nice feature to have.

I have pushed 35aca05 to main, which passes CONNECT requests to the same handle_request handler. I will most likely cut a release in the coming days.

0xFar5eer commented 2 years ago

Perfect thanks! Also could you msg me in telegram http://t.me/Far5eer I have a few questions about possibility to hire you for some rust projects.

Yeah I guess CONNECT handling for https traffic would be nice feature to have.

I have pushed 35aca05 to main, which passes CONNECT requests to the same handle_request handler. I will most likely cut a release in the coming days.

omjadas commented 2 years ago

v0.18.0 has been released which should make this possible to do.

0xFar5eer commented 2 years ago

Is it possible to to hire you part-time for a project based on hudsucker? I am sure you can code it in an a few evenings but I am willing to pay for it :) And I don't want to make public request feature for that.

Can you drop a message to my discord: 0xFar5eer#6504 ?