jromwu / masquerade

An implementation of MASQUE in Rust
45 stars 7 forks source link

Issues encountered while setting up masquerade for HTTP/3 to HTTP/1.1 proxying, and a question about using existing SOCKS5 proxies #2

Open kaykyr opened 1 year ago

kaykyr commented 1 year ago

Hi,

I was looking for a way to proxy my connection with Instagram using a proxy that sends requests over HTTP/3 and returns responses in HTTP/1.1. Is this project intended to serve a similar purpose?

While trying to set up and execute the project, I encountered some issues with the provided code. Here's what happened:

Initially, I executed the server with the following command:

cargo run --bin server -- 127.0.0.1:4433

Then, I executed the client using this command:

cargo run --bin client -- 127.0.0.1:4433 127.0.0.1:8989 http

However, I received an error message that stated:

thread 'main' panicked at 'UDP socket send_to() failed: Os { code: 56, kind: Uncategorized, message: "Socket is already connected" }'

To resolve this issue, I made the following changes to the code:

At line 155 in client.rs:

        let (write, send_info) = conn.send(&mut out).expect("initial send failed"); 
        // while let Err(e) = socket.send_to(&out[..write], send_info.to).await {
        while let Err(e) = socket.send(&out[..write]).await {
            if e.kind() == std::io::ErrorKind::WouldBlock {
                debug!("send_to() would block");
                continue;
            }
            panic!("UDP socket send_to() failed: {:?}", e);
        }
        debug!("written {}", write);

At line 476 in client.rs:

                // match socket.send_to(&out[..write], send_info.to).await {
                match socket.send(&out[..write]).await {
                    Ok(written) => debug!("{} written {} bytes out of {}", conn.trace_id(), written, write),
                    Err(e) => panic!("UDP socket send_to() failed: {:?}", e),
                }

After making this change, the code executed without any errors. Is this approach correct?

Finally, I would like to ask if it's possible to use an existing TCP/SOCKS5 proxy hosted on a remote server as a way to establish a QUIC-encapsulated connection, or if it's only possible to do this using pre-existing interfaces on localhost?

Thank you for your help!

jromwu commented 1 year ago

Hi!

I am not too sure what does it mean by to send requests in HTTP/3 and receive responses in HTTP/1.1. What happens here is we proxy a connection with Instagram (whatever protocol Instagram is using, HTTP/3 or HTTP/1.1), you establish a tunnel:

Instagram client <-HTTP/1.1 or SOCKS5> masquerade client <-HTTP/3-> masquerade server <-> Instagram server
                 <---------------------any protocol Instagram uses---------------------->

where the packets reaching the Instagram server and client are unmodified, so it stays HTTP/1.1 if it uses HTTP/1.1.

The code change looks okay to me. It might be that I tested on a different platform and the socket did let me connect.. I will review and change the code later.

It is definitely possible to host it on a remote server. You would need to replace corresponding the 127.0.0.1 in the command to the IP for the network interface you would like to host it on.

Cheers!

DavidWittman commented 7 months ago

After making this change, the code executed without any errors. Is this approach correct?

Yes, it is correct. From the Tokio docs:

UDP is "connectionless", unlike TCP. Meaning, regardless of what address you've bound to, a UdpSocket is free to communicate with many different remotes. In tokio there are basically two main ways to use UdpSocket:

one to many: bind and use send_to and recv_from to communicate with many different addresses one to one: connect and associate with a single address, using send and recv to communicate only with that remote address