Skip to content

Latest commit

 

History

History
99 lines (59 loc) · 4.72 KB

File metadata and controls

99 lines (59 loc) · 4.72 KB

Jailing your apps using Linux Namespaces

If you have a recent Linux kernel (>2.6.26) you can use its support for namespaces for added security.

What are namespaces?

They are an elegant (more elegant than most of the jailing systems you might find in other operating systems) way to "detach" your processes from a specific layer of the kernel and assign them to a new one.

The 'chroot' system available on UNIX/Posix systems is a primal form of namespaces: a process sees a completely new file system root and has no access to the original one.

Linux extends this concept to the other OS layers (PIDs, users, IPC, networking etc.), so a specific process can live in a "virtual OS" with a new group of pids, a new set of users, a completely unshared IPC system (semaphores, shared memory etc.), a dedicated network interface and its own hostname.

uWSGI can "jail" its processes using Linux namespaces. Being a networked application, it will not switch networking namespaces, and to keep sysadmins reasonably sane, users are kept untouched too.

All this put together, a namespace-constrained uWSGI stack will not see other processes running in the system, will not be able to access other processes' IPC, will not be able to access the original root filesystem and will have a dedicated hostname.

A real world example: Jailing the uWSGI Control Center in Ubuntu 10.10

Let's start by creating a new root filesystem for our jail. You'll need debootstrap. We're placing our rootfs in /ns/001, and then create a 'uwsgi' user that will run the uWSGI server. We will use the chroot command to 'adduser' in the new rootfs, and we will install the Flask package, required by uwsgicc.

All this needs to be executed as root.

mkdir -p /ns/001
debootstrap maverick /ns/001
chroot /ns/001
# in the chroot jail now
adduser uwsgi
apt-get install mercurial python-flask
su - uwsgi
# as uwsgi now
git clone https://github.com/unbit/uwsgicc.git .
exit # out of uwsgi
exit # out of the jail

Now on your real system run

uwsgi --socket 127.0.0.1:3031 --chdir /home/uwsgi/uwsgi --uid uwsgi --gid uwsgi --module uwsgicc --master --processes 4 --namespace /ns/001:mybeautifulhostname

If all goes well, uWSGI will set /ns/001 as the new root filesystem, assign mybeautifulhostname as the hostname and hide the PIDs and IPC of the host system.

The first thing you should note is the uWSGI master becoming the pid 1 (the "init" process). All processes generated by the uWSGI stack will be reparented to it if something goes wrong. If the master dies, all jailed processes die.

Now point your webbrowser to your webserver and you should see the uWSGI Control Center interface.

Pay attention to the information area. The nodename (used by cluster subsystem) matches the real hostname as it does not make sense to have multiple jail in the same cluster group. In the hostname field instead you will see the hostname you have set.

Another important thing is that you can see all the jail processes from your real system (they will have a different set of PIDs), so if you want to take control of the jail you can easily do it.

Note

A good way to limit hardware usage of jails is to combine them with the cgroups subsystem.

.. seealso:: :doc:`Cgroups`

Reloading uWSGI

When running jailed, uWSGI uses another system for reloading: it'll simply tell workers to bugger off and then exit. The parent process living outside the namespace will see this and respawn the stack in a new jail.

How secure is this sort of jailing?

Hard to say! All software tends to be secure until a hole is found.

Additional filesystems

When app is jailed to namespace it only has access to its virtual jail root filesystem. If there is any other filesystem mounted inside the jail directory, it won't be accessible, unless you use namespace-keep-mount.

# app1 jail is located here
namespace = /apps/app1

# nfs share mounted on the host side
namespace-keep-mount = /apps/app1/nfs

This will bind /apps/app1/nfs to jail, so that jailed app can access it under /nfs directory

# app1 jail is located here
namespace = /apps/app1

# nfs share mounted on the host side
namespace-keep-mount = /mnt/nfs1:/nfs

If the filesystem that we want to bind is mounted in path not contained inside our jail, than we can use "<source>:<dest>" syntax for --namespace-keep-mount. In this case the /mnt/nfs1 will be binded to /nfs directory inside the jail.