You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
WebControl does not work behind HTTPS due to hardcoding of HTTP schema #146
It appears the socket.io interface config may have hardcoded the HTTP schema into the URL construction, because WebControl fails to work behind a HTTPS connection for me:
Yes, it is. HTTPS was another layer of things that I never tried to deal with considering my relatively limited knowledge of such things. static/scripts/baseSocket.js has it set to open via HTTP from the browser side. I don't know what specifically needs to be done to support operation over HTTPS. I "assume" webcontrol would need to be configured for HTTPS.. however that's done.
All you need to do to adapt to schema is leave out the schema from any client side code. Assets on the browser side are resolved relative to the root schema when no schema is provided. For example, the following HTML tag: <link rel=dns-prefetch href=//fonts.googleapis.com>
Will resolve to http on a HTTP site and HTTPS on a HTTPS site. Nothing else needs to change, as long as the website backend implements TLS correctly (not in your control — in my house, I have a front proxy doing TLS termination).
It seems to still run if I drop the HTTP out of the baseSocket.js file, but webcontrol itself is running the flask development server and its not running HTTPS (not everything is done via websocket). Does that still cause an issue?
But I suspect what you mean is that your flask server does not implement TLS termination (i.e., negotiate a HTTPS handshake with the client). Indeed, that is the job of the front-proxy. Right now, you're doing this:
localhost:5000 -> flask:5000
Nginx is a common front proxy which can implement TLS termination. Its job is to relay the traffic to the Flask server, having handled the encryption/decryption and passing off normal HTTP traffic:
You're correct in your suspicion. I've used nginx on an aspnet program, but that's on a dedicated webserver and not sure how to (or if its possible) package it all up into a single pyinstaller executable. That's sort of the tricky part.
Oh, you don't need to package nginx. Just make the change to the frontend that you suggested (and test that it's doesn't break your deployment). It's the end-user's responsibility to run the front proxy.
For example, I have WebControl running in a container right now. I can access it directly at 192.168.0.202:5000 (connecting to flask). In my original screenshot, you can see that I am also able to load the UI through the HTTPS website URL https://maslow.snowy-cabin.com. The reason this works is that my front proxy receives the traffic to that URL, and acts, well, as a proxy! So the WebControl app doesn't need to know anything about the fact that it's being accessed over HTTPS. From its perspective, it's just getting normal old traffic via port 5000.
The change is required because the frontend has to know which URL to connect to. Even though the flask backend doesn't know the difference, the frontend is the one establishing the connection. So even even though I loaded the website through the HTTPS URL (front proxy), if you try to load an asset on the frontend Javascript via HTTP instead of HTTPS then it will fail. This causes browser security errors, as you can see from the Javascript log.
In fact, the entire problem boils down to the fact that the Javascript frontend is technically trying to connect to a different server by specifying a schema which is different than that provided in the URL bar. As it stands, this is actually a pretty big security vulnerability, which is why modern browsers won't let you do it.
Perhaps we are talking about two different kinds of installations. For the releases I build, they function as all-in-one webservers (for lack of a better term). It's basically a single installation containing everything the user needs. They don't have to set up a webserver/frontend, etc.
I think the part you're missing is that a front proxy like nginx is an entirely optional add-on which should be left in the user's control. This is how server deployment is supposed to be done, and also in keeping with containerization best-practices. Think of WebControl like, say, WordPress:
Wordpress:
Is a PHP server application
Is available as a docker container (or not — your choice, it doesn't matter)
Has a frontend (HTML + Javascript) that can connect via sockets to the backend (PHP)
WebControl:
Is a Python server application
Is available as a docker container (or not — your choice, it doesn't matter)
Has a frontend (HTML + Javascript) that can connect via sockets to the backend (Python)
Wordpress does not include nginx when you install in on your computer, nor should it. Nor does it support SSL/HTTPS out of the box. If you want to host your WordPress site anywhere but at localhost:xxx, then you add your own nginx (or other front proxy) to achieve load balancing, SSL termination, etc.
But most importantly, none of this changes the way the app works at all. Wordpress and WebControl both function as normal, without any awareness of nginx, regardless of if it is present or not. They simply don't care, and that's by design. I can still load Wordpress and run it on localhost:xxx, and in fact that is the default behavior—just as importantly this default behavior still works with nginx. Generally adding a front proxy like nginx is how you move (whatever application, like Wordpress) from a localhost-only to some sort of larger deployment. The key word here is proxy. Nginx is a proxy. It adds a layer to the communication, but does not change anything to the perspective of the application itself because the traffic looks the same to the backend application.
Finally, the real point here is not about the backend. It's about the frontend. WebControl has a security vulnerability because of the way its frontend is designed. In a nutshell:
WebControl's frontend is attempting to connect to a different server than where the backend resides. It does not use the same schema as it was told to, and this lack of following of security practices is the root cause of the problem.
This is a classic security vulnerability which leaves WebControl open to man-in-the-middle attacks, ultimately allowing an attacker to theoretically take control over the Maslow (literally, control it) in certain scenarios where the WebControl application is not otherwise secured.
Yes, nginx is a web server that happens to be often used as a reverse
proxy, while haproxy is purpose-built for that.
Le jeu. 21 mai 2020 17 h 10, Orob-Maslow <notifications@github.com> a
écrit :
Which is another reason I was recommending against bundling any sort of
reverse proxy (or the assumption of its existence) with the application
itself :) I happen to use Envoy Proxy myself (nginx is merely a convenient
example) so my setup will look a touch different.
On Thu, May 21, 2020 at 4:33 PM Emile Cantin ***@***.***> wrote:
Yes, nginx is a web server that happens to be often used as a reverse
proxy, while haproxy is purpose-built for that.
Le jeu. 21 mai 2020 17 h 10, Orob-Maslow ***@***.***> a
écrit :
> Side question... Does haproxy do the same thing that nginx is doing?
> Octoprint uses haproxy in a manner similar to your description.
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <
#146 (comment)
>,
> or unsubscribe
> <
https://github.com/notifications/unsubscribe-auth/AAGYF3XDM3R2VMXJHQ4IN7LRSWKEHANCNFSM4NHAW4KA
>
> .
>
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#146 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAP47VO3U7VD5P43DQIMT4DRSWT25ANCNFSM4NHAW4KA>
.
I can drop the http from baseSocket.js if that works for your installation because it seems unneeded for a standard install (will check more). I just want to make sure there are no other changes needed.
Sounds great — if you want, you can just tell me where the config file is (or open an PR to show me) and I can test it myself in the docker container as well.
Activity
madgrizzle commentedon May 21, 2020
Yes, it is. HTTPS was another layer of things that I never tried to deal with considering my relatively limited knowledge of such things. static/scripts/baseSocket.js has it set to open via HTTP from the browser side. I don't know what specifically needs to be done to support operation over HTTPS. I "assume" webcontrol would need to be configured for HTTPS.. however that's done.
zaneclaes commentedon May 21, 2020
All you need to do to adapt to schema is leave out the schema from any client side code. Assets on the browser side are resolved relative to the root schema when no schema is provided. For example, the following HTML tag:
<link rel=dns-prefetch href=//fonts.googleapis.com>Will resolve to http on a HTTP site and HTTPS on a HTTPS site. Nothing else needs to change, as long as the website backend implements TLS correctly (not in your control — in my house, I have a front proxy doing TLS termination).
Same applies to JavaScript.
madgrizzle commentedon May 21, 2020
It seems to still run if I drop the HTTP out of the baseSocket.js file, but webcontrol itself is running the flask development server and its not running HTTPS (not everything is done via websocket). Does that still cause an issue?
zaneclaes commentedon May 21, 2020
tl;dr: that sounds fine...
I'm not sure what you mean by:
But I suspect what you mean is that your flask server does not implement TLS termination (i.e., negotiate a HTTPS handshake with the client). Indeed, that is the job of the front-proxy. Right now, you're doing this:
localhost:5000->flask:5000Nginx is a common front proxy which can implement TLS termination. Its job is to relay the traffic to the Flask server, having handled the encryption/decryption and passing off normal HTTP traffic:
https://house.snowy-cabin.com->nginx:443->flask:5000madgrizzle commentedon May 21, 2020
You're correct in your suspicion. I've used nginx on an aspnet program, but that's on a dedicated webserver and not sure how to (or if its possible) package it all up into a single pyinstaller executable. That's sort of the tricky part.
zaneclaes commentedon May 21, 2020
Oh, you don't need to package nginx. Just make the change to the frontend that you suggested (and test that it's doesn't break your deployment). It's the end-user's responsibility to run the front proxy.
For example, I have WebControl running in a container right now. I can access it directly at
192.168.0.202:5000(connecting to flask). In my original screenshot, you can see that I am also able to load the UI through the HTTPS website URLhttps://maslow.snowy-cabin.com. The reason this works is that my front proxy receives the traffic to that URL, and acts, well, as a proxy! So the WebControl app doesn't need to know anything about the fact that it's being accessed over HTTPS. From its perspective, it's just getting normal old traffic via port 5000.The change is required because the frontend has to know which URL to connect to. Even though the flask backend doesn't know the difference, the frontend is the one establishing the connection. So even even though I loaded the website through the HTTPS URL (front proxy), if you try to load an asset on the frontend Javascript via HTTP instead of HTTPS then it will fail. This causes browser security errors, as you can see from the Javascript log.
In fact, the entire problem boils down to the fact that the Javascript frontend is technically trying to connect to a different server by specifying a schema which is different than that provided in the URL bar. As it stands, this is actually a pretty big security vulnerability, which is why modern browsers won't let you do it.
madgrizzle commentedon May 21, 2020
Perhaps we are talking about two different kinds of installations. For the releases I build, they function as all-in-one webservers (for lack of a better term). It's basically a single installation containing everything the user needs. They don't have to set up a webserver/frontend, etc.
zaneclaes commentedon May 21, 2020
I agree. That's what I'm describing as well.
I think the part you're missing is that a front proxy like
nginxis an entirely optional add-on which should be left in the user's control. This is how server deployment is supposed to be done, and also in keeping with containerization best-practices. Think ofWebControllike, say,WordPress:Wordpress:
WebControl:
Wordpress does not include nginx when you install in on your computer, nor should it. Nor does it support SSL/HTTPS out of the box. If you want to host your WordPress site anywhere but at
localhost:xxx, then you add your own nginx (or other front proxy) to achieve load balancing, SSL termination, etc.But most importantly, none of this changes the way the app works at all. Wordpress and WebControl both function as normal, without any awareness of nginx, regardless of if it is present or not. They simply don't care, and that's by design. I can still load Wordpress and run it on
localhost:xxx, and in fact that is the default behavior—just as importantly this default behavior still works with nginx. Generally adding a front proxy like nginx is how you move (whatever application, like Wordpress) from alocalhost-only to some sort of larger deployment. The key word here is proxy. Nginx is a proxy. It adds a layer to the communication, but does not change anything to the perspective of the application itself because the traffic looks the same to the backend application.Finally, the real point here is not about the backend. It's about the frontend. WebControl has a security vulnerability because of the way its frontend is designed. In a nutshell:
This is a classic security vulnerability which leaves WebControl open to man-in-the-middle attacks, ultimately allowing an attacker to theoretically take control over the Maslow (literally, control it) in certain scenarios where the WebControl application is not otherwise secured.
Orob-Maslow commentedon May 21, 2020
Side question... Does haproxy do the same thing that nginx is doing? Octoprint uses haproxy in a manner similar to your description.
emilecantin commentedon May 21, 2020
zaneclaes commentedon May 21, 2020
madgrizzle commentedon May 22, 2020
I can drop the http from baseSocket.js if that works for your installation because it seems unneeded for a standard install (will check more). I just want to make sure there are no other changes needed.
zaneclaes commentedon May 22, 2020
Sounds great — if you want, you can just tell me where the config file is (or open an PR to show me) and I can test it myself in the docker container as well.
madgrizzle commentedon May 22, 2020
PR committed into master branch.