WelcomeWelcome | FAQFAQ | DownloadsDownloads | WikiWiki

Author Topic: HOWTO: (build and) chroot busybox's http daemon in TCL 2.0  (Read 9250 times)

Offline PingPing

  • Jr. Member
  • **
  • Posts: 99
HOWTO: (build and) chroot busybox's http daemon in TCL 2.0
« on: June 17, 2009, 01:17:58 PM »
Here's a little HOWTO I put together based off similar HOWTOs for Apache.  I chose BusyBox as the http server because, well, it's small and does the job I wanted it to: a home server.  All comments welcome.

First we need to create the user which we're going to chroot.  In this HOWTO I'll be using the user 'www' and also creating a new group of the same name:

    sudo addgroup -g 80 www
    sudo adduser -h /home/www -s /bin/false -G www www
    (enter any password you like)

Here I've created the user 'www' (the second 'www' in adduser), made it a member of the www group ('-g www'), given it a home directory of /home/www and set its login shell to /bin/false.  By doing the latter, there is no shell available for anyone trying to login as user 'www'.  This is a important security feature.

While Tiny Core Linux (TCL) uses BusyBox for its command line utilities, it was not built with BusyBox's httpd server, so we must compile it from source ourselves.  All of the necessary compile tools are available from the TCL 2.0 repos.  What is needed are the following:

gcc-binutils.tce
base_devs.tce
bison.tce
diffutils.tce
file.tcel
findutils.tce
flex.tce
gawk.tce
gperf.tce
grep.tce
help2man.tcel
m4.tce
make.tce
patch.tce
pkg-config.tce
sed.tce

Once we have these installed we need to download the BusyBox source code tarball, unpack it, change directory into the unpacked code and make a blank .config file:

    $  wget http://www.busybox.net/downloads/busybox-1.14.1.tar.gz
    $  tar -xzf busybox-1.14.1.tar.gz
    $  cd busybox-1.14.1
    $  make allnoconfig


Building BusyBox is similar to building the Linux kernel in that we 'make menuconfig && make install', so first we must configure the BusyBox build:

    $  make menuconfig

Here you'll be greeted with the kernel-esque type ncurses configuration menu.  Navigate to BusyBox Settings > Installation Options > BusyBox installation prefix.  You'll see that it's currently set to './_install'.  Change this to '/home/www' so that the binaries will be installed to /home/www which is going to be the top of our chrooted directory tree.  Next, get back to the main config menu page and go to Coreutils, scroll down and select 'false' (using the space bar).  Next, return to the main menu and go to Network Utilities and select httpd (again, using the space bar).  Now the selection will have expanded with a few more options.  Choose the one called 'Enable -u option (NEW)'.  You can leave everything else as it is.  Finally, exit the config saving your changes.  Now just:

    $  sudo make install

You should now see /home/www has been populated with the following:

bin/busybox
bin/false
usr/sbin/httpd

the latter two of which are soft links to the first.

Next we must copy some key files to /home/www to prepare it as the chrooted environment:

    $  sudo mkdir /home/www/etc /home/www/lib
    $  sudo cp /etc/group  /home/www/etc/
    $  sudo cp /etc/passwd  /home/www/etc/
    $  sudo cp /etc/shadow  /home/www/etc/
    $  sudo cp /etc/hosts  /home/www/etc/
    $  sudo cp /etc/hostname  /home/www/etc/
    $  sudo cp /etc/nsswitch.conf  /home/www/etc/
    $  sudo cp /etc/resolv.conf  /home/www/etc/
    $  sudo cp /lib/libnss_compat-2.9.so  /home/www/lib/libnss_compat.so.2
    $  sudo cp /lib/libnss_dns-2.9.so  /home/www/lib/libnss_dns.so.2
    $  sudo cp /lib/libnss_files-2.9.so  /home/www/lib/libnss_files.so.2
    $  sudo cp /lib/libc-2.9.so  /home/www/lib/libc.so.6
    $  sudo cp /lib/ld-2.9.so  /home/www/lib/ld-linux.so.2

Next, remove all lines in:

/home/www/etc/group
/home/www/etc/passwd
/home/www/etc/shadow

that don't refer to user/group 'www', ie. there should be just one line left in each file after the deletions.  Finally, make everything in /home/www owned by user 'www' and group 'www':

    sudo chown -R www.www /home/www

Finally, just create/add any index.html file in /home/www and start things up:

    sudo chroot /home/www /usr/sbin/httpd -u www:www

If you 'ps' you should see something like:

    7543  www     /usr/sbin/httpd -u www:www

Note the process ID (7543 in my case).  To test the chroot has worked:

    sudo ls -l /proc/7543/root

and you should see that /home/www is the start of the (chrooted) directory tree.
« Last Edit: June 17, 2009, 01:23:33 PM by PingPing »

Offline danielibarnes

  • Hero Member
  • *****
  • Posts: 548
Re: HOWTO: (build and) chroot busybox's http daemon in TCL 2.0
« Reply #1 on: June 17, 2009, 03:00:06 PM »
Nice job. I appreciate your sharing these details. I also do that when I can. I understand the effort involved in making instructions simple enough for others to be able to reproduce your work efficiently.

Some packages have a "make jail" script. You (or someone else) could use these instructions to write one for httpd and package it into an mini-webserver extension.

Offline PingPing

  • Jr. Member
  • **
  • Posts: 99
Re: HOWTO: (build and) chroot busybox's http daemon in TCL 2.0
« Reply #2 on: June 29, 2009, 05:45:34 AM »
I've done a script.  The script assumes busybox's httpd (and false) has been compiled and installed to /usr/local/httpd:
Code: [Select]
###
### setup group, user and password for user 'www' in TCL
###

sudo addgroup -g 80 www
sudo adduser -h /home/www -s /bin/false -G www -D www
echo www:tinycore > sudo chpasswd

###
### setup group, user and password for user 'www' in chroot
###

sudo chown tc:staff /home/www
mkdir /home/www/etc
cat /etc/group | grep www > /home/www/etc/group
cat /etc/passwd | grep www > /home/www/etc/passwd
sudo cat /etc/shadow | grep www > /home/www/etc/shadow

###
### copy relevent /etc and /lib files to chroot environment
###

ETCS="hostname hosts nsswitch.conf resolv.conf"
for STR in $ETCS; do
  sudo cp -p /etc/$STR /home/www/etc/
done
mkdir /home/www/lib
LIBS="ld-2.9.so ld-linux.so.2 \
   libc-2.9.so libc.so.6 \
   libnss_compat-2.9.so libnss_compat.so.2 \
   libnss_dns-2.9.so libnss_dns.so.2 \
   libnss_files-2.9.so libnss_files.so.2"
for STR in $LIBS; do
  sudo cp -dp /lib/$STR /home/www/lib/
done

###
### move busybox's httpd to chroot environment
###

mkdir -p /home/www/usr/local/httpd/bin
sudo mv -f /usr/local/httpd/bin/busybox /usr/local/httpd/bin/false /home/www/usr/local/httpd/bin/
mkdir -p /home/www/usr/local/httpd/sbin
sudo mv -f /usr/local/httpd/sbin/httpd /home/www/usr/local/httpd/sbin/

###
### setup document root in chroot environment for busybox's httpd
###

mkdir /home/www/htdocs
echo "<html><body><h1>It works!</h1></body></html>" > /home/www/htdocs/index.html

###
### finally, set ownership permissions
###

sudo chown -R root:root /home/www
sudo chown -R www:www /home/www/htdocs
sudo chown www:www /home/www
EDIT:

FWIW, here's the httpd build script:
Code: [Select]
###
### grab the tarball and unpack
###

VERS=1.14.2
wget -q http://www.busybox.net/downloads/busybox-$VERS.tar.gz
tar -xzf busybox-$VERS.tar.gz

###
### make a blank configuration file, then tailor it for httpd, then remake
###

cd busybox-$VERS
make allnoconfig
CONF_HEADERS="INSTALL_NO_USR \
FALSE \
HTTPD \
FEATURE_HTTPD_SETUID \
FEATURE_HTTPD_BASIC_AUTH \
FEATURE_HTTPD_CGI \
FEATURE_HTTPD_ENCODE_URL_STR"
for STR in $CONF_HEADERS; do
  sed -i "s/# CONFIG_$STR is not set/CONFIG_$STR=y/" .config
done
make

###
### install, copy binaries and links to /tmp
###

sudo make install
mkdir -p /tmp/httpd/usr/local/httpd/bin
mkdir -p /tmp/httpd/usr/local/httpd/sbin
sudo cp -p _install/bin/busybox /tmp/httpd/usr/local/httpd/bin/
sudo cp -pP _install/bin/false /tmp/httpd/usr/local/httpd/bin/
sudo cp -pP _install/sbin/httpd /tmp/httpd/usr/local/httpd/sbin/
cd -

###
### make .tce
###

cd /tmp/httpd
find usr -not -type d > ../busybox-httpd.filelist
tar czf busybox-httpd.tce --numeric-owner -T ../busybox-httpd.filelist
advdef -z4 busybox-httpd.tce
cd -
mv /tmp/httpd/busybox-httpd.tce .
md5sum busybox-httpd.tce > busybox-httpd.tce.md5.txt

###
### make .tcz
###

mkfs.cramfs /tmp/httpd busybox-httpd.tcz
md5sum busybox-httpd.tcz > busybox-httpd.tcz.md5.txt

Maybe some of the TCL devs (if they've got time) can give me a heads up on the FEATURE_HTTPDs before I create and submit .tces and .tczs?

EDIT:
Changed the build script.
« Last Edit: July 02, 2009, 07:14:41 AM by PingPing »

Offline danielibarnes

  • Hero Member
  • *****
  • Posts: 548
Re: HOWTO: (build and) chroot busybox's http daemon in TCL 2.0
« Reply #3 on: June 29, 2009, 02:40:33 PM »
I'll give those scripts a try when I get a chance. A few suggestions:

replace
cat /etc/group | grep www > /home/www/etc/group

with the shorter
grep www /etc/group > /home/www/etc/group

add -l when copying libs to save space by creating hard links where possible
sudo cp -dpl /lib/$STR /home/www/lib/ 2>/dev/null || sudo cp -dp /lib/$STR /home/www/lib/

instead of
sudo cp -dp /lib/$STR /home/www/lib/

Don't forget /dev/null

I also have an example of chroot in my scponly extension. Here is the "mkscproot" script:
Code: [Select]
#!/bin/sh

usage() {
echo "Usage: $THISFILE -u [username]"
echo "Default username is scponlyuser"
exit 1
}

THISFILE=$(basename $(readlink -f $0))
[ "-u" != "$1" ] && usage

SCPUSER=${2:-scponlyuser}
SCPONLYC=/usr/local/sbin/scponlyc

# Add the user but remove ownership from home directory
adduser -D -s $SCPONLYC $SCPUSER
chown -R 0:0 /home/$SCPUSER

# Create chroot environment
SFTP=$(find /usr -name sftp-server|head -1)
cd /home/$SCPUSER
mkdir -p .ssh/
mkdir -p bin/
mkdir -p etc/
mkdir -p lib/
mkdir -p usr/bin/
mkdir -p usr/lib/
mkdir -p usr/libexec/
mkdir -p usr/sbin/
mkdir -p usr/local/bin/
ln /bin/busybox bin/
ln /usr/sbin/dropbearmulti usr/sbin/
cp -L /usr/local/bin/groups usr/local/bin/
cp -L $SFTP usr/libexec/
for f in $SFTP /bin/busybox /usr/sbin/dropbearmulti /usr/local/bin/groups; do
for l in $(ldd $f|grep -v -E 'linux-gate'|cut -d' ' -f3); do
SRC=$(readlink -f $l)
DST=$(echo .$l|sed 's:local/::')
mkdir -p $(dirname $DST)
[ -e $DST ] || ln $SRC $DST >/dev/null 2>&1 || cp -L $SRC $DST
done
done
for l in ld-linux.so.2 libnss_files.so.2; do
ln $(readlink -f /lib/$l) lib/$l
done
grep $SCPUSER /etc/passwd > etc/passwd
grep $SCPUSER /etc/group > etc/group
chown 0:0 etc/passwd etc/group
ln -s busybox bin/rm
ln -s busybox bin/ln
ln -s busybox bin/ls
ln -s busybox bin/mv
ln -s busybox bin/chmod
ln -s busybox bin/chown
ln -s busybox bin/chgrp
ln -s busybox bin/mkdir
ln -s busybox bin/rmdir
ln -s busybox bin/pwd
ln -s busybox bin/echo
ln -s ../../bin/busybox usr/bin/id
ln -s ../sbin/dropbearmulti usr/bin/scp
mkdir dev
cd dev
mknod -m 666 null c 1 3

With all of this code, I highly suspect this thread will get moved to "Programming & Scripting" :)

Offline PingPing

  • Jr. Member
  • **
  • Posts: 99
Re: HOWTO: (build and) chroot busybox's http daemon in TCL 2.0
« Reply #4 on: June 29, 2009, 09:16:57 PM »
Thx for the continued advice.  I'm still a scripting newbie and always interested to learn how to improve my scripts.

I'd really appreciate some feedback from someone about the BusyBox build choices for the CONFIG_FEATURE_HTTPDs.  At the moment I'm only using 4 of the possible 9 (?).  Should I include more in the .tce/.tcz builds?

Offline PingPing

  • Jr. Member
  • **
  • Posts: 99
Re: HOWTO: (build and) chroot busybox's http daemon in TCL 2.0
« Reply #5 on: July 01, 2009, 05:10:00 AM »
I've attached the scripts if anyone's interested.

EDIT:  
edited above scripts to show revised location of binaries being usr/local/httpd not usr/local.
attached revised scripts. 
Additionally, it needs to be pointed out that the chroot script will only work with .tces and not .tczs.
« Last Edit: July 02, 2009, 07:11:24 AM by PingPing »