erebe / wstunnel

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

Obfuscate protocol, target and port in request url #169

Closed bluewalk closed 5 months ago

bluewalk commented 7 months ago

Is your feature request related to a problem? Please describe. When using wstunnel in an environment where proxies do MITM scanning (eg SSL stripping and resigning with own certificate) it's clear to the proxy which target and port are targetted from the url wstunnel connects to.

eg: GET https://domain.net/myUpgradePathPrefix/tcp/127.0.0.1/8085 HTTP/1.1 here the proxy is able to easily determine it's a tunnel as the protocol, target and port are visible.

Describe the solution you'd like The ability to have wstunnel obfuscate/encrypt this information with a predefined symmetric key on both client and server.

Describe alternatives you've considered I've already tried randomizing the upgradePathPrefix with a totp token thinking it would make it look more like random visits but on further checking I've noticed the above.

kanran111 commented 7 months ago

These are indeed the features needed to enhance security and prevent monitoring of logs from the router. Currently, running a random upgradePathPrefix seems somewhat pointless because there is the additional prefix like tcp/127.0.0.1/XXX in the URL which very tracking easily.

bluewalk commented 7 months ago

Yes, unfortunately I have zero knowledge of Haskell so I won't be able to create a PR for it. Hoping @erebe would just whip this up in a jiffy 😀

What would even be better is to have wstunnel encrypt all of it's data with a predefined symmetric key or certificate so these kind of proxies and or inspection software can't snoop on the contents either. But encrypting the "connect" path (/tcp/127.0.0.1/8085) would be of great help already. Either encrypted in the URL or as encrypted headers on the request itself.

erebe commented 7 months ago

Hello,

Thank you for taking the time to correctly describe your issue and what you tried :)

Regarding the question, is this a real case scenario you encountered, or is it just a theoretical one ? If it is a real case, can you describe in which context you encountered it ?

For the feature request, I am working on a complete rewrite in Rust of the project, so I am going to take the feature into account :) Regarding an ETA, with the current spare time I have ATM, don't expect a release before the end of the year.

bluewalk commented 7 months ago

Thank you for taking the time to correctly describe your issue and what you tried :)

😃

Regarding the question, is this a real case scenario you encountered, or is it just a theoretical one ? If it is a real case, can you describe in which context you encountered it ?

Yes, there are companies that use services to filter internet traffic. They do this by stripping the SSL and inspect the traffic, after which they sign it again using their own CA. This would also include traffic when you surf in your private time during your (lunch) break like your own webmail, WhatsApp, Twitter etc.

Thus I use wstunnel to encapsulate traffic to my server. But as it turned out when I was checking the traffic, the tunnel-connect-information is readable in the http/https request, hence my proposal to have that encrypted.

For the feature request, I am working on a complete rewrite in Rust of the project, so I am going to take the feature into account :) Regarding an ETA, with the current spare time I have ATM, don't expect a release before the end of the year.

Oh that sounds sweet. Looking forward to it!

erebe commented 7 months ago

Thank you for the explanation, going to add that :)

bluewalk commented 7 months ago

Great to hear, if you need beta testing you can shoot me a message :)

kanran111 commented 7 months ago

Yes, there are companies that use services like ZScaler and Barracuda Web Security and Filtering to filter internet traffic. They do this by stripping the SSL and inspect the traffic, after which they sign it again using their own CA. This would also include traffic when you surf in your private time during your (lunch) break like your own webmail, WhatsApp, Twitter etc.

Not my bussiness, but if they do that, it seems like they can be read all the chat messages through chat apps of client not end-to-end encrypted right?

erebe commented 7 months ago

@kanran111 pretty much yes, it means also they have their certificate authorized on your devices. Which is widely common on big corp where your devices trust company CA. At that point, you don't have many options left beside adding another layer of encryption/obfuscation.

If I understand correctly the request, @bluewalk just wants to for the websocket request to look normal, to avoid him being flagged as someone bypassing security/tunneling traffic. In the case he tunnels secure traffic (i.e: https), transmitted data would be fine/still secure, but the websocket request still cries loudly he is tunneling traffic

bluewalk commented 7 months ago

