Recently I have been asked, if Apache can bind to port 80, while running under an unprivileged (non-root) account. Of course, any process can, using RBAC.
Apache HTTP Server has a directive in its configuration file, under which user account the process should run. But if you want it to listen on the default port TCP/80, the parent process must be running under root. Apache opens port 80 as root and then forks child processes, that drop their effective uid and gid according to httpd.conf. There are some drawbacks:
- some people just do not find it safe enough
- it also requires, that Apache must be controlled by root user
One solution is to run it on an unprivileged port e.g. 8080 and use a port forwarding, or to have a load balancer / proxy server. Professionals use RBAC.
First let's configure Apache to run under user www
aix71@/# mkgroup id=10000 www
aix71@/# mkuser id=10000 home=/var/www shell=/bin/ksh login=false pgrp=www groups=www www
aix71@/# mkdir -p /var/www
aix71@/# chown www.www /var/www
aix71@/# grep -E "^User|^Group" /etc/opt/freeware/apache/httpd.conf
aix71@/# grep "^Listen" /etc/opt/freeware/apache/httpd.conf
A few dontforgets:
- Change the start script, so that Apache starts under user www
- Change the owner and permissions to DocumentRoot, log files, httpd.conf file, pid directory etc. Triple check it. Especially ensure that the error log file is writable by user www.
- Verify that Apache runs under root. Stop it (free port 80).
That's all about Apache configuration.
Role Based Access Control allows you to control user access to system resources on much finer level than a traditional root/nonroot approach. Using RBAC you can specify, that a certain non-root user can perform tasks on objects, that would normally require a root access. For example to work with LVM, to create backups, or to open a TCP port lower than 1024. Let's configure RBAC for our scenario.
A little bit of RBAC hacking. We need to know, what privileges does httpd program need to bind to port 80. You verified, that your Apache will succesfuly start and run under root user, right? As root run
aix71:/# tracepriv -f /opt/freeware/apache/sbin/httpd
12255428: Used privileges for /opt/freeware/apache/sbin/httpd:
For privileges description vist AIX 7.1 Infocenter or better, download a PDF. IT intuition says we need PV_NET_PORT privilege.
Create a domain using
aix71@/# mkdom command.
mkdom "id=1" dfltmsg="TCP Port 80" apache_80
We just created a domain with name apache_80 with id=1 and your custom identification string. Use
lsdom ALL to list all defined domains in the system.
Set the security attribute of the domain object. We want to set TCP port 80 to be accessible by a process that belongs to our domain.
aix71@/# setsecattr -o domains=apache_80 \
objtype=netport secflags=FSF_DOM_ANY TCP_80
Set the access attribute of the domain object. We want to set Apache binary to have privileges for network port when the command is run and for its child processess.
aix71@/# setsecattr -c accessauths=ALLOW_ALL \
innateprivs=PV_NET_PORT inheritprivs=PV_NET_PORT \
- set user www to belong to the domain apache_80
aix71@/# chuser "domains=apache_80" www
- And always always always, after you change anything in the domain setup, run
setkst command to set the kernel security table.
What now. Ah, sure, run the apachectl command to start the Apache. Check, that all apache processes run under www user. Doesn't work? Hm.
If you followed all the steps, and you are running AIX 7.1 (my test system), it's hard to believe it doesn't work. Most likely it's Apache configuration related.
- Does your apache run under root in the first place?
- Check if user www has access to all necessary directories: configuration directory, DocumentRoot directory, log files....
- Is port 80 free?
- Does Apache run under user www on unprivileged port e.g. 8080? If yes, this could be RBAC issue.
Thanks to Viktor Vojtanik for review and feedback and for an independent test.