179 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
ifchd, copyright (c) 2004-2010 Nicholas Kain.  Licensed under GNU GPL.
 | 
						|
 | 
						|
Requirements:
 | 
						|
 | 
						|
Linux kernel (tested: 2.4, 2.6)
 | 
						|
        * libcap is required (available via ftp.kernel.org)
 | 
						|
 | 
						|
C99-compliant C compiler (for C99 struct subobject init)
 | 
						|
        * any modern GCC should be sufficient
 | 
						|
 | 
						|
CMake (tested: 2.8)
 | 
						|
 | 
						|
Tested with glibc 2.2.x and 2.3.x.  dietlibc is not compatible.  I have not yet
 | 
						|
tested uclibc.
 | 
						|
 | 
						|
I may bother to port to other operating systems, but don't count on it.
 | 
						|
 | 
						|
INTRODUCTION
 | 
						|
------------
 | 
						|
 | 
						|
ndhc consists of a set of daemons that cooperate in order to provide
 | 
						|
privilege-seperated dhcp client services.  Each daemon runs with the minimal
 | 
						|
necessary privileges in order to perform its task.  Currently, ndhc consists of
 | 
						|
two daemons: the eponymous ndhc and ifchd.
 | 
						|
 | 
						|
ndhc communicates with dhcp servers and handles the vagaries of the dhcp
 | 
						|
client protocol.  It runs as a non-root user inside a chroot.  ndhc retains
 | 
						|
only the minimum necessary set of privileges required to perform its duties.
 | 
						|
These powers include the ability to bind to a low port, the ability to open a
 | 
						|
raw socket, and the ability to communicate on broadcast channels.  ndhc holds
 | 
						|
no other powers and is restricted to a chroot that contains nothing more than a
 | 
						|
domain socket filesystem object and (at least on Linux) a urandom device node.
 | 
						|
 | 
						|
ifchd handles interface change requests.  It listens on a UNIX domain socket
 | 
						|
for such requests, and denies any client that does not match an authorized gid,
 | 
						|
uid, or pid.  ifchd runs as a non-root user inside a chroot, and retains only
 | 
						|
the power to configure network interfaces.  ifchd is designed so that it has
 | 
						|
the ability to service multiple client requests simultaneously; a single ifchd
 | 
						|
is sufficient for multiple ndhc clients.  Only exotic setups should require
 | 
						|
this functionality, but it does exist.
 | 
						|
 | 
						|
Note that ndhc does not support the entire DHCP client protocol.  Only the
 | 
						|
minimum necessary featureset is implemented.  This behavior should be familiar
 | 
						|
to anyone who has used software that purports to be be secure.
 | 
						|
 | 
						|
Many of the features that ndhc depends upon are not entirely standard and vary
 | 
						|
between UNIX systems.  It is likely that some effort will be required in order
 | 
						|
to port ndhc to new systems.  The ndhc daemon should be entirely portable aside
 | 
						|
from its use of Linux-style POSIX capabilities.
 | 
						|
 | 
						|
ifchd is necessarily less portable, since it must use system-specific ioctls in
 | 
						|
order to configure network interfaces.  Additionally, ifchd uses extensions to
 | 
						|
the UNIX domain socket family to limit connections to user defined subsets of
 | 
						|
possible uids, gids, and pids.  These extensions are present in Linux and BSD,
 | 
						|
although both Linux and BSD have different interfaces for the functionality.
 | 
						|
Patches that provide support for new systems are welcome.
 | 
						|
 | 
						|
USAGE
 | 
						|
-----
 | 
						|
 | 
						|
1) Compile and install ifchd and ndhc.
 | 
						|
    a) Create a build directory:
 | 
						|
       mkdir build && cd build
 | 
						|
    b) Create the makefiles:
 | 
						|
       cmake ..
 | 
						|
    c) Build ifchd and ndhc:
 | 
						|
       make
 | 
						|
    d) Install the ifchd/ifchd and ndhc/ndhc executables in a normal place.  I
 | 
						|
       would suggest /usr/sbin or /usr/local/sbin.
 | 
						|
 | 
						|
2) Time to create the jail in which ifchd and ndhc will run.
 | 
						|
    a) Become root and create new group "ifchd".
 | 
						|
 | 
						|
        $ su -
 | 
						|
        # umask 077
 | 
						|
        # groupadd ifchd
 | 
						|
 | 
						|
    b) Create new users "ifchd" and "dhcp".  The primary group of these
 | 
						|
       users should be "ifchd".
 | 
						|
 | 
						|
        # useradd -d /var/lib/ndhc -s /sbin/nologin -g ifchd ifchd
 | 
						|
        # useradd -d /var/lib/ndhc -s /sbin/nologin -g ifchd dhcp
 | 
						|
 | 
						|
    b) Create the jail directory and set its ownership properly.
 | 
						|
 | 
						|
        # mkdir /var/lib/ndhc
 | 
						|
        # chown ifchd.ifchd /var/lib/ndhc
 | 
						|
        # chmod a+rx /var/lib/ndhc
 | 
						|
 | 
						|
    c) Create a urandom device for ndhc to use within the jail.
 | 
						|
 | 
						|
        # cd /var/lib/ndhc
 | 
						|
        # mkdir dev
 | 
						|
        # mknod dev/urandom c 1 9
 | 
						|
        # chown -R root.root dev
 | 
						|
        # chmod a+rx dev
 | 
						|
        # chmod a+r dev/urandom
 | 
						|
 | 
						|
        d) (optional) If you wish for logging to properly work, you
 | 
						|
           will need to properly configure your logging daemon so that it
 | 
						|
           opens a domain socket in the proper location within the jail.
 | 
						|
           Since this varies per-daemon, I cannot provide a general
 | 
						|
           configuration.
 | 
						|
 | 
						|
