erebe / wstunnel

Tunnel all your traffic over Websocket or HTTP2 - Bypass firewalls/DPI - Static binary available
Other
3.22k stars 290 forks source link

[Feature Request] Add TPROXY UDP and TCP listening on local #106

Closed cattyhouse closed 5 months ago

cattyhouse commented 2 years ago

Right now, wstunnel has socks5, sni, host-headers support, that is great. to make it even greater, is it possible to add tproxy support? to me wstunnel is a much simplified version of v2ray (the tcp+tls+ws mode), which is the only thing i am interested to bypass the great fire wall.

with tproxy, we can :

  1. setup iptables rules to do traffic dispatch based on dest ip addr via ipset
  2. setup iptables rules to specify which dest ports to go through wstunnel
  3. all transparent to users, so we don't need to use curl -x socks5://... just curl

tproxy docs , from kernel.org tproxy use case, tproxy is already supported by shadowsocks-libev, v2ray and trojan-go. tproxy to socks5 convert tools, this can be used with current version of wstunnel, but if wstunnel has native tproxy support, it would be great.

note, that the UDP is a little bit special, to make FULL CONE UDP work, there may also need some changes on wstunnel server, some kind of map, i don't know, i am not a programmer.

thank you.

erebe commented 2 years ago

Hello, Wasn't aware of tproxy protocol, going to look into it :) But I have little free time to spend on this project at the moment so, don't be hyped too much ^^

cattyhouse commented 5 months ago

since now it is written in rust, can you add tproxy listenning? thanks

erebe commented 5 months ago

Hello,

Yes it is in my todo, I have some stuff to finish first for reverse tunneling, and after I am going to work on it.

cattyhouse commented 5 months ago

Thank you very much.

erebe commented 5 months ago

So I had a look regarding how to implement it.

For tcp tproxy, it should be rather easy to add, mostly glue. For udp, it would require more much more work because at the moment wstunnel udp server is cross-platform, and sadly there is no way to retrieve udp destination address from a packet in an OS agnostic way.

I will start by adding transparent tcp tproxy, I will see after for the udp version.

erebe commented 5 months ago

Would you mind trying this release https://github.com/erebe/wstunnel/releases/tag/v8.1.0 and let me know if it is ok for you ? (it only supports TCP transparent proxy for now)

client -L 'tproxy+tcp://[::1]:1212' ....
cattyhouse commented 5 months ago

Thank you. my current iptables rules involve both TCP and UDP TPROXY. The UDP part is mainly used for proxying DNS and QUIC traffic( like YOUTUBE app).

i think i can test TCP DNS (DNS OVER TLS or DNS OVER HTTPS) and TCP https (proxying https:// websites) for now. I'll report back when i finish the test.

cattyhouse commented 5 months ago

result:

tcp tproxy works great, looking forward to udp support, thanks.

client

./wstunnel client -L 'tproxy+tcp://127.0.0.1:1999' --http-upgrade-path-prefix vaQ0fBMSHiRZhXkm8zRI --tls-verify-certificate --tls-sni-override mydomain wss://myip:8443
tproxy rules like mentioned in kernel.org page
# dig doh/tcp test

dig @1.1.1.1 +https google.com
curl checkip.amazonaws.com # shows my server ip

server

./wstunnel server --restrict-http-upgrade-path-prefix vaQ0fBMSHiRZhXkm8zRI --tls-certificate ./my_ecc.crt --tls-private-key ./my_pkcs8.key wss://0.0.0.0:8443

some notes:

on server side, if the private key is in ECC format, like key generated by Caddy auto https. i have to convert it to pkcs8 format

openssl pkcs8 -topk8 -nocrypt -in ECC.key -out pkcs8.key
erebe commented 5 months ago

Would you mind retrying https://github.com/erebe/wstunnel/releases/tag/v8.1.0, I have added support for transparent proxy for UDP.

./wstunnel client -L 'tproxy+udp://127.0.0.1:1999'  -L 'tproxy+tcp://127.0.0.1:1999' 

P.s: I will look into the ECC format

cattyhouse commented 5 months ago

I did a cross compilation on macOS targeting linux x84_64 using cargo-zigbuild, and the binary results 4.9M, both TCP and UDP tproxy work great.

Btw, Cargo.toml under profile.release, there is a debug=1, while rust official docs say it defaults 0.

erebe commented 5 months ago

Perfect :fireworks: :partying_face:

I made a final release here https://github.com/erebe/wstunnel/releases/tag/v8.1.1

Regarding the debug=1, it is on purpose. Without it, it is impossible to troubleshoot the crash a user may encounter, as there will be no stack trace. Feel free to strip the binary to remove them if needed.

cattyhouse commented 5 months ago

got it, thank you, i'll close this for now.

erebe commented 5 months ago

You should be able to load your EC private key now with release https://github.com/erebe/wstunnel/releases/tag/v8.2.1

leonixyz commented 1 month ago

@cattyhouse could you please provide some more information about your setup?

I'm struggling to make it work in tproxy+tcp mode for a local application. The problem with the kernel docs is that it relies on adding rules to PREROUTING in mangle, which is only evaluated for non-local traffic.

I was able to redirect local traffic into the tunnel, running on the same machine originating the traffic, by adding this rule:

iptables -t nat -A OUTPUT -p tcp -m tcp --dport 12345 -j REDIRECT

and indeed I see the traffic entering the tunnel correctly:

On the client I see a full TCP handshake.

The problem is that on the server I see the traffic exiting from the tunnel already with 127.0.0.1 as source IP.

I assume you don't, disregarding the fact that you tunnel routed, non-local, traffic. Could you please confirm? And if not so, next question would be to @erebe: do you think it would be possible, and would you accept a pull request to allow also the server mode to (optionally) fully deal with tproxied traffic, by ensuring exiting packets have the same src ip as the had when they entered?

thanks in advance


edit:

I add some more detail about my setup:

how I run the client:

# wstunnel client -L tproxy+tcp://12345 ws://my-remote-host.com:80

and the server:

# wstunnel server  ws://0.0.0.0:80