GithubHelp home page GithubHelp logo

omjadas / hudsucker Goto Github PK

View Code? Open in Web Editor NEW
189.0 12.0 33.0 312 KB

Intercepting HTTP/S proxy

Home Page: https://crates.io/crates/hudsucker

License: Apache License 2.0

Rust 100.00%
proxy http man-in-the-middle tls ssl websocket rust

hudsucker's People

Contributors

dependabot[bot] avatar glossiness avatar omjadas avatar wabscale avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hudsucker's Issues

Im totally planning on using this!

Hey there @omjadas, thank you for this! I'm totally planning on using this in a project of mine and will report back. Perhaps this is just useless noise, but IDK I often like to know if stuff I'm making out of the goodness of my heart is being used...so now you know! Just a hobby project mind you, but still. Super cool that you built/are building something like this!

v0.18.0 not found on crates.io

hi, i'm sorry but i'm very noob with rust so i think that this is a stupid question

i'm trying to use hudsucker; i put hudsucker = "0.18.0" on my Cargo.toml, but running cargo build i get

Updating crates.io index
error: failed to select a version for the requirement `hudsucker = "^0.18.0"`
candidate versions found which didn't match: 0.16.1, 0.16.0, 0.15.0, ...
location searched: crates.io index

it works using 0.16.1

what am i doing wrong?

thanks in advance

[Feature] Selective MITM

When using the proxy provided by hudsucker, all https requests will use the certificate issued by hudsucker. However, usually most of our requests may not need to be processed through hudsucker, so I suggest adding some option for selective MITM.

My idea is that the user of your crate could pre-provide a list of hosts and only mitm requests corresponding to the hosts in that list.

Or a more flexible way, let the user provide some kind of judgment method closure, and pass in the req to determine if it should be forwarded directly or need to mitm.

I believe that selective mitm will improve the overall performance when using hudsucker's proxy.

Offer to update readme with refering to other project

Hello, @omjadas !
I maintain my own open source project, you can find it here. My project relies on your library, so, first of all, I want to express my gratitude to you for this cool library.
I would like to offer you to refer my project in readme of yours (or in any other way) as example of software that uses your library. You also can find that I have already referred your project in readme of mine.
I believe that this can help me to find some contributors and keep improving the project.
I would appreciate any feedback.

How to get the original data of Response body?

Thank you for making such a great box. I just learned Rust. I want to get the raw body data of the response based on this. I'm using example/log.rs. Printed res displays the body value as Body (Streaming). For example, when the content-type is application/json, I need to get the original json data. How can I decode it into raw data? Hope you can give me a complete example, thank you!

Response { status: 200, version: HTTP/2.0, headers: {"content-length": "1347", "content-type": "application/json; charset=utf-8", "etag": "229858941_501691865", "strict-transport-security": "max-age=2592000", "x-content-type-options": "nosniff", "x-exp-trackingid": "40508587-0516-427b-a2c9-e02a22506ce6", "x-cache": "CONFIG_NOCACHE", "access-control-allow-origin": "*", "x-msedge-ref": "Ref A: B0BD5EC4DAC04E828DCBCFD3F4E9DAD6 Ref B: TYO01EDGE2009 Ref C: 2023-09-24T13:33:31Z", "date": "Sun, 24 Sep 2023 13:33:30 GMT"}, body: Body(Streaming) }

[Feature Request] Upstream Proxy

I noticed that this crate supports upstream proxy before in b7a2136

But it was removed in 408999b

This is a very useful feature and might be worth it to bring it back?

I would like to propose a more flexible design instead of the original implementation by adding this to HttpHandler which will give an option to route traffic based on request or rotate from a list of upstream proxies

pub trait HttpHandler: Clone + Send + Sync + 'static {

    async fn get_upstream_proxy(&mut self, _ctx: &HttpContext, _req: &Request<Body>) -> String {
       // return upstream URL string here
    }
}

Cargo bech does not build

Hi,
i just clone the repo and cargo bench does not build.


error[E0433]: failed to resolve: use of undeclared crate or module `hyper_tls`
  --> benches/proxy.rs:94:49
   |
