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

Interstitial pages now breaking websockets #749

Closed
arenasys opened this issue Sep 15, 2024 · 7 comments
Closed

Interstitial pages now breaking websockets #749

arenasys opened this issue Sep 15, 2024 · 7 comments

Comments

@arenasys
Copy link

Previously I could proxy a websocket server through a public zrok share and connect to using client side JS in the browser. Since a month or so ago this no longer works, on firefox I see ns_error_websocket_connection_refused. Connecting still works fine outside the browser, so i assume this is a CORS problem? Any way to fix this?

@arenasys
Copy link
Author

arenasys commented Sep 15, 2024

Minimal reproduction using the python websockets package. Python client works fine, Web client only works when connecting locally, but not through Zrok.

Zrok command:

zrok share public localhost:28888 --headless

Python server:

import websockets.sync.server

def handle_connection(connection):
    connection.send("server hello")
    print("RECV", connection.recv())
    connection.close()

server = websockets.sync.server.serve(handle_connection, host="127.0.0.1", port=28888)
server.serve_forever()

Python client:

import websockets.sync.client

endpoint = "wss://blahblah.share.zrok.io" #"ws://127.0.0.1:28888"
client = websockets.sync.client.connect(endpoint)
print("RECV", client.recv())
client.send("client hello")
client.close()

Web client:

<script>
var endpoint = "wss://blahblah.share.zrok.io"; //"ws://127.0.0.1:28888"
ws = new WebSocket(endpoint);
ws.onopen = function() {
    ws.send("web client hello")
}
ws.onmessage = function(event) {
    console.log("RESV", event.data)
}
ws.onerror = function(event) {
    console.log("ERROR", event)
}
</script>

@michaelquigley
Copy link
Collaborator

michaelquigley commented Sep 15, 2024

Nothing has changed with regards to anything HTTP headers or CORS related in zrok in months. The production zrok instance at zrok.io rolled out the interstitial pages feature approximately a month ago, so you're probably running into that.

In your websocket client, add the header skip_zrok_interstitial set to any value and I would bet you'll be working again.

Alternatively, if you use a User-Agent starting with a string other than Mozilla/5.0 you can also bypass the interstitial page.

There's an office hours video on some of the rationale involved with this. Long story short... there has been a bunch of phishing and fraud that has required the production zrok instance to introduce interstitial pages on free accounts. Upgrading to any paid account or using private shares eliminates the interstitial.

https://www.youtube.com/watch?v=NYjec5mIXTE

@michaelquigley
Copy link
Collaborator

That's also why the Python client works fine... It's using a User-Agent that doesn't start with Mozilla/5.0, bypassing the interstitial.

@arenasys arenasys changed the title CORS now breaking websockets Interstitial pages now breaking websockets Sep 16, 2024
@arenasys
Copy link
Author

Can confirm the python client fails with:

client = websockets.sync.client.connect(endpoint, user_agent_header="Mozilla/5.0")

However I cannot set the user agent or that header in browser side JS. So safe to say free zrok no longer works for my use case?

@michaelquigley
Copy link
Collaborator

Public shares on the hosted version of zrok will no longer work, no. You can still take advantage of private shares, and potentially self-host a frontend for your application, all on the free tier.

https://www.youtube.com/watch?v=LrD8OeZivRY

@michaelquigley
Copy link
Collaborator

For historical purposes once this issue is closed, this is an issue related to the configuration of the NetFoundry-hosted zrok instance at zrok.io, not the core open source product. The hosted zrok has interstitial pages enabled on the public frontend, and manages the skip_interstitial_grants on a per-account basis, allowing users in different tiers to bypass the interstitial requirement.

So, for free tier users of the hosted instance, this breaks the built-in websocket client in browers.

@arenasys
Copy link
Author

arenasys commented Sep 17, 2024

The root issue is that Websockets will not work if interstitial pages are enabled. The only solution is to disable/bypass interstitial pages.

It's intentional that browser-based connections cannot bypass interstitial pages if they are enabled.
But is it intentional that websockets dont work with interstitial pages? I assume yes.

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

No branches or pull requests

2 participants