-
Notifications
You must be signed in to change notification settings - Fork 33
How to safely expose Node RED to the Internet
These are notes and ideas prior to writing a recipe for the cookbook.
-
Websocket security!
Note that this is no longer correct.
Websockets do not inherit ANY security features other than TLSFor this reason, it cannot be recommended to expose any page using raw websockets (ws: or wss:) over the Internet if you need any level of security at all. E.g. DO NOT use websockets if you are allowing your system to be controlled over the Internet from a Node-RED delivered page with websockets - including Dashboard!
This needs a lot more work before we could consider Node-RED websockets in any way "secure".
It is possible that using Socket.IO may provide some additional security, I am looking into it.
Note that this does represent a real risk. But currently the risk is tiny as knowledge and penetration of Node-RED into the rest of the real world is still limited. None the less, it is important to understand the current limitations. While waiting for native changes to websocket processing, please take this into account and don't expose sensitive systems to the Internet - E.g Might not be the wisest thing to do to put your boiler controls onto the Internet using Dashboard switches (because they use websockets) without additional protection.
- Discussion on JWT and front-end reverse proxies with a resulting blog post here and the node-red-contrib-auth node which provides helpers for simple JWT based auth (it doesn't actually do the auth though).
If you don't know anything about networking, you might need to read the quick explanation lower down.
For Node-RED to be accessible from the Internet, you will need to know your public IP address. Internally to your local network, you might point your browser at http://192.168.1.2:1880/ui for example but that is meaningless on the Internet as it is a local-only address. Now even if you know the external address, it will fail to connect to Node-RED for 2 reasons.
Firstly, your router's firewall will reject all incoming requests by default. So you have to change the firewall to allow inbound traffic on port 1880 (see the security section on why you might want to change that).
Secondly, the router does not, by default, know how to route traffic from that inbound request to the correct internal destination. To resolve that, you have to set up a Network (and/or Port) Address Translation (NAT/PAT) entry that links requests from any address on port 1880, to 192.168.1.2 on port 1880.
Of course, IP addresses are not terribly friendly so you might want to set up a name. This is done using a public DNS (Domain Name Service). If you want your own name, you will need to register a "domain name" for which there is a small annual cost. There are, however, some services that will give you a sub-domain name for free, have a look for "dynamic DNS" services. The other reason to use a dynamic DNS service is that many ISP's don't give out permanently fixed addresses (because they are in short supply) - so your public IP address may change from time-to-time. Once you have your name and have associated it with your public IP address, and have set up your router/firewall appropriately, you can access Node-RED from the Internet using a name like: http://donald.duck.com:1880/ui.
Now carry on and read why you should immediately (within a few seconds) pull the plug! Make it secure, do not assume that nobody is interested in you. Though it may be true, the bots out there don't care whether you are famous, important or otherwise noteworthy, they are mainly only looking for a tiny foothold and it is fully automated. On a brand new public IP address, connected for the first time, it typically takes less than 30 seconds for automated hacking attempts to start.
-
Always use TLS (HTTPS) to encrypt the traffic between the client browser and the Node-RED service
You can use Node-RED itself to host the cert (see this script), use a reverse proxy (NGINX, HA-Proxy or Apache web) or use an external 3rd party service such as Cloudflare.
-
Consider using a non-standard IP PORT >1024
This obscures the fact that you are using Node-RED and it helps mitigate against automated attacks.
Use ports higher than 1024. Lower ports generally require running your app with admin or root privileges which may create additional security weaknesses.
-
Apply protection to the editor and admin API
This is done using the built-in password security configuration setting
adminAuth
.This can be a simple list of user names and hashed passwords or could be a function which allows other authentication schemes to be used. (An example of another scheme other than the simplistic one in the docs would be helpful but I don't have one at present).
-
Apply protection to the user interface pages - See section "User Interface Security" below.
-
Consider putting Node-RED behind an reverse proxy such as NGINX, HAproxy or Apache Web Server. Or IIS on Windows/Azure.
You can use those to terminate https, possibly provide a login front-end, mitigate various attacks and potentially provide better performance. Phusion Passenger can also help with Node.JS performance and keeping things running.
-
Consider preventing direct access to the Node-RED web service by using a content delivery network such as Cloudflare
You can use this to provide better https security and to mitigate various attacks. This has the significant advantage that you only need a private (self-signed) certificate in Node-RED. Normally, a private certificate causes pain to end users as browsers assume it is "insecure" which is wrong. However, CloudFlare provides its own, publicly signed, certificate which is accepted by browsers.
If you do use this method, only allow Internet access to Node-RED from Cloudflare. All external traffic is then forced through the protection features and certificate of the CDN. This is achieved using a firewall and configuring it to only accept connections to the Node-RED service from a CloudFlare server. You can use your router to do this or the built-in firewall of the operating system.
-
Limit the use of websocket connections to non-sensitive use only or add additional processing to apply authentication and authorisation controls to the socket.
Node-RED has some built-in user interface security that allows you to fairly easily apply access restrictions to pages destined for users (as opposed to the admin/editor UI).
Please don't forget however that you must configure Node-RED to require TLS security (HTTPS). Without that, adding these methods is pointless.
Also, a small warning, the contributed nodes have not necessarily been extensively tested for security issues. Probably best to remember this and perform your own testing accordingly. Security is easy to get wrong.
This is the simplest but least flexible method. It is described at the end of the security page of the Node-RED documentation.
It only supports a single user however and it applies to all of the user pages served by Node-RED
including the Dashboard. (httpStaticAuth
separately controls access to "static" resources).
This setting allows you to add ExpressJS middleware to all of the http in
nodes. So you could add any
authentication and authorisation scheme that is compatible with Express's middleware such as the excellent
Passport.
node-red-contrib-httpauth
adds a single node called http auth
to the pallette. You add this downstream of an http in
node and it adds HTTP Basic or Digest authentication to the route defined in the http in
node.
Credentials are defined in the node's configuration or in an external file.
node-red-contrib-http-auth0
is similar to the auth node above but uses the external authentication provider Auth0. Fine as long as you trust Auth0 and are happy with all of your authentication requests going via their servers.
Note that node-red-contrib-auth
does not actually provide authentication, it is simply a helper for using JWT. It should be possible, therefore to use it as part of an authentication flow.
ngrok acts like a reverse proxy and is able to create a secure link from a machine on the internal network via an externally site, hosted by ngrok themselves.
The basic service is designed primarily for testing but should work well. It is particularly useful for setting up HTTPS callback locations for API connections such as the Facebook API which doesn't work with self-signed certificates.
Just remember that you are effectively creating a connection for external services to a specific IP/port inside your local network. Example. As such you have to trust the ngrok web services security and privacy processes.
The advantage is that, because ngrok reaches out to its intermediary service, you don't have to make any changes to your router/firewall for it to work.
Let's assume that you are running Node-RED on a device inside your home or small office network. Between your network and the outside world, you are likely to have a "Router". Note that, in larger installations, you may have much more including a dedicated firewall.
A SOHO (Small Office/Home Office) or consumer router also contains firewall capabilities. The router part is responsible for taking traffic from your network and routing it to the outside world and visa-versa. The firewall part is responsible for preventing unwanted traffic getting into your network (on better routers, it can also add protections to outgoing traffic too).
The other issue of note is how things on networks are addressed. These days, something called TCP/IP is the main protocol for network traffic. Identifications of devices (the actual network card) is done using something called a MAC address that we don't need to worry about. But a service end point (such as a web server) is identified firstly using an IP address and then by a port. The default port for Node-RED is 1880 though this can be changed in the settings. The port for each service must be unique both at the IP address and the device levels.
IP addresses have 2 versions v4 and v6. We will discount v6 for now. An IPv4 address has 4 numbers from 0-255 separated by dots. Some addresses are reserved for special use and most are publicly pre-allocated. In SOHO/Home environments you will generally only see addresses starting with 192.168.n.n, you might occasionally see addresses starting with 10.n.n.n
These addresses are not for use on the Internet, they are reserved for private networks like your home or small office (or not so small offices!).
So when you run Node-RED on a device, the device has an IP address, lets say 192.168.1.2 and the Node-RED service opens a port on that address, generally 1880. But this is a non-routable/non-Internet address and your router will rightly refuse to route it outside your local network.
Not terribly helpful! That's where something called Network Address Translation (NAT) comes in. When your service using a non-routable address wants to reach out to the Internet, the router is configured to translate your internal address to the external address for your Internet connection. That is assigned by your ISP from a range of registered, routable addresses.
The router then keeps track of what connections have been made so that return traffic gets back to the right place.
Now, if you want to allow someone/thing on the Internet to get access to a service running on your local network, the router requires a table to translate the other way. There are a couple of ways to do that, your router manual should lead you through it (you can use NAT/PAT or a DMZ). The firewall will also need changing to allow inbound traffic.