A few weeks ago I was tasked with setting up UniFi WiFi controller software on a server running CentOS. The software only seems to be officially supported on Windows and Mac, but it’s all written in Java (write once run anywhere™) so that makes this quite feasible. And for the most part it proved to be an easy enough task: there are plenty of guides for exactly this scattered around the Net.
The only problem: almost all of them tell you to disable Security-Enhanced Linux to get the controller to work. That wasn’t a permanent option, so after setting the WiFi controller up I went about figuring out how to make it play nicely with SELinux.
Installing the UniFi controller
Note: this section is largely paraphrased from here.
First, we’ll need to install MongoDB for UniFi’s use. To do this, we’ll need a repo file for Mongo so
yum knows where to find it.
[mongodb] name=MongoDB Repository baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/ gpgcheck=0 enabled=1
That in place, we install Mongo and some other necessary stuff:
yum -y install mongodb-org mongodb-org-server java-1.7.0-openjdk unzip wget
We add a user for the UniFi controller:
useradd -r unifi
Now we download the UniFi controller software (written in Java) to
wget http://dl.ubnt.com/unifi/3.2.1/UniFi.unix.zip unzip -q UniFi.unix.zip -d /opt chown -R unifi:unifi /opt/UniFi
We want the controller software to start up with our server, and the easiest way to get that right in newer versions of CentOS is to write a
systemd script for Unifi. So we make a new file in the appropriate folder and write some stuff to it:
# Systemd unit file for UniFi Controller [Unit] Description=UniFi AP Web Controller After=syslog.target network.target [Service] Type=simple User=unifi ExecStart=/usr/bin/java -Xmx1024M -jar /opt/UniFi/lib/ace.jar start ExecStop=/usr/bin/java -jar /opt/UniFi/lib/ace.jar stop SuccessExitStatus=143 [Install] WantedBy=multi-user.target
Now that that’s done we just need to enable MongoDB and the module we just wrote:
systemctl enable unifi.service chkconfig mongod on
The controller web interface is now available at https://serveripaddressgoeshere:8443. Or it would be if you had SELinux disabled. Feel free to disable SELinux temporarily and play around with it, but remember to come back for the next section of this tutorial.
To get it to work without disabling SELinux, we need to assure SELinux that the controller is a legitimate program and that its operations are trustworthy. There are basically three ways to go about doing this:
- Set SELinux file permissions (a fine-grained system for controlling what processes can do what on each file) correctly for the program’s files.
- Set SELinux booleans correctly for our operations (stuff like “can host webserver accessible by outside network = true”).
- Write a new SELinux policy to allow the program to do what it needs to.
Ideally you want to avoid the third method, although it’s probably the easiest and most likely to get things to work – a policy of writing policies for every little thing just makes security even more complicated than it already is. So my solution ended up being a mix of the first and second methods.
First off, we’ll need to install
semanage, the program which lets us do all the SELinux configuration stuff we’re about to do. It’s provided by
policycoreutils-python, so we do the following:
yum -y install policycoreutils-python
Now we can start configuring SELinux. First, let’s tell it about MongoDB’s default ports:
semanage port -m -t mongod_port_t 27117 semanage port -m -t mongod_port_t 27017
Then we give MongoDB access to some of the UniFi controller software’s folders.
chcon -R --type=mongod_var_lib_t /opt/UniFi/data chcon -R --type=mongod_var_lib_t /opt/UniFi/logs
Now we specify that we’ll be allowing UniFi to run a web server by giving httpd (HTTP daemon):
chcon -R --type=httpd_sys_content_t /opt/UniFi/lib chcon -R --type=httpd_sys_content_t /opt/UniFi/webapps chcon -R --type=httpd_sys_content_t /opt/UniFi/work
Note that if
restorecon, a command that resets all SELinux file permissions, is run on the file system, these settings will be lost. Making them permanent is left as an exercise to the reader.
Now that that’s done, we can set our SELinux booleans to allow our server to host a web server.
setsebool -P httpd_can_network_connect=1 setsebool -P httpd_can_network_connect_db=1
And we’re done. If everything’s gone well, we should now be able to connect to the UniFi controller admin web interface over https://serveripaddressgoeshere:8443. If not, well, sorry. :(
It’s a good idea to set up a firewall at this point, which again I’ll leave as an exercise for the reader (use
firewalld or whatever else floats your boat). Unifi uses these TCP ports by default:
- 8081 (for management purpose)
- 8080 (device inform)
- 8443 (controller UI / API)
- 8880 (portal redirect port for HTTP)
- 8843 (portal redirect port for HTTPs)
- 27117 (local-bound port for DB server)
And this UDP port:
Lastly, keep in mind that UniFi WiFi access points should probably not be used as frisbees.