Open stuart-mclaren opened 1 year ago
In current design, the TCP port for transparent proxy also serve as SOCKSv5 server. Is it possible to distinguish connections that redirected by firewall and connections that direct to the port in FreeBSD? If it's a direct connection, pass it to SOCKS handshaking procedure.
Thanks for your feedback.
Looking at the ipfw man page (https://www.freebsd.org/cgi/man.cgi?ipfw(8))
For packets forwarded locally, the local address of the socket will be set to the original destination address of the packet.
I think this means that, in principle, we can distinguish between firewall redirected packets and direct connections.
Adding some debug to the code
while let Some(sock) = clients.next().await {
println!("sock is {:?}", sock);
and running
$ curl 216.58.193.142:80
produced this log output
sock is Ok(PollEvented { io: Some(TcpStream { addr: 216.58.193.142:80, peer: 10.0.0.1:62950, fd: 10 }) })
listeners: 127.0.0.1:2080 # Address for listeners[0].0.local_addr().unwrap())
Note: addr has been set to 216.58.193.142:80 as per the man page.
This is different to a direct connection, eg
$ curl localhost:2080
sock is Ok(PollEvented { io: Some(TcpStream { addr: 127.0.0.1:2080, peer: 127.0.0.1:10825, fd: 10 }) })
listeners: 127.0.0.1:2080 # unchanged
Note that addr is unchanged (127.0.0.1:2080) because it hasn't been affected by the firewall.
So (hopefully) something like this would work (pseudo code):
if not (listener.ipv4_addr == sock.ipv4_addr and listener.port == sock.port) {
// ipfw NAT detected
}
But if it's bind on 0.0.0.0
or ::
rather than a specific address…
I start feeling that reusing the socket for SOCKS proxy is a mistake from the beginning. I should at least give a CLI switch for it.
FreeBSD's ipfw firewall does not rewrite the destination IP address when forwarding using rules such as:
00100 fwd 127.0.0.1,2080 tcp from me to not me 80,443
This commit adds ipfw support by assuming transparent redirection on freebsd. If you create the above rule and point moproxy at a http proxy at IP address 1.2.3.4
$ moproxy -b 127.0.0.1 -p 2080 -t 1.2.3.4:8080
You can fetch remote 443 or 80 ports without setting proxy environment variables, eg:
$ curl https://example.com:443
...