3)  At this point the jail is usable; ifchd and ndhc are ready to
 | 
						|
    be used.  As an example of a sample configuration, here is my
 | 
						|
    rc.dhcp:
 | 
						|
 | 
						|
--START--
 | 
						|
 | 
						|
#!/bin/sh
 | 
						|
case "$1" in
 | 
						|
        start)
 | 
						|
                ifchd -i wan0 -p /var/run/ifchd.pid -u ifchd -g ifchd -U dhcp \
 | 
						|
                      -G ifchd -c /var/lib/ndhc &> /dev/null
 | 
						|
                ndhc -b -i wan0 -u dhcp -C /var/lib/ndhc &> /dev/null
 | 
						|
                ;;
 | 
						|
        stop)
 | 
						|
                killall ndhc ifchd
 | 
						|
                ;;
 | 
						|
esac
 | 
						|
 | 
						|
--END--
 | 
						|
 | 
						|
    This script works fine with my personal machines, which are set up
 | 
						|
    exactly as I have outlined above.  If you have not entirely followed my
 | 
						|
    directions, the script will of course require modifications.
 | 
						|
 | 
						|
4o) If you encounter problems, I suggest running both ifchd and ndhc in the
 | 
						|
   foreground, and perhaps compiling ndhc with extra debugging output
 | 
						|
   (uncomment DEBUG=1 in the Makefile).
 | 
						|
 | 
						|
 | 
						|
BEHAVIOR NOTES
 | 
						|
--------------
 | 
						|
 | 
						|
ifchd does not enable updates of the local hostname and resolv.conf by default.
 | 
						|
If you wish to enable these functions, use the --resolve (-r) and --hostname
 | 
						|
(-o) flags.  See ifchd --help.
 | 
						|
 | 
						|
ifchd can be set such that it only allows clients to configure particular
 | 
						|
network interfaces.  The --interface (-i) argument does the trick, and may
 | 
						|
be used multiple times to allow multiple interfaces.
 | 
						|
 | 
						|
GRSECURITY NOTES
 | 
						|
----------------
 | 
						|
 | 
						|
Make sure that CONFIG_GRKERNSEC_CHROOT_CAPS is disabled.  Otherwise, ifchd will
 | 
						|
lose its capabilities (in particular, the ability to reconfigure interfaces)
 | 
						|
when it chroots.
 | 
						|
 | 
						|
 | 
						|
PORTING NOTES
 | 
						|
-------------
 | 
						|
 | 
						|
Unportable functions are isolated to linux.c.  Any attempts to port ifchd to
 | 
						|
other platforms should isolate platform-dependent code to similarly named
 | 
						|
compilation units (eg: for FreeBSD, freebsd.[ch]).
 | 
						|
 | 
						|
There are four major functions that ifchd depends upon that are not generally
 | 
						|
portable.  First, it uses the SO_PEERCRED flag of getsockopt() to discriminate
 | 
						|
authorized connections by uid, gid, and pid.  Similar functionality exists in
 | 
						|
at least the BSDs; however, it has a different API.  Second, ifchd takes
 | 
						|
advantage of Linux capabilities so that it does not need full root privileges.
 | 
						|
Capabilities are supposedly a POSIX feature, but in practice, they vary greatly
 | 
						|
from system to system.  Third and fourth, ifchd configures network interfaces
 | 
						|
and routes.  Interface and route configuration is entirely non-portable,
 | 
						|
usually requiring calls to the catch-all ioctl(), and will almost certainly
 | 
						|
require platform-dependent code.
 | 
						|
 | 
						|
Some standard C libraries include a native implementation of strlcpy() and
 | 
						|
strlcat().  Such defines may conflict with my implementations in strl.c/strl.h.
 | 
						|
It is up to the user whether the standard C library implementations should be
 | 
						|
used.  Note that some machines implement strlcpy() and strlcat() with
 | 
						|
nonstandard semantics (notably Solaris).  On these systems, using the
 | 
						|
system-provided implementations may lead to security problems.  Such problems
 | 
						|
are the fault of the vendor.  If you are unsure whether your system is correct
 | 
						|
or not, I suggest using the implementation that I provide.
 |