Socket connection from chrome extension being blocked by proxy/firewall - javascript

I have a web app in javascript that connects to a socket using socket.io and a Chrome Extension which connects in the same way and to the same server.
Everything works fine in most computers and internet connections, but one of my customer's computer is failing to have the Chrome Extension connected (the web app connects successfully).
By inspecting the extension's console for background.js (the script within the extension creating the socket connection) I see that it is not trying to connect to the right URL (my socket server) but to an unknown URL which seems to be a proxy: https://gateway.zscloud.net/auT?origurl=http%3A%2F%2Fmy_socket_server_domain...
Since this is happening only in that specific computer (from the 10 or so that I have tried with so far) using different internet connections (corporate network, guests network, mobile hotspot) and since other computers in those same networks DID succeed in connecting, I assume something installed or configured in the problematic computer is catching the connection request before it happens and tries to redirect it through a proxy.
Again, this happens only in the context of the Chrome Extension. The very same computer using the same internet connection DOES succeed in connecting from a web page in the same browser (Google Chrome).
Does anybody know what the problem could be? The client is not aware of having a security software (firewall, antivirus, etc...) that could be causing this, but it's a computer managed by his company so an admin could have done that for him. If that was the case, however, shouldn't the connection from the webpage be captured too? Is there anything specific to socket connections in Chrome Extensions that differ from regular web apps?
Thanks!

WebSocket connections differ from normal HTTP requests; they require a protocol upgrade after establishing that (some!) proxies may be unable to support.
I was at some point behind one such (transparent) proxy at work; however, it does not attempt to intercept HTTPS, which means I could use wss: WebSockets but not ws: WebSockets.
..which you should be using, anyway! With Let's Encrypt on the market, the barrier of entry for HTTPS is very low. If any sensitive data at all is sent through that connection, it's in your best interest.
For the record, that particular proxy is part of ZScaler which is a security solution. Sadly, it includes HTTPS MITM, so the above is unlikely to solve the problem (but should be implemented anyway!). It's set up as an OS-level proxy - if that setting is possible to change, or override with Chrome's proxy settings, that would fix it. However, that's going to piss off network security!
If you can't do that, then your client is a SOL and should complain up the chain about the security solution breaking legitimate applications.
Edit: I looked around and found this, which seems to claim that using SSL (that is, wss:) is enough. But that's from 2012 - perhaps before ZScaler was able to MITM all HTTPS traffic.
It should be possible to test whether wss: switch will work using https://www.websocket.org/echo.html - if it can connect then everything will work over wss:

Related

Can Chrome or Firefox open a network port and serve connections using javascript?

For a mostly offline browser game I'm researching the possibility to run a WebRTC signalling server from a browser.
I can imagine that security-wise it's a big no-no to open a port and serve connections from a browser (or service worker), but I cannot* find any information on this.
Q. Can Chrome, Firefox (or perhaps any other major browser) open a network port and serve connections using javascript? Or is this fundamentally disallowed by browser design?
*) For sake of completeness, I did find one option (maybe), but it's overly complex, and therefore isn't very appealing. There is a javascript package called filerjs, which allows for a posix-like filesytem in the browser, I think using indexedb, that would allow for a nodejs installation in the browser. I did not further investigate it, so no idea if it actually works, and if a connection could be served this way.
I don't think that you can run a signaling server in the browser. But you say "mostly offline", does that mean that the peers are connected to the internet, but playing from the same LAN? Or are they completely offline? Here are a few ideas:
Signaling server on the web
Even if the signaling server is running on the web, chances are that WebRTC will connect directly through the LAN (to be tested, and it may depend on how the browser selects the ICE candidates).
Manual signaling
Now, the signaling server is only there to exchange SDP messages. So you could theoretically copy-paste the offer and answer (or copy it manually, or scan it with a QR code). It may not be practical, but for instance you could try hardcoding the SDP offer/answer. The two players would need to exchange information somehow, though:
The ICE candidates (those are IPs) that you would need to create the SDP message
The SDP type (one has to be the offer, the other has to be the answer)
I never tried it, but maybe your UI could tell the player "Please share the following IPs to the other player, and enter their IPs below. Also select if you are the offerer or the answerer". But you see that it seems a bit convoluted...
Signaling server in the LAN
If the peers are completely offline and the manual signaling is too convoluted, my next idea would be to run the signaling server in the LAN, and have the peers connect to it. You could even make it such that your game first tries to contact your signaling server on the Internet, and if it fails (because it is offline), it could fallback and try to contact the one in the LAN (maybe it would need to ask the user for the IP of the signaling server, then).

Turning your browser into proxy server

