Avoiding root in Linux

Christian Stredicke
CEO of Vodia Networks
Using the root account is a simple answer to provide the PBX process the necessary permissions. However it has become a good habit to provide processes only those capabilities that it needs to run.

One way to get this working would be to change the user once that all ports have been allocated. However that approach has a couple of drawbacks. First of all, the PBX starts reading and also writing files before the ports have been allocated. Writing files first as root and then later under a user account will create a lot of problems. And when the PBX changes ports or needs to re-allocate ports at a later stage, which is possible when the admin changes the setting from the web interface, this operation will fail.

A better solution is to use the Linux capabilities. This is a system that provides a fine-grained way to control what the process (thread) can do. The PBX needs to be able to allocate ports below the 1024 limit, open raw ports (for listening to the DHCP traffic), change the QoS bits for sockets, listen to broadcast traffic for the multicast provisioning, and change the priority so that the RTP packets have top priority in the system.

Here is what you have to do to make that happen: First create a group for the PBX which we can use to grab the permissions from:

root@pbx# sudo groupadd pbx
root@pbx# sudo usermod -a -G pbx <your-user-id>
root@pbx# newgrp pbx

Then make sure that the PBX executable is part of that group and only the owner and the group can actually execute it:

root@pbx# chgrp pbx /usr/local/pbx/pbxctrl
root@pbx# chmod 750 /usr/local/pbx/pbxctrl

Then comes the part where we actually tell the OS what capabilities the PBX will get when executed from an account that is in the PBX group:

root@pbx# sudo setcap cap_net_raw,cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_sys_nice=eip obj-d/pbxctrl-debian64
root@pbx# sudo getcap obj-d/pbxctrl-debian64

The last line should show you that the capabilities are there.

Then you should modify the startup script in /etc/init.d, so that the PBX starts with the user permission:

PBX_DIR=$PBX_DIR
prog=\$PBX_DIR/pbxctrl
lockfile=/var/lock/subsys/pbxctrl
OPTIONS="--dir \$PBX_DIR"
USER=<your-user-ID>

Then change the line that starts the PBX. It uses the daemon utility, just add -u $USER to it, so that is uses the account.

daemon -u $USER \$prog \$OPTIONS

Try to restart the PBX. It should now run as the user process and get all ports.