@kanran111 You are correct, when it's end-to-end encrypted then no. If it's just HTTPS traffic then they can see all the plain data as if were HTTP traffic. Hence my question of adding another layer of encryption/obfuscation to the websocket connection initialization.

I can make sure the traffic flowing through the websocket tunnel is encrypted, yet the requests made to initialize the tunnel are unrecrypted/unobfuscated. Companies/Regimes can detect it and then flag or block it.

@erebe

If I understand correctly the request, @bluewalk just wants to for the websocket request to look normal, to avoid him being flagged as someone bypassing security/tunneling traffic. In the case he tunnels secure traffic (i.e: https), transmitted data would be fine/still secure, but the websocket request still cries loudly he is tunneling traffic

Yes exactly😊

erebe commented 7 months ago

Hi back @bluewalk,

I made a complete rewrite of wstunnel, would you mind giving this version a shot ? https://github.com/erebe/wstunnel/releases/tag/v7.0-rc1

The only feature missing ATM is the ability to connect to a proxy

bluewalk commented 7 months ago

HI @erebe,

Great! I will test it after work today, as at work I need to use a proxy there.

I see you have used JTW tokens and a /events endpoint, that's a nice solution yet it would still be readable (with jtw.io for example) but less likely to trigger anything :) One more thing that would be nice is to specify the key (on server and client with a parameter) instead of a hardcoded key.

bluewalk commented 7 months ago

I've tested it and so far seems very intuitive, would love to have the verbose logging to troubleshoot as we have in v6. Once it has proxy support I can test it at work as well.

Maybe add a link for donations too, cause great work! 😉

erebe commented 7 months ago

You can get the verbose log, if you start the program with the env variable RUST_LOG=debug wstunnel ..., you will get plenty of logs :)

But good catch, I will try to make it the default !

bluewalk commented 7 months ago

But good catch, I will try to make it the default !

It doesn't have to log like mental by default though but info logs should be good to have :-)

Looking forward to proxy support!

erebe commented 7 months ago

It is now available in the latest release https://github.com/erebe/wstunnel/releases/tag/v7.0.0 :)

bluewalk commented 7 months ago

Hi, you work fast! I've just tested the proxy but there seems to be an error.

Starting with proxy pointing to localhost:4321 (proxie on macos). The client seems to be connecting to the IP of the target but with the port of the proxy.

./wstunnel client wss://myhost.net/ --http-upgrade-path-prefix someupgradeprefix -L tcp://8085:127.0.0.1:8085 -p http://localhost:4321

2023-10-21T15:49:10.322022Z INFO wstunnel::tcp: Starting TCP server listening cnx on 127.0.0.1:8085
2023-10-21T15:49:12.938077Z INFO tunnel{id="018b52ed-1c69-70f2-9ba9-9ab317044c46" remote="127.0.0.1:8085"}: wstunnel::tcp: Opening TCP connection to mywebhost:4321
2023-10-21T15:49:12.940366Z DEBUG tunnel{id="018b52ed-1c69-70f2-9ba9-9ab317044c46" remote="127.0.0.1:8085"}: wstunnel::tcp: connecting to ipofhost:4321 2023-10-21T15:51:51.006718Z ERROR tunnel{id="018b52ef-5ec7-7544-a7bf-9b6c5c14cd12" remote="127.0.0.1:8085"}: wstunnel: Cannot connect to tcp endpoint myhost.net:4321 reason None

Not specifying the proxy works as expected, it connects to port 443.

Shouldn't this line point to proxy_host instead of host https://github.com/erebe/wstunnel/blob/ef738d5bae221f19fc6bfef05ff388c69ed84dcf/src/tcp.rs#L116

erebe commented 7 months ago

Indeed you are right, fixing it :)

erebe commented 7 months ago

New release https://github.com/erebe/wstunnel/releases/tag/v7.1.0

bluewalk commented 7 months ago

Yes works as expected, traffic also looks way less suspicious, great work! 👍 You should definitely add a donate link somewhere.

erebe commented 7 months ago

I have added one on the readme :)

ko-fi

bluewalk commented 7 months ago

Great, get some coffee on me 💪🏻

kanran111 commented 7 months ago

I have added one on the readme :)

ko-fi

Me too, You're doing very well, keep it up bro!

kanran111 commented 6 months ago