I have a logic written on my server mostly doing curl requests (e.g. accessing social networks). though, some of the sites, will be blocking my server(s) IPs soon.
I can of course, use VPN or deploy multiple servers per location, but it won't get accurate, and still some of the networks might get block the user account.
I am trying to find creative solution to run it from the user browser (it is ok to ask for his permission, as it is an action he is explicitly trying to execute) Though I am trying to avoid extra installations (e.g. downloadable plugins\extension or a desktop app)
Is there a way to turn the client browser into a server-proxy, to run those curl-calls from his machine instead of sending it from my own server? (e.g. using web-sockets, polling, etc.)
It depends on exactly what sort of curl requests you are making. In theory, you could simulate these using an XMLHttpRequest. However, for security reasons these are generally not allowed to access resources hosted on a different site. (Imagine the sort of issues it could cause for instance if visiting any website could cause your browser to start making requests to Facebook to send messages on your behalf.) Basically it will depend on the Cross-origin request policy of the social networks that you are querying. If the requests being sent are intended to be publicly available without authentication then it is possible that your system will work, otherwise it will probably be blocked.

Why do I get a getCurrentPosition() and watchPosition() "insecure origins" error in Chrome on localhost?

I'm working on a website in my local development environment (Ubuntu 16.04) and testing the website on Chrome (58) via http://localhost.example/ - which connects to the local web server.
Running this Javascript:
$(document).ready(function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
});
Triggers this error:
[Deprecation] getCurrentPosition() and watchPosition() no longer work
on insecure origins. To use this feature, you should consider
switching your application to a secure origin, such as HTTPS. See
https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins for more details.
Why is that? I understand that public facing websites need to be running HTTPS for the geolocation library/ functionality to work. We have a number of public websites running similar code across HTTPS.
However according to the depreciation documentation:
localhost is treated as a secure origin over HTTP, so if you're able
to run your server from localhost, you should be able to test the
feature on that server.
The above Javascript is running in-line in the HTML body loaded via http://localhost.example/test-page/ - so why am I getting the "insecure origins" error in Chrome?
Firefox (53) shows the in browser access location prompt, as expected.
Chrome considers localhost over http as secure. As you are using hostnme localhost.example over http, this is not considered as secure.
Note: Firefox will behave similarly as of Firefox 55
SSL over HTTP protocol ensures the private communication within Client and Server. The information might transmit through the private networks while transmission. Any third person (hacker) on the network can steal that information. To avoid that browser forces the user to use a secure connection.
On the local server, the information is not going beyond our private local network since there is not need of this kind of security. So we can expect a browser to allow geolocation without SSL on the local server. Ideally, the browser developer should skip this validation for localhost and 127.0.0.1 or similar origins.
There must be tricks available to avoid such issues i.e. you can install self-signed SSL certificate on the local server or you can edit the Chrome configuration file to allow domains to access the geolocation, webcam etc.
Helpful links,
https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins
https://ngrok.com/

Locate server on LAN in JavaScript

TL;DR
In Javascript, how do you to find the IP of all servers running a specified program on a specified port in the LAN?
Background
I'm writing a server in node.js that is supposed to connect users browsers as controllers to a common device on which a game is running. The browsers are running a web app based on html and Javascript. The connection is based on socket.io.
I'd like for the web app to be able to find all available instances of this server in the LAN in order to create a server list for the user to choose from.
Is there a way to make the server discoverable by the web app on the local network in Javascript, and in that case: how?
Ideas
Have the server broadcast its IP to all devices on the LAN and have the web app listen for these messages (No idea how to do this without node on the client)
Connect to every IP on the network and see if the connection is successful. (Does not seem feasible)
Scan every IP on the network and connect only to those where the port is open. (Once again, no idea how to do this without node on the client and does not seeem feasible either.)
EDIT
The server is supposed to be portable and work independently, without any central system backing it up or providing matchmaking for clients. It is a LAN only server and should work even without internet access.
There is no way for you do this. Sorry. Since there is no exposure to UDP on client-side JavaScript, broadcasting is out of question. Any attempt on massive scanning will quickly raise flags on network monitoring software. You have to use a known address.

Find a server in local network via client javascript in browser

Is it possible to find the ip of an http-server (which will respond on a specific request) in local network only via client javascript in the browser? It should work on mobile and desktop browsers.
The poor mans way trying out all ip(v4) adresses seems not possible because I cannot get reliably the local ip (http://net.ipcalf.com doesn't work on IE and all mobile browsers on iOS). UDP broadcasts don't seem possible with javascript. Is there any other possibility?
My only other alternative seems to be developing a native discovery app for all relevant platforms (win, mac, ios, android).
You just can guess the IP-Range of the local network and send multiple ajax requests to each IP in the Network. You will always get an error for each request, because if there isn't a timeout you get an No Access-Control-Allow-Origin error. However you can distinguish these errors by setting the timeout time to a certain time and track the time until the error occurs. If the tracked time is equal or bigger than your timeout you can suspect a timeout error. Otherwise you will get the error faster. So you can suspect that there is a server behind this IP.
Note: This is no secure method to search for servers and very CPU intensive.
There's no purely client-side way to get that information, no. You'd have to query a site that provides DNS lookup with a cross-domain-friendly API, but that's not purely client-side.

Categories

Resources