94 | fn native_tls_client() -> hyper::client::Client<hyper_tls::HttpsConnector<HttpConnector>> {
   |                                                 ^^^^^^^^^ use of undeclared crate or module `hyper_tls`
   |
help: there is a crate or module with a similar name
   |
94 | fn native_tls_client() -> hyper::client::Client<hyper_rustls::HttpsConnector<HttpConnector>> {
   |                                                 ~~~~~~~~~~~~

error[E0433]: failed to resolve: use of undeclared crate or module `hyper_tls`
   --> benches/proxy.rs:106:16
    |
106 |     let https: hyper_tls::HttpsConnector<HttpConnector> = (http, tls).into();
    |                ^^^^^^^^^ use of undeclared crate or module `hyper_tls`
    |
help: there is a crate or module with a similar name
    |
106 |     let https: hyper_rustls::HttpsConnector<HttpConnector> = (http, tls).into();
    |                ~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0433`.
error: could not compile `hudsucker` due to 2 previous errors

When I change cargo.toml line 62 from
rustls-client = ["dep:hyper-rustls", "tokio-tungstenite/rustls-tls-webpki-roots"]
to
rustls-client = ["dep:hyper-rustls", "dep:hyper-tls", "tokio-tungstenite/rustls-tls-webpki-roots"]

cargo bench builds (I am not sure if it is a proper fix though as I am a begginer).

CertificateUnknown error occured when running the log.rs

Hi man, thank you for your project first.

But I'm stucked when running the log.rs in your examples directory.

I just copy src/example/log.rs to src/main.rs and src/example/ca to src/ca and add env_logger = "0.9" to [denpendencies] and then cargo run.

After install the hudsucker.pem to my computer ( Trusted Root Certification Authorities ) and setting my web proxy to 127.0.0.1:3000 , I got the error log:

thread 'tokio-runtime-worker' panicked at 'Failed to establish TLS connection with client: Custom { kind: InvalidData, error: AlertReceived(CertificateUnknown) }', C:\Users\forti\IdeaProjects\hudsucker\src\proxy.rs:137:30 [2021-11-03T05:46:55Z ERROR rustls::session] TLS alert received: Message { typ: Alert, version: TLSv1_3, payload: Alert( AlertMessagePayload { level: Fatal, description: CertificateUnknown, }, ), }

Waiting for your response, thank you.

[Bug] Lack of appropriate CN in site's certificates signed with RCgen CA

Hello!
The issue is pretty simple. If certificate for a site created with OpensslAuthority, this authority sets CN to DNS name of site: https://github.com/omjadas/hudsucker/blob/main/src/certificate_authority/openssl_authority.rs#L74

But RcgenAuthority does not do that, it places DNS name only in Alt Names: https://github.com/omjadas/hudsucker/blob/main/src/certificate_authority/rcgen_authority.rs#L85

This issue leads to browsers reject certificates signed with RcgenAuthority, because there is no appropriate CN.

I would like to request a fix for this, please. Probably, I could do a pull-request, but I have not enough free time :(

[Feature] Use type Option for handler

In the current version, we need to pass three handlers to use hudsucker, including http_handler, incoming_message_handler and outgoing_message_handler.

I think many times the user may not need to handle everything and can use Option type, the user only needs to use Some to specify what needs to be handled and just pass None for things that are not of concern.

This would require the hudsucker to determine if the request or response is need to be handled by the user function, but I believe it would be more user friendly and flexible for crate users. And in this way, the example does not need an additional NoopHandler.

How to obtain the request URI address in `HttpHandler::handle_response`?

I was giving it a try today and was quite curious if it was possible to have the request's URI address available in HttpHandler::handle_response. It looks like the Response type used is a hyper::Response, which doesn't contain any information about the URI. Is there a way to obtain it? It's fairly handy to have that information available also while handling responses (for filtering, for rexample).

In the proxy implementation, where HttpHandler::handle_response is called, looks like Request (which contains the URI) information is readily available, I'd be happy to provide a PR if needed.

Great work, by the way, it was super easy to set it up and start working with it. Thanks!

MITMing HTTPS requests

Is there an example for MITMing HTTPS requests without ever hitting the original web server? If I just create a new response in the handle_request I get a generic "connection closed" error. I did a bit of digging through your code and I tried returning an empty response for CONNECT requests but that also didn't help. I'm assuming I'm missing something simple.

Thanks!

Cargo audit failure due to tungstenite dependency

I get the following high severity audit failure due to hudsucker's dependency on a vulnerable version of tungstenite:

Crate:     tungstenite
Version:   0.19.0
Title:     Tungstenite allows remote attackers to cause a denial of service
Date:      2023-09-25
ID:        RUSTSEC-2023-0065
URL:       https://rustsec.org/advisories/RUSTSEC-2023-0065
Severity:  7.5 (high)
Solution:  Upgrade to >=0.20.1
Dependency tree:
tungstenite 0.19.0
├── tokio-tungstenite 0.19.0
│   ├── hyper-tungstenite 0.10.0
│   │   └── hudsucker 0.20.0
│   │       └── <my component>
│   └── hudsucker 0.20.0
└── hyper-tungstenite 0.10.0

error: 1 vulnerability found!

It seems like the latest release of hyper-tungstenite uses a fixed version of tungstenite, so it would be good if hudsucker could be updated to resolve the security issue.

How to do something after streaming body?

This is a noob question, not really an issue. I'm trying to stream a response and then do stuff after that finishes. Specifically (for now) I'm computing a sha256 of the response body, and need to call finalize(). Here's one attempt to do that: https://github.com/nlevitt/warcprox-rs/blob/master/src/main.rs
You can run this with cargo run and in another terminal execute for example curl -k -gvsS --proxy http://127.0.0.1:8000 https://example.com/.
The problem is that the None case in poll_next() is never called.

It would be even nicer to be be able to chain some sort of finally to the end of the body stream, but I'm not sure if that's possible. https://github.com/nlevitt/warcprox-rs/blob/stream-combinators/src/main.rs#L63

How to modify response body?

Could you please tell me how to modify the response?

I tried to get the specific content of the body in the closure and convert it to a string, but now I can't await it in the closure.

Handle Specific Response?

I need to intercept a response from a specific url, I tried to do this multiple ways the only way I found was to get the request from the specific URL and then use reqwest copy the request into a reqwest request then send it through reqwest client then convert the response to a hyper::Response then return req.into(), in Golang with mitmproxy-go this would be super simple id just match the URL and get the response easily, is there a better way to do this?

Access to the open websockets

I'd appreciate it if there was something like with_connects_collector that takes a Vec(for example) and uses it to store client/server connections to allow not only processing but also sending user data packets.

Failed to establish TLS connection:

hello,i have some problems,when the req.uri have https.it will be successes,but if the uri like this , p1.music.126.net:443,it will fail.
this is my error log

2023-08-21T14:36:32.567413Z ERROR proxy{version=HTTP/1.1 method=CONNECT uri=p1.music.126.net:443 client_addr=192.168.137.116:63216}:process_connect: hudsucker::proxy::internal: Failed to establish TLS connection: tls handshake eof
2023-08-21T14:36:32.582093Z ERROR proxy{version=HTTP/1.1 method=CONNECT uri=p1.music.126.net:443 client_addr=192.168.137.116:63217}:process_connect: hudsucker::proxy::internal: Failed to establish TLS connection: tls handshake eof
2023-08-21T14:36:32.606450Z ERROR proxy{version=HTTP/1.1 method=CONNECT uri=p1.music.126.net:443 client_addr=192.168.137.116:63218}:process_connect: hudsucker::proxy::internal: Failed to establish TLS connection: tls handshake eof
2023-08-21T14:36:32.690224Z ERROR proxy{version=HTTP/1.1 method=CONNECT

all of these uri contain :443 will be failed,how to deal this,thanks😊

[feature request] Use anonymous function as handler parameter

Thanks for your crate

My use case is that when I use with_http_handler/with_incoming_message_handler/with_outgoing_message_handler, I want to store the request & response. In the current case, it looks like the only way to store it is to create global mutables using something like lazy_static. Switching to anonymous functions we can easily create Arc<Mutex<>> in any context to store the data. what do you think about this?

[Feature Request] Add context for Proxy

Sometimes we need to determine the request and then modify the response.

In this case, there is a need to have a context to synchronize some data that is obtained from the request and then use them when modifying response.

I think we can add a context struct to struct Proxy, and pass its borrow to both requestHandler and responseHandler closures along with the req or res.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.