From 3ed0d8d4c9d5e656d444e78031951d664f4dfaa3 Mon Sep 17 00:00:00 2001 From: Vadim Ushakov Date: Thu, 11 Jul 2019 00:06:11 +0700 Subject: [PATCH] Fix a websocket connection issue when running in the proxy mode Steps to reproduce: 1. Run Zeronet with --ui_trans_proxy in a docker container or other isolated environment. 2. Set 127.0.0.1:43110 as a HTTP Proxy in a browser. 3. Navigate to http://talk.zeronetwork.bit/ 4. The site stops loading, since the websocket connection isn't functional. The bug consists of 2 related issues: 1. Connect to the proper address. When running in the proxy mode, Zeronet sends its env["SERVER_NAME"] and env["SERVER_PORT"] as the websocket destination address in the wrappper HTML code (variable `server_url`). That looks wrong for me, since the values of those variables have nothing to do with the actual address accessible by the browser. ZeroNet can run in a container, the connection also can be tunneled over SSH and so on. In all those cases, the internal SERVER_NAME makes no sense as the destination at all. The code for sending and handling `server_url` is deleted. The browser should connect to the websocket in the same way as it connects to the ZeroNet UI in general. 2. Send the proper response for CONNECT requests. A browser tries to connect to the correct address, but it still fails. A browser, when connecting via a HTTP proxy to a webdocket, uses the [HTTP tunneling protocol](https://en.wikipedia.org/wiki/HTTP_tunnel), and ZeroNet lacks support for it. To fix this, it's enoght to send the "200 OK" response on the CONNECT method request. --- src/Ui/UiRequest.py | 10 ++++------ src/Ui/UiServer.py | 7 ++++++- src/Ui/media/Wrapper.coffee | 2 +- src/Ui/media/all.js | 2 +- src/Ui/template/wrapper.html | 1 - 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py index 48599fda2..21625220f 100644 --- a/src/Ui/UiRequest.py +++ b/src/Ui/UiRequest.py @@ -81,6 +81,10 @@ def route(self, path): if config.ui_restrict and self.env['REMOTE_ADDR'] not in config.ui_restrict: return self.error403(details=False) + if self.env['REQUEST_METHOD'] == "CONNECT": + self.start_response("200 OK", []) + return "" + # Check if host allowed to do request if not self.isHostAllowed(self.env.get("HTTP_HOST")): return self.error403("Invalid host: %s" % self.env.get("HTTP_HOST"), details=False) @@ -430,13 +434,8 @@ def renderWrapper(self, site, path, inner_path, title, extra_headers, show_loadi inner_query_string = "?wrapper_nonce=%s" % wrapper_nonce if self.isProxyRequest(): # Its a remote proxy request - if self.env["REMOTE_ADDR"] == "127.0.0.1": # Local client, the server address also should be 127.0.0.1 - server_url = "http://127.0.0.1:%s" % self.env["SERVER_PORT"] - else: # Remote client, use SERVER_NAME as server's real address - server_url = "http://%s:%s" % (self.env["SERVER_NAME"], self.env["SERVER_PORT"]) homepage = "http://zero/" + config.homepage else: # Use relative path - server_url = "" homepage = "/" + config.homepage user = self.getCurrentUser() @@ -469,7 +468,6 @@ def renderWrapper(self, site, path, inner_path, title, extra_headers, show_loadi return self.render( "src/Ui/template/wrapper.html", - server_url=server_url, inner_path=inner_path, file_url=re.escape(file_url), file_inner_path=re.escape(file_inner_path), diff --git a/src/Ui/UiServer.py b/src/Ui/UiServer.py index 9daa90b12..25594ed2e 100644 --- a/src/Ui/UiServer.py +++ b/src/Ui/UiServer.py @@ -25,6 +25,12 @@ def __init__(self, *args, **kwargs): self.args = args self.kwargs = kwargs + def finalize_headers(self): + # Send no additional headers in response to the CONNECT method + if self.environ['REQUEST_METHOD'] == "CONNECT": + return + super(UiWSGIHandler, self).finalize_headers() + def run_application(self): if "HTTP_UPGRADE" in self.environ: # Websocket request try: @@ -51,7 +57,6 @@ def handle(self): super(UiWSGIHandler, self).handle() del self.server.sockets[self.client_address] - class UiServer: def __init__(self): diff --git a/src/Ui/media/Wrapper.coffee b/src/Ui/media/Wrapper.coffee index e57a1868f..f7af93fbe 100644 --- a/src/Ui/media/Wrapper.coffee +++ b/src/Ui/media/Wrapper.coffee @@ -692,7 +692,7 @@ class Wrapper log: (args...) -> console.log "[Wrapper]", args... -origin = window.server_url or window.location.href.replace(/(\:\/\/.*?)\/.*/, "$1") +origin = window.location.href.replace(/(\:\/\/.*?)\/.*/, "$1") if origin.indexOf("https:") == 0 proto = { ws: 'wss', http: 'https' } diff --git a/src/Ui/media/all.js b/src/Ui/media/all.js index 86c61b51c..0e9ed8683 100644 --- a/src/Ui/media/all.js +++ b/src/Ui/media/all.js @@ -1961,7 +1961,7 @@ $.extend( $.easing, })(); - origin = window.server_url || window.location.href.replace(/(\:\/\/.*?)\/.*/, "$1"); + origin = window.location.href.replace(/(\:\/\/.*?)\/.*/, "$1"); if (origin.indexOf("https:") === 0) { proto = { diff --git a/src/Ui/template/wrapper.html b/src/Ui/template/wrapper.html index 96f68d628..1de105af6 100644 --- a/src/Ui/template/wrapper.html +++ b/src/Ui/template/wrapper.html @@ -83,7 +83,6 @@

ZeroNet requires JavaScript support.

If you use NoScript/Tor browser: Cl file_inner_path = "{file_inner_path}" permissions = {permissions} show_loadingscreen = {show_loadingscreen} -server_url = '{server_url}' script_nonce = '{script_nonce}' if (typeof WebSocket === "undefined") {