Browser support of TCP proxy

rust-tcp-proxy/main.rs at master · hishboy/rust-tcp-proxy · GitHub Can browsers, e.g., Firefox, Chrome, Edge, etc, use http, https, or socks protocol to connect to that proxy? Does it need system firewall or else to forward browser traffic?

Most browsers support setting a proxy. How you do this depends on the browser you use. For example in firefox you can go to preferences and then in the search bar type "proxy".

I'm unfamiliar with OSI network layers, so I'm not sure whether TCP proxies can forward http and https connections. After I read some resources of OSI layers, I'm still confused about whether that TCP proxy is transparent proxy or not.

Be careful TCP/IP does not adhere to the OSI model much. It rather takes OSI as a suggestion.

Proxy hides the source IP address, so the website can only see the proxy's IP address. How to modify source IP address and get destination address in Rust?

If you are lucky the proxy set an http header to indicate the origin. If not and the proxy either sets it to a fake value or not at all, you are out of luck unless you are either three letter governement agency that can correlate traffic going in and out of the proxy or illegally manage to hack the proxy.

It seems you misunderstood my question.

How to modify source IP address and get destination address in Rust?

I asked how to modify source address, this is to develop a proxy in Rust, not to hack any proxy. Since proxy forwards user traffic to websites, I asked how to see the destination so it can forward the traffic. So my question is how to develop a Rust proxy, not to hack proxy.

You mean you want the proxy to present a different ip address for packets it sends? For that I think you will need to run as root/admin and use a tun or tap device to send raw ip packets. Maybe some OSes have an ip to do it using a regular socket, but you almost definitively need root/admin permission even in that case.

I think I misunderstood the question again. If you want to know the remote address of a TcpStream you can use the peer_addr() method. For the local address there is local_addr(). If you are writing an HTTP or SOCKS proxy, then you have to get address the client wants to connect to from this protocol. For example for an HTTP proxy the client would start with for example CONNECT www.example.com:443 HTTP/1.1 and in the request body put whatever they want to send to www.example.com:443, while in SOCKS the first packet contains the destination ip addr and port.

The 24th line of rust-tcp-proxy/main.rs at master · hishboy/rust-tcp-proxy · GitHub contains .map(|to_stream|, what's the input type from TcpStream::connect(to_addr) to .map? And what type does to_stream have?

If you need a proxy for developing check Burp Suite.

Rust-tcp-proxy uses Arc. Is it possible to develop a proxy without Arc?

Yes, when using scoped threads instead of std::thread::spawn.

No. Because you need &mut reader and &mut writer.
The writer and the reader aren't copyable.
You have to use a reference-counted pointer.

Read and Write are actually implemented for &TcpStream too. Not just TcpStream.

Is it achievable with single thread? I tried to use single thread, but get error "connection reset by peer", "broken pipe", or "timeout".

Do peek(), write_all(), and flush() methods on TcpStream wait until the connection closed? Since when I tried to use single thread, it returns "timeout" error in some cases, I suspect that some methods wait until the connection closed.

They wait until the operation is done, which may wait on the other end of the connection reading. This in turn can be blocked on the other end of the connection finishing a write operation, which requires the local end to finish reading, which is a deadlock if you only use a single thread without asynchronous IO.

(post deleted by author)

If a Mutex was held by thread A, then thread B successfully acquire that Mutex, will thread A automatically hold that Mutex after thread B finishes operations? Does it need a loop to always try acquiring? E.g.,

let a = Mutex::new(vec![]);

After that,

loop{
    let a = a.lock().unwrap();
    //do something
}