Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added utls to websocket #1256

Merged
merged 2 commits into from Oct 18, 2022
Merged

Added utls to websocket #1256

merged 2 commits into from Oct 18, 2022

Conversation

HirbodBehnam
Copy link
Contributor

@HirbodBehnam HirbodBehnam commented Oct 15, 2022

Hello again
Well; I added utls this time to websocket which is far more popular than http2 and will be probably more used.

So lemme explain it a little because this pull request contains only additions and some of them are not really obvious. At first, I added a method called WebsocketHandshake to UConn. Why another method is needed? Because both Chrome and Firefox fingerprints have a very small difference depending on if the request is a websocket connection or a simple HTTP request.
Chrome Fingerprint Difference
Firefox Fingerprint Difference
As you can see, the only difference is in ALPN which for websocket, it only contains http/1.1. Apparently, when stablishing a WSS connection, you need to only send http/1.1 in ALPN. But unfortunately, utls library only has normal TLS fingerprints (which is used by HTTP methods). Also, utlsIdToSpec is an unexported function so we cannot use it to get the ClientHelloSpec of browsers. But, there is a function which builds the client hello which is called BuildHandshakeState. Calling this function for the first time results in client hello be built with normal browsers fingerprint; This results in UConn.Extensions to be populated. Next, I iterate over UConn.Extensions to find the ALPNExtension which is used to define the ALPNs and override it with http/1.1 only. If there is no ALPNExtension found (which happens in randomized fingerprint) add one and fill it with http/1.1 as well. At last, I will rebuild the client hello and do the handshake.

For the websocket part itself, I just defined websocket.Dialer.NetDialTLSContext to do something like the one in the websocket.Dialer.NetDial and the one in http package (which I updated in my last pull request). I simply dials the endpoint like the one defined here and then establishes a utls connection with the peer using the new WebsocketHandshake method.

I tested the executable myself and it works fine. Firefox generates this fingerprint and Chrome generates this one. I also tested it with ArvanCloud CDN and my own server and it proxied my traffic.

As a side note, I also like to note that if you don't set the fingerprint key in tlsSettings in config, the old code flow will be executed which means that websocket.Dialer.NetDialTLSContext won't be set and go's normal fingerprint will be used.

Edit: Here is the commit which sets chrome ALPN to http1.1 only: chromium/chromium@db82955

@yuhan6665
Copy link
Member

Thanks for your detailed information and great work! @HirbodBehnam
Will make a version release so that it will be available to all downstream clients :)

@yuhan6665 yuhan6665 merged commit 1f93cbb into XTLS:main Oct 18, 2022
@yuhan6665 yuhan6665 added the good first issue Good for newcomers label Oct 18, 2022
@gaukas
Copy link

gaukas commented Oct 18, 2022

Also, utlsIdToSpec is an unexported function so we cannot use it to get the ClientHelloSpec of browsers.

If that's an issue, we will be happy to export the function. uTLS is meant to export unexported types/funcs in crypto/tls so I don't see a reason why we don't want to export our own functions.

Also, we would welcome any PRs adding new ClientHelloSpec from browsers when websocket is used if they are different (for now I believe there's none). That would be really helpful.

@HirbodBehnam
Copy link
Contributor Author

@gaukas That would be really cool! I think exporting utlsIdToSpec would help us do minor changes to browser fingerprints with ease just like what I did in this pull request.

And for new fingerprints yes, that might be a good idea to add them. I'll have a look and maybe I'll do a pull request ¯⁠\⁠_⁠(⁠ツ⁠)⁠_⁠/⁠¯

@gaukas
Copy link

gaukas commented Nov 1, 2022

Hi @HirbodBehnam, UTLSIdToSpec() has been introduced in refraction-networking/utls#136 and will go live in the next tagged version. Currently we don't have a specific ETA but we are targeting no later than mid-Nov.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants