Update the README.

This commit is contained in:
Nicholas J. Kain 2014-03-10 01:09:25 -04:00
parent 1824802fb2
commit a130448d46

126
README
View File

@ -1,4 +1,4 @@
ndhc + ifchd, Copyright (C) 2004-2014 Nicholas J. Kain. ndhc, Copyright (C) 2004-2014 Nicholas J. Kain.
See LICENSE for licensing information. In short: Two-clause / New BSD. See LICENSE for licensing information. In short: Two-clause / New BSD.
Requirements: Requirements:
@ -10,10 +10,9 @@ libcap (available via ftp.kernel.org)
INTRODUCTION INTRODUCTION
------------ ------------
ndhc consists of a set of daemons that cooperate in order to provide ndhc is a multi-process, privilege-separated dhcp client. Each subprocess runs
privilege-separated dhcp client services. Each daemon runs with the minimal with the minimal necessary privileges in order to perform its task. Currently,
necessary privileges in order to perform its task. Currently, ndhc consists of ndhc consists of two subprocesses: the ndhc and ifch.
two daemons: the eponymous ndhc and ifchd.
ndhc communicates with dhcp servers and handles the vagaries of the dhcp 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 client protocol. It runs as a non-root user inside a chroot. ndhc retains
@ -23,13 +22,10 @@ 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 no other powers and is restricted to a chroot that contains nothing more than a
domain socket filesystem object and a urandom device node. domain socket filesystem object and a urandom device node.
ifchd handles interface change requests. It listens on a UNIX domain socket ifch handles interface change requests. It listens on a shared pipe for such
for such requests, and denies any client that does not match an authorized gid, requests. ifch runs as a non-root user inside a chroot, and retains only the
uid, or pid. ifchd runs as a non-root user inside a chroot, and retains only power to configure network interfaces. ifch automatically forks from ndhc
the power to configure network interfaces. ifchd is designed so that it has to perform its job.
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.
ndhc fully implements RFC5227's address conflict detection and defense. Great ndhc fully implements RFC5227's address conflict detection and defense. Great
care is taken to ensure that address conflicts will be detected, and ndhc also care is taken to ensure that address conflicts will be detected, and ndhc also
@ -48,14 +44,13 @@ to be more of an annoyance than a help. v6 LLAs work much better in practice.
FEATURES FEATURES
-------- --------
Privilege-separated. Neither ifchd or ndhc runs as full root, and capabilities Privilege-separated. ndhc does not run as root after initial startup, and
are divided between the programs. Both programs run in a chroot. capabilities are divided between the subprocesses. Both programs run in a
chroot.
Robust. ndhc performs no runtime heap allocations -- malloc() is never called Robust. ndhc performs no runtime heap allocations -- malloc() is never called
(and neither is brk(), mmap(), etc), and ndhc never performs recursive calls (and neither is brk(), mmap(), etc), and ndhc never performs recursive calls
and only stack-allocates fixed-length types, so stack depth is bounded, too. and only stack-allocates fixed-length types, so stack depth is bounded, too.
ifchd lightly uses malloc(), but no heap allocations have long lifetimes, and
are bounded from being large.
Active defense of IP address and IP collision avoidance. ndhc fully implements Active defense of IP address and IP collision avoidance. ndhc fully implements
RFC5227. It is capable of both a normal level of tenacity in defense, where RFC5227. It is capable of both a normal level of tenacity in defense, where
@ -64,17 +59,18 @@ in the case of a conflict, and of relentlessly defending a lease forever. In
either mode, it rate-limits defense messages, so it can't be tricked into either mode, it rate-limits defense messages, so it can't be tricked into
flooding by a hostile peer or DHCP server, either. flooding by a hostile peer or DHCP server, either.
Small. Both ndhc and ifchd avoid unnecessary outside dependencies and are Small. Both ndhc avoids unnecessary outside dependencies and is written in
written in plain C. The only library used is libcap, as the raw raw kernel API plain C. The only library used is libcap, as the raw raw kernel API for
for capabilities is not guaranteed to stay stable. capabilities is not guaranteed to stay stable.
Fast. ndhc filters input using the BPF/LPF mechanism so that uninteresting Fast. ndhc filters input using the BPF/LPF mechanism so that uninteresting
packets are dropped by the operating system before ndhc even sees the data. packets are dropped by the operating system before ndhc even sees the data.
ndhc also only listens to DHCP traffic when it's necessary. ndhc also only listens to DHCP traffic when it's necessary.
Flexible. ndhc can request particular IPs, send user-specified client IDs, Flexible. ndhc can request particular IPs, send user-specified client IDs,
write a file that contains the current lease IP, write PID files, etc. One write a file that contains the current lease IP, write PID files, etc.
ifchd session can service multiple ndhc sessions.
Self-contained. ndhc does not exec other processes, or rely on the shell.
Aware of the hardware link status. If you disconnect an interface on which Aware of the hardware link status. If you disconnect an interface on which
ndhc is providing dhcp service, it will be aware. When the link status ndhc is providing dhcp service, it will be aware. When the link status
@ -85,33 +81,33 @@ different, it will forget about the old lease and request a new one.
USAGE USAGE
----- -----
1) Compile and install ifchd and ndhc. 1) Compile and install ndhc.
a) gmake a) gmake
b) Install the build/ifchd and build/ndhc executables in a normal place. I b) Install the build/ndhc executable in a normal place. I would suggest
would suggest /usr/sbin or /usr/local/sbin. /usr/sbin or /usr/local/sbin.
1alt) Compile and install ifchd and ndhc. 1alt) Compile and install ndhc.
a) Create a build directory: a) Create a build directory:
mkdir build && cd build mkdir build && cd build
b) Create the makefiles: b) Create the makefiles:
cmake .. cmake ..
c) Build ifchd and ndhc: c) Build ndhc:
make make
d) Install the ifchd/ifchd and ndhc/ndhc executables in a normal place. I d) Install the ndhc/ndhc executable in a normal place. I would suggest
would suggest /usr/sbin or /usr/local/sbin. /usr/sbin or /usr/local/sbin.
2) Time to create the jail in which ifchd and ndhc will run. 2) Time to create the jail in which ndhc will run.
a) Become root and create new group "ifchd". a) Become root and create new group "ndhc".
$ su - $ su -
# umask 077 # umask 077
# groupadd ifchd # groupadd ndhc
b) Create new users "ifchd" and "dhcp". The primary group of these b) Create new users "ifch" and "dhcp". The primary group of these
users should be "ifchd". users should be "ndhc".
# useradd -d /var/lib/ndhc -s /sbin/nologin -g ifchd ifchd # useradd -d /var/lib/ndhc -s /sbin/nologin -g ndhc ifch
# useradd -d /var/lib/ndhc -s /sbin/nologin -g ifchd dhcp # useradd -d /var/lib/ndhc -s /sbin/nologin -g ndhc dhcp
b) Create the jail directory and set its ownership properly. b) Create the jail directory and set its ownership properly.
@ -122,7 +118,7 @@ USAGE
# mkdir var # mkdir var
# mkdir var/state # mkdir var/state
# mkdir var/run # mkdir var/run
# chown -R ifchd.ifchd var # chown -R dhcp.ndhc var
# chmod -R a+rx var # chmod -R a+rx var
# chmod g+w var/run # chmod g+w var/run
@ -142,21 +138,18 @@ USAGE
Since this varies per-daemon, I cannot provide a general Since this varies per-daemon, I cannot provide a general
configuration. configuration.
3) At this point the jail is usable; ifchd and ndhc are ready to 3) At this point the jail is usable; ndhc is ready to be used. As an example
be used. As an example of a sample configuration, here is my of a sample configuration, here is my rc.dhcp:
rc.dhcp:
--START-- --START--
#!/bin/sh #!/bin/sh
case "$1" in case "$1" in
start) start)
ifchd -i wan0 -p /var/run/ifchd.pid -u ifchd -g ifchd -U dhcp \ ndhc -b -i wan0 -u dhcp -U ifch -C /var/lib/ndhc &> /dev/null
-G ifchd -c /var/lib/ndhc &> /dev/null
ndhc -b -i wan0 -u dhcp -C /var/lib/ndhc &> /dev/null
;; ;;
stop) stop)
killall ndhc ifchd killall ndhc
;; ;;
esac esac
@ -166,20 +159,16 @@ esac
exactly as I have outlined above. If you have not entirely followed my exactly as I have outlined above. If you have not entirely followed my
directions, the script will of course require modifications. directions, the script will of course require modifications.
4o) If you encounter problems, I suggest running both ifchd and ndhc in the 4o) If you encounter problems, I suggest running both ndhc in the foreground
foreground and examining the printed output. and examining the printed output.
BEHAVIOR NOTES BEHAVIOR NOTES
-------------- --------------
ifchd does not enable updates of the local hostname and resolv.conf by default. ndhc 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 If you wish to enable these functions, use the --resolve (-R) and --hostname
(-o) flags. See ifchd --help. (-H) flags. See ndhc --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.
PORTING NOTES PORTING NOTES
------------- -------------
@ -189,29 +178,25 @@ of tasks that are platform-specific. ndhc is rather platform-dependent, and it
extensively uses Linux-specific features. Some of these features are also extensively uses Linux-specific features. Some of these features are also
available on the BSDs. available on the BSDs.
1) Both ndhc and ifchd use the SO_PEERCRED flag of getsockopt() to discriminate 1) ndhc takes advantage of Linux capabilities so that it does not need full
authorized connections by uid, gid, and pid. Similar functionality exists in
at least the BSDs; however, it has a different API.
2) ifchd takes advantage of Linux capabilities so that it does not need full
root privileges. Capabilities were a proposed POSIX feature that was not made root privileges. Capabilities were a proposed POSIX feature that was not made
part of the official standard, so any implemention that may exist will be part of the official standard, so any implemention that may exist will be
system-dependent. system-dependent.
3) ifchd configures network interfaces and routes. Interface and route 2) ndhc configures network interfaces and routes. Interface and route
configuration is entirely non-portable, usually requiring calls to the configuration is entirely non-portable, usually requiring calls to the
catch-all ioctl(), or even more unusual mechanisms like netlink sockets. catch-all ioctl(), or even more unusual mechanisms like netlink sockets.
4) ndhc uses netlink sockets extensively for both fetching data and hardware 3) ndhc uses netlink sockets extensively for both fetching data and hardware
link state change notification events. link state change notification events.
5) ndhc uses the Berkeley Packet Filter / Linux Packet Filter interfaces to 4) ndhc uses the Berkeley Packet Filter / Linux Packet Filter interfaces to
drop unwanted packets in kernelspace. This functionality is available on drop unwanted packets in kernelspace. This functionality is available on
most modern unix systems, but it is not standard. most modern unix systems, but it is not standard.
6) ndhc uses epoll() and signalfd(). These are Linux-specific. 5) ndhc uses epoll() and signalfd(). These are Linux-specific.
7) Numerous socket options are used, and the AF_PACKET socket family is used 6) Numerous socket options are used, and the AF_PACKET socket family is used
for raw sockets and ARP. These are largely Linux-specific, too. for raw sockets and ARP. These are largely Linux-specific, too.
HISTORY HISTORY
@ -230,10 +215,10 @@ for extreme security. A root privileged DHCP client would be nearly the
only root-owned process running on the machine, so I was highly motivated only root-owned process running on the machine, so I was highly motivated
to develop an alternative. to develop an alternative.
ifchd was first written entirely from scratch. It did not take long to write, A separate ifchd was first written entirely from scratch. It did not take long
since it is by design rather simple, and I was already familiar with to write, since it is by design rather simple, and I was already familiar with
the quirks of Linux capabilities. That left me with the choice of adapting the quirks of Linux capabilities. That left me with the choice of adapting an
an existing DHCP client or writing my own from scratch. existing DHCP client or writing my own from scratch.
At the time, I just wanted something that would work, so my choice was to At the time, I just wanted something that would work, so my choice was to
adapt udhcpc to work with ifchd. udhcpc was chosen since it was intended to adapt udhcpc to work with ifchd. udhcpc was chosen since it was intended to
@ -269,6 +254,13 @@ ifchd was in good shape and required little work. I ended up rewriting
ndhc. The only parts that remained from the original were the parts that ndhc. The only parts that remained from the original were the parts that
I had already rewritten before, and some of those were rewritten, too. I had already rewritten before, and some of those were rewritten, too.
Eventually ifchd was rewritten to extensively use a Ragel-generated DFA-based
parser to make it easier to verify correct behavior for all possible inputs.
Quite a while later, I eventually merged ifchd into the same binary as
ndhc and instead rely on forking subprocesses and using pipes for IPC. This
brought a lot of simplifications, particularly for user configuration.
The end result is a modern DHCP client is largely RFC-compliant, except where The end result is a modern DHCP client is largely RFC-compliant, except where
the RFCs dictate behavior that would be problematic, overly complex, useless, the RFCs dictate behavior that would be problematic, overly complex, useless,
or exploitable. DHCP is poorly specified, and real-world servers and clients or exploitable. DHCP is poorly specified, and real-world servers and clients
@ -284,7 +276,7 @@ have known about them otherwise.
GRSECURITY NOTES GRSECURITY NOTES
---------------- ----------------
Make sure that CONFIG_GRKERNSEC_CHROOT_CAPS is disabled. Otherwise, ifchd will Make sure that CONFIG_GRKERNSEC_CHROOT_CAPS is disabled. Otherwise, ndhc will
lose its capabilities (in particular, the ability to reconfigure interfaces) lose its capabilities (in particular, the ability to reconfigure interfaces)
when it chroots. when it chroots.