I just noticed that your new bearer token string is using JWT encryption without a passphrase. It can be easily decrypted. Is there an option to set a passphrase for this? Another option is to use OpenSSL encryption with passphrase image

bluewalk commented 6 months ago

@kanran111 As far as I know JWT token are always readable by design. They are signed with a password/passphrase (the third part of the token when split by a period is the signature) to verify if it's been modified.

https://auth0.com/docs/secure/tokens/json-web-tokens

You are right Although JWTs can also be encrypted to provide secrecy between parties, might be a nice addition with a passphrase we can set with a parameter :)

kanran111 commented 6 months ago

@kanran111 As far as I know JWT token are always readable by design. They are signed with a password/passphrase (the third part of the token when split by a period is the signature) to verify if it's been modified.

https://auth0.com/docs/secure/tokens/json-web-tokens

You are right Although JWTs can also be encrypted to provide secrecy between parties, might be a nice addition with a passphrase we can set with a parameter :)

yep, i use jwt to encrypt my api token.

bluewalk commented 6 months ago

@erebe @kanran111 mentioned JWE tokens (encrypted JWT), this would definitely be a nice addition to make sure the token cannot be read. Especially if we can specify the key/passprhase ourselves with a parameter 💪🏻

kanran111 commented 6 months ago

@erebe @kanran111 mentioned JWE tokens (encrypted JWT), this would definitely be a nice addition to make sure the token cannot be read. Especially if we can specify the key/passprhase ourselves with a parameter 💪🏻

That's right, and it will also prevent someone from trying to connect to my wstunnel without knowing the password.

erebe commented 6 months ago

I was not aware of JWE, that's something I can add I guess. But you know at some point, if all you see is encrypted data while it should not be, it is fishy too.

Going to take a look at JWE

P.s: Regarding prevent someone from trying to connect to my wstunnel you can already do that with the upgrade path prefix and forcing the server to match your secret path.

bluewalk commented 6 months ago

But you know at some point, if all you see is encrypted data while it should not be, it is fishy too.

I agree, it's not common to use JWE tokens, if you're adding it; you can make it optional. For instance when no key/passphrase is supplied then use normal JWT, otherwise JWE.

kanran111 commented 6 months ago

I was not aware of JWE, that's something I can add I guess. But you know at some point, if all you see is encrypted data while it should not be, it is fishy too.

Going to take a look at JWE

P.s: Regarding prevent someone from trying to connect to my wstunnel you can already do that with the upgrade path prefix and forcing the server to match your secret path.

That's right. However, I'm forwarding the service port on the VPS because my service provider doesn't allow it. I'm concerned that someone might peek into the traffic and attempt to decrypt it when they see the service port, which could pose challenges for me

bluewalk commented 6 months ago

If you enable SSL verification (--tls-verify-certificate) you will know when someone is peeking. Unless you are in a situation where your employer/ISP does SSL stripping and resigning for inspection like I mentioned earlier.

kanran111 commented 6 months ago

If you enable SSL verification (--tls-verify-certificate) you will know when someone is peeking. Unless you are in a situation where your employer/ISP does SSL stripping and resigning for inspection like I mentioned earlier.

i mean they just look into URL of request and decrypt it, cause bearer stay into URL too 👯 , and when they decrypt it, maybe i got some trouble. image

bluewalk commented 6 months ago

Correct, but you can only see the URL when you are either using plain HTTP or are doing SSL stripping. When using SSL (HTTPS) the service provider can only see the IP and at most the SNI.

In order to do SSL stripping they will also need to resign the traffic with a certificate you most likely don't trust, hence the --tls-verify-certificate. Unless you have no choice and have to accept the self signed cert or corporate ca-cert; then they can see the bearer token and JWE could come in handy.

kanran111 commented 6 months ago

Correct, but you can only see the URL when you are either using plain HTTP or are doing SSL stripping. When using SSL (HTTPS) the service provider can only see the IP and at most the SNI.

In order to do SSL stripping they will also need to resign the traffic with a certificate you most likely don't trust, hence the --tls-verify-certificate. Unless you have no choice and have to accept the self signed cert or corporate ca-cert; then they can see the bearer token and JWE could come in handy.

My mistake, I thought that requests passing through the firewall would expose the entire URL and only encrypt the headers and body. Thank you for clarifying this.