Is there a way to configure the SignalK/Plug-In process to bind to privileged ports on Venus OS?

I suppose like many of you, we look to Victron to provide more capabilities with various manufacturer integrations on our boat or home (I use Victron for both). One way or another we do this to save ourselves money and/or provide more features/capabilities than what can be offered with a limited wallet or what can be provided for by being cost conscious without throwing unlimited funds at something.

I’m a Network/Systems Engineer for my normal work, and I have an Electronic Engineering degree. I deploy many custom ESP32 devices, computers, cameras, and specific manufacturer solutions to accomplish things that make integrations/features improve my life and enjoyment of home and more importantly on the boat.

I have many devices at home, and I have a Statum 0/1 NTP server in my house that I built. I control all time sync locally and do not allow any NTP traffic to the internet. I configure (where applicable) all devices to use my local NTP server and configure my SonicWALL firewall to redirect all NTP traffic to the NTP server for those that are hardcoded and not configurable.

For the boat, it ‘should’ be fairly simple to do the similar. I have a Garmin NMEA 2000 GPS unit that is always on and synced. The Cerbo SGX knows about it and has access to it natively, SignalK, and Node-Red. I should not need to build and install another GPS receiver/device to provide an NTP source for my boat local ethernet (LAN) network for all other equipment I’ve installed. Not to mention the Cerbo is one of those devices that hardcoded to talk to Europe NTP servers (I’m in the US)?!?! Why is this not a configurable item on the Cerbo???
I should not have to deploy an enterprise grade firewall just to redirect that NTP traffic either. So, I solve it through controlling local DNS resolution to an NTP server of my choice. I also do DNS redirects where I am able to detect or know the list of FQDN’s that are being used by a device.

I found a plugin for SignalK in the Appstore ‘signalk-ntp-server’ that fit’s the exact solution that I want/need and provides a proper NTP server without having to deploy extra hardware.

BUT the issue is now that the SignalK process does not have access to ‘privileged’ ports on Venus OS (e.g. <1024). The plugin cannot bind to port 123 and will not work as an NTP server.

The solution I’m looking for should survive device reboots and firmware updates to the Cerbo.
I’m weak on Venus OS, so I’m not sure how to accomplish this properly, let alone on the Linux OS. I’m extremely strong on Windows O/S Kernal’s.

I found the command ‘sysctl -w net.ipv4.ip_unprivileged_port_start=122’ that works until the Cerbo reboots. the ‘-w’ should allow it to persist, so there is something I’m unaware about? The command does not error out either.

What would be the best way to accomplish allowing SignalK to access ports below 1024 and even better specifically allow it to only access port 123. I am good with a solution that allows access on all ports or just port 123.

If needed, the specifics of my Cerbo version are usually the latest version as I keep things regularly updated as provided through Cerbo Updates, SignalK, or Node-Red.
I’ve found you have to be careful sometimes on updates as some SignalK plugins or Node-RED plugins updates sometime have dependencies that are not included yet in the Cerbo firmware.

Cerbo GX / SGX v3.54 (Large)
build date/time: 20250128120635

/usr/lib
├── @victronenergy/node-red-contrib-victron@1.5.23
├── corepack@0.28.0
├── node-red@3.1.10
├── npm@10.7.0
├── signalk-server@2.11.0
└── victron-vrm-api@0.2.10

Sorry for the long first post, but I thought also providing some context would help in understanding the ‘Why’ of wanting to allow SignalK to access port 123.

Let me throw some more or less generic Linux ideas at you:

I see signalk-server is started from the script /service/signalk-server/run, which has

/usr/bin/prepare-signalk.sh && exec setpriv --init-groups --reuid signalk --regid signalk /usr/bin/start-signalk.sh

If we season that line with a few sprinkles of magic, it becomes:

[...] setpriv --inh-caps +NET_BIND_SERVICE --ambient-caps +NET_BIND_SERVICE [...]

That gives the subprocess the capability to bind to low ports while still running as a normal user (traditionally, that’s only allowed for root).

The nicer version would probably to set the capabilities on the signalk executable, or the ntp plugin executable. This would be the least privilege approach, but requires finding which executable is doing the bind(2) system call. The above solution allows start-signalk.sh and all child processes to bind to low ports, which is probably an acceptable risk.

Oh, and if you change the /service/signalk-server/run script, be prepared to change it again after an OS upgrade, or to add a few lines to /data/rc.local that fix it on every boot.

Hope this helps.

Edit:

  1. I’ve tested this on VenusOS 3.52, binding to 123/tcp with netcat.
  2. sysctl -w writes to the kernel, not some “persistent” config file. You’d have to do that yourself, /etc/sysctl.conf should be the right file, but as the “need to re-edit after upgrade” also applies here (I guess), the capabilities solutions is as much work, but cleaner.

Thank you so much for your reply.

I do read the victron published docs and do research as much as I can.
I was on a similar approach you were, but I wanted to ask what was proper in case there was a more elegant solution. And your reply confirmed there is a better solution.

Since this requires running the ‘/opt/victronenergy/swupdate-scripts/resize2fs.sh’ file to obtain RW access to the ‘/opt/victronenergy/service/signalk-server/run’ file, I was already working on creating a ‘rcS.local’ file which would run the ‘resize2fs.sh’ script and then run a patch command for the ‘run’ file.

BUT, I was inserting ‘sysctl -w net.ipv4.ip_unprivileged_port_start=1’ into the run file.

I like your approach better as it limits it to signalk more than the whole Venus OS.

I’ll update my files and report back.

This part of the Venus OS I was somewhat familiar with as I utilize the config settings to make sure my Cerbo’s are configured correctly after a firmware update or device reset… I do device resets more than normal because sometimes I get stuck after I do a plugin update, and it fails or breaks my signalk or node-red since the dependencies for the plugin isn’t there and I don’t know how to install a specific version of plugin after update. So, I factory reset and then take advantage of the pre-configure to make it faster to recover since.
I tar the data directory up every time I get to a working state and before I do plugin updates so I can recover semi-automatically

1 Like

I change my files and confirm the settings.
I will summarize my final actions and working config here for future reference. I hope I get this right.

Since the rootfs is RO, we need to run the following command:

/opt/victronenergy/swupdate-scripts/resize2fs.sh

Now we can edit files to test and cause the changes to stick. Here are my edits:

cp /opt/victronenergy/service/signalk-server/run /data/run.diff

edit /data/run.diff FROM:

/usr/bin/prepare-signalk.sh && exec setpriv --init-groups --reuid signalk --regid signalk /usr/bin/start-signalk.sh

edit TO:

/usr/bin/prepare-signalk.sh && exec setpriv --inh-caps +NET_BIND_SERVICE --ambient-caps +NET_BIND_SERVICE --init-groups --reuid signalk --regid signalk /usr/bin/start-signalk.sh

To create a patch file that will be used in rcS.local later:

diff -u /opt/victronenergy/service/signalk-server/run /data/run.diff > /data/run.patch

To install the patch file and be able to test changes (requires reboot to test):

patch /opt/victronenergy/service/signalk-server/run < /data/run.patch

If it works as expected, create a /data/rcS.local file:

#!/bin/sh
# make the rootfs writeable
/opt/victronenergy/swupdate-scripts/resize2fs.sh
# apply the patch file
patch /opt/victronenergy/service/signalk-server/run < /data/run.patch
exit 0

This will survive reboots, and firmware updates.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.