Fixed. Seems there was an "edit" sub-path in the url, so Github thought you wanted to edit the page. Which is why he required you to logon to github...
Make sure that you only allow access to required commands, not full sudo access. So, using visudo, something like
bart ALL=(ALL) NOPASSWD: /bin/systemctl
Then only that command can be run from node-red.
Thanks for taking the time to explain Bart.
You should certainly lock that down and you should certainly run Node-RED under a separate user id anyway. You can still enable users to do things like restart node-red by adding the command to sudoers without a password prompt. Restarting Node-RED is often not that insecure though possible to get a denial of service that way. Allowing the Node-RED user to restart the Pi might be more problematic.
One way around these issues is to have 2 instances of Node-RED. A more secure instance that runs under a separate id and that has a defined API that controls things like restarts (and restricts how often the restart is allowed for example so you don't get DOS'd) and the more generic instance - still under its own id. That one doesn't have privileged access but may be able to request things via the secure instance. This gives you a lot more control and an extra layer of security to work with.
When working with a Pi it is particularly important that you control access of course because the Pi user is TOTALLY OPEN with access to do anything. It is set that way to let the Pi be used as a learning and exploratory device, not for security. If you want a secure Pi, you really need to get rid of the Pi user and group.
Of course, we are really getting into the weeds here and, at the end of the day, you have to decide what your risks are and how much you want to try and mitigate them.
For me personally, my home server cannot be accessed directly from the Internet at all. I have some flows where I can control certain things and request certain information via Telegram. Then I have a couple of specific endpoints defined via Cloudflare Zero Trust - but the Node-RED editor isn't included by default. However, I do have a method that would let me turn on access should I need it.
But then, as I always say, my profession and experience makes me more than averagely paranoid.
Is it possible to specify parameters on the allowed command? So allow sudo systemctl restart nodered
but not other systemctl commands. I could not find any evidence that one could do that.
Yes, absolutely. And you can restrict to specific users or groups.
For example, here is 1 line from my live server:
/usr/sbin/iwlist wlp3s0 scan | grep -B 2 ESSID
Which, as you can see, is a complete BASH command line.
How do you put that into the NOPASSWD spec in sudoers?
You do sudo sudoers
as usual, then you should have a line for the user you want to change:
myuser ALL= NOPASSWD:/some/command with params \
/usr/sbin/iwlist wlp3s0 scan | grep -B 2 ESSID
Note the trailing \
which is a line continuation marker so that you can lay things out in a way that is comprehensible.
Oh, I see. I didn't see any examples of that anywhere.
So to limit systemctl to restarting node-red I can just use
me ALL=(ALL) NOPASSWD: /bin/systemctl restart nodered
Excellent, thanks.
I also created a small simple service for secure access to local servers:
It doesn't have a lot of features, but it also has no dependencies on the client side (except for a browser) and it's super simple to setup.
Has anyone tried serving static files with tailscale?
- I access my tailscale server editor at
https://myserver.forest-frog.ts.net/flow_editor/
- I've put a mp3 file in
/home/me/audio/frontdoor.mp3
and ensured that the file & directory permissions are OK - Setup httpStatic in settings
httpStatic: '/home/me/audio/',
- In the node-red log, I can see that
httpStatic
is registered ok -28 Nov 20:51:34 - [info] HTTP Static : /home/me/audio > /
- Because I've set
httpAdminRoot
to 'flow_editor', the audio file would normally be served athttps://myserver.forest-frog.ts.net/flow_editor/frontdoor.mp3
, but all I get isCannot GET /flow_editor/frontdoor.mp3
(I'm using a laptop to retrieve the url, which is also running tailscale and in the same tailnet)
Hi @Paul-Reed,
No I haven't tested that yet, but it is indeed weird that it doesn't work...
And if you circumvent your tailscale agent, can you fetch your file directly:
http://<pysical_ip_address_raspberry_where_static_file_is_hosted>:1880/frontdoor.mp3
P.S. Instead of making static files available via Node-RED, you can also tell your Tailscale agent to do that. I also haven't tested that yet. Like you can serve your local services (e.g. Node-RED) within your tailnet, you can also serve files or directories within your tailnet. See their documentation to create a simple fileserver with a single command:
sudo tailscale serve /tmp/public
Yes, but it's good news that there are two alternative solutions
I've gone with the local IP version, and yes, works well! thanks @BartButenaers
I'm using the served files to cast announcements to my google/nest speakers...
Yes but I can't imagine any reason why it wouldn't work via your virtual tailnet hostname. Will need to check it during the weekend.
Once you have something interesting found, please share it in your other matter related tutorial!
Awesome job, @BartButenaers !
One question: What if an unauthorized person would have physical access to a machine in your Tailscale network, does that bring extra risks?
Not so much extra risks. But yes, this can be a downside of a VPN style solution. However, Tailscale is a bit more than a standard VPN so you may still get more protection than a standard VPN in that I believe you can restrict what resources are available to an endpoint.
At the end of the day, any system that connects 2 endpoints can only ever be as secure as the weakest connection.
@jw_te_r ,
Thanks for the constructive feedback! That is the only way I can improve the tutorial. I was already wondering whether somebody had read it (beside Paul and Julian of course) and found it useful. The repo didn't get much stars yet...
Good question. That is indeed not very clear from my tutorial. I have registered an issue to remind myself to add it to the tutorial, if I ever find time...
Because your Node-RED is only available from the WAN via your secure tailnet, it is indeed pretty safe:
But like you say, what happens if somebody gets access to your LAN. Instead of accessing Node-RED via the Tailscale agent (daemon) on your Raspberry, he can navigate directly to port 1880 where your Node-RED is listening. And suppose you have removed the basic authentication from e.g. your Node-RED dashboard (to improve the WAF factor of your home automation), the hacker has direct access without username or password...
Therefore there is a part about extra security in the tutorial, where I mention that you could add extra firewall rules. For example to iptables on your Raspberry. In that rule you tell the firewall that port 1880 can only be accessed from localhost, and not from outside. That way the reverse proxy in your Tailscale agent can still forward the requests to port 1880, but you cannot access your Node-RED directly anymore.
There is an open issue about iptables already, but I simply don't find the time to experiment with iptables. So hopefully somebody else can read through the great feedback I got there, and do some testing...
I have also registered a new issue to add an extra section to the tutorial, to explain that the node-red-matter-bridge node from @sammachin is a much more secure alternative to control Node-RED from a Google Home or Alexa device. Because it doesn't require anymore to open a public funnel, which improves the security of the setup a lot. I just need to find some time to play with that node
Ok, that's clear. Thanks again.
I was wondering about a slightly different use case:
Recently I was asked to program a Node-Red installation for somebody else, which of course is not in my local network. At that time I had not heard yet about Tailscale, and because I know next to nothing about network security I opted to make it local only.
The installation runs on a NUC with a touch screen attached and no network access at all. Which means I will have to get into my car if there is a problem.
I was wondering whether Tailscale would be the way to make an installation like this accessible for me. Your tip about only allowing access to port 1880 from localhost sounds intriguing. I'll think about that for the next time.
Hmm, I haven't thought about such a setup yet.
Not sure if Tailscale has a solution out of the box for those situations.
Some possible setups from the top of my head:
- Perhaps you can drive once again over to your customer and install a tailscale agent and a separate tailnet. Then you invite yourself (see this article) to join that external tailnet.
- Add his device to your own tailnet. While you want to be able to access his device, but you want to avoid that he can access your devices:
- Add a label e.g. "own_device" to all your own devices, and a label "customer_device" to his device (in the "Devices" tabsheet of your Tailscale account).
- Create a ACL rule (in the "Access Control tabsheet of your Tailscale account) to allow only traffic from devices with label "own_device" to devices with label "customer_device", but not the other way around.
- Create a separate tailnet for your customer. Then share his device to yourself (see this article), so you get access to his shared machine.
At first sight I think I would go for option 3, but I might be mistaken completely. I have not read any details, so please have a good reading to make sure you setup it correctly!
And of course if you get something working, it would be helpful for others if you could share here on Discourse how you did it. That could also be a good eye opener for the community towards Tailscale, because I think a lot of users underestimate its possibilities...
[EDIT]: when you need to manage devices remotely from other users, it might also be interesting to have a look at Taildrop. It is a build-in tool from Tailscale to send files between your personal devices inside a tailnet. I haven't used that either myself...