Chrooting proxy services

From Gentoo Wiki
Jump to: navigation, search

Today there are many process isolation techniques. Most of therm are based on virtualization or containers. And less of them are focus on security... We will use hardened chroot to isolate Internet services.

Kernel options

To create hardened jail we need hardened-sources to be installed (it is wise to use one of hardened profiles). So emerge it:

root #emerge --ask sys-kernel/hardened-sources

Then set necessary hardened chroot options:

KERNEL make menuconfig options
Security options  --->
    Grsecurity  --->
        [*] Grsecurity
            Customize Configuration  --->
                Filesystem Protections  --->
                    [*] Chroot jail restrictions
                    [*]   Deny mounts
                    [*]   Deny double-chroots
                    [*]   Deny pivot_root in chroot
                    [*]   Enforce chdir("/") on all chroots
                    [*]   Deny (f)chmod +s
                    [*]   Deny fchdir and fhandle out of chroot
                    [*]   Deny mknod
                    [*]   Deny shmat() out of chroot
                    [*]   Deny access to abstract AF_UNIX sockets out of chroot
                    [*]   Protect outside processes
                    [*]   Restrict priority changes
                    [*]   Deny sysctl writes
                    [*]   Deny bad renames
                    [*]   Capability restrictions

Chroot

As en example, of building chroot services, take a look at home proxy server. Usual home proxy looks like:

                  +-------------------------------------------------------------+
                  | Chrooted sockd or torsocks <-> Other Internet applications  |
                  |      ^                                                      |
                  |      |                                                      |
                  |                                Chrooted          HTTP*      |
 +----------+     |  Chrooted  <->  Chrooted  <->    HAVP    <->    Internet    |
 | Internet | <-> | <-> Tor         Privoxy            +          applications  |
 +----------+     |                    ^           libClamAV                    |
                  |                    |                                        |
                  |                                                             |
                  |                 Chrooted                                    |
                  |                 FreshClam                                   |
                  +-------------------------------------------------------------+

Best way is write ebuild to do build chroot of the service!!! So generally for chroot tor service Gentoo user want run:

root #emerge --config net-misc/tor

and that is all... But developers don't want support so complicate ebuild. ;) So hire we show example of bash scripts to build chroot (shoold be in pkg_config() function in ebuild) and examples of chrooted init scripts for all shown above services.

First of all install services and build binary packages for them:

root #emerge --ask -b app-antivirus/clamav net-misc/tor net-proxy/dante net-proxy/havp net-proxy/privoxy net-proxy/torsocks

Then configure all of them, configuration is not a part of this how to... ;)

Next scripts build chroot services even if all executeble file system mounted as readonly and all writeable file system mounted as noexecutable. But you must allow write to / and /usr file system when execute it!

You must manually run build chroot scripts any time when you update or reconfigure the service or update his library!

Chrooted FreshClamAV

FILE /etc/init.d/clamdchrooted freshclam
#!/sbin/runscript
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

CHROOT="/usr/chroot/clamav"
PIDCLAMD="/var/run/clamav/clamd.pid"
PIDFRESH="/var/run/clamav/freshclam.pid"
daemon_clamd="/usr/sbin/clamd"
daemon_freshclam="/usr/bin/freshclam"
daemon_milter="/usr/sbin/clamav-milter"

extra_commands="logfix"

depend() {
        use net
        provide antivirus
}

get_config() {
        clamconf | sed 's/["=]//g' | \
        awk "{
        if(\$0==\"Config file: $1.conf\") S=1
        if(S==1&&\$0==\"\") {
                print \"$3\"
                exit
        }
        if(S==1&&\$1~\"^$2\$\") {
                print \$2!=\"disabled\"?\$2:\"$3\"
                exit
        }
        }"
}

checkconfig() {
        checkpath --directory \
                --owner "${CLAMAV_USER:-clamav}:${CLAMAV_GROUP:-clamav}" \
                --mode 0755 --directory `dirname ${CHROOT}${PIDCLAMD}`
        if [ ! -c ${CHROOT}/dev/null ] ; then
                mknod -m 666 ${CHROOT}/dev/null c 1 3
                mount -ro remount ${CHROOT}/dev
        fi
}

start() {
        # populate variables and fix log file permissions
        logfix

        if [ "${START_CLAMD}" = "yes" ]; then
                checkconfig || return 1
                if [ -S "${CHROOT}${clamd_socket}" ]; then
                        rm -f ${CHROOT}${clamd_socket}
                fi
                ebegin "Starting chrooted clamd"
                start-stop-daemon --start --quiet \
                        --nicelevel ${CLAMD_NICELEVEL:-0} \
                        --ionice ${IONICE_LEVEL:-0} \
                        --pidfile "${CHROOT}${PIDCLAMD}" \
                        --exec chroot ${CHROOT} ${daemon_clamd}
                eend $? "Failed to start clamd"
        fi

        if [ "${START_FRESHCLAM}" = "yes" ]; then
                checkconfig || return 1
                ebegin "Starting chrooted freshclam"
                start-stop-daemon --start --quiet \
                        --nicelevel ${FRESHCLAM_NICELEVEL:-0} \
                        --ionice ${IONICE_LEVEL:-0} \
                        --pidfile "${CHROOT}${PIDFRESH}" \
                        --exec chroot ${CHROOT} ${daemon_freshclam} -- -d --pid "${PIDFRESH}"
                retcode=$?
                if [ ${retcode} = 1 ]; then
                        eend 0
                        einfo "Virus databases are already up to date."
                else
                        eend ${retcode} "Failed to start freshclam"
                fi
        fi

        if [ "${START_MILTER}" = "yes" ]; then
                if [ -z "${MILTER_CONF_FILE}" ]; then
                        MILTER_CONF_FILE="/etc/clamav-milter.conf"
                fi

                ebegin "Starting clamav-milter"
                start-stop-daemon --start --quiet \
                        --nicelevel ${MILTER_NICELEVEL:-0} \
                        --ionice ${IONICE_LEVEL:-0} \
                        --exec ${daemon_milter} -- -c ${MILTER_CONF_FILE}
                eend $? "Failed to start clamav-milter"
        fi
}

stop() {
        if [ "${START_CLAMD}" = "yes" ]; then
                ebegin "Stopping chrooted clamd"
                start-stop-daemon --stop --pidfile "${CHROOT}${PIDCLAMD}" --quiet --name clamd
                eend $? "Failed to stop clamd"
        fi
        if [ "${START_FRESHCLAM}" = "yes" ]; then
                ebegin "Stopping chrooted freshclam"
                start-stop-daemon --stop --quiet \
                --pidfile "${CHROOT}${PIDFRESH}" \
                --name freshclam \
                --exec chroot ${CHROOT} ${daemon_freshclam} -- -K --pid "${PIDFRESH}"
                eend $? "Failed to stop freshclam"
        fi
        if [ "${START_MILTER}" = "yes" ]; then
                ebegin "Stopping clamav-milter"
                start-stop-daemon --stop --quiet --name clamav-milter
                eend $? "Failed to stop clamav-milter"
        fi
}

logfix() {
        clamd_socket=$(get_config clamd LocalSocket /run/clamav/clamd.sock)
        clamd_user=$(get_config clamd User clamav)
        freshclam_user=$(get_config freshclam DatabaseOwner clamav)

        if [ "${START_CLAMD}" = "yes" ]; then
                # fix clamd log permissions
                # (might be clobbered by logrotate or something)
                local logfile=$(get_config clamd LogFile)
                if [ -n "${CHROOT}${logfile}" ]; then
                        checkpath --quiet \
                                --owner "${clamd_user}":"${clamd_user}" \
                                --mode 640 \
                                --file ${CHROOT}${logfile}
                fi
        fi

        if [ "${START_FRESHCLAM}" = "yes" ]; then
                # fix freshclam log permissions
                # (might be clobbered by logrotate or something)
                local logfile=$(get_config freshclam UpdateLogFile)
                if [ -n "${CHROOT}${logfile}" ]; then
                        checkpath --quiet \
                                --owner "${freshclam_user}":"${freshclam_user}" \
                                --mode 640 \
                                --file ${CHROOT}${logfile}
                fi
        fi
}
FILE clamav-chroot.shBuild chrooted freshclam
#!/bin/bash
# 20150922
# GPL-3

PKGDIR="/usr/portage/packages"
CATEGORY="app-antivirus"
PN="clamav"
CHROOT="/usr/chroot/${PN}"
WORKD=`pwd`

# Cleaning chroot directory.
umount "${CHROOT}"/var/lib/${PN} "${CHROOT}"/var/log/${PN} "${CHROOT}"/var/run "${CHROOT}"/var/tmp "${CHROOT}"/dev 1>/dev/null 2>&1
rm -rf "${CHROOT}"

# Make comon directory and symlinks.
mkdir -p "${CHROOT}"/{dev,etc}
if [ -d /lib64 ]
    then
        mkdir -p "${CHROOT}"/{lib64,usr/lib64}
        cd "${CHROOT}" && ln -s lib64 lib
        cd "${CHROOT}/usr" && ln -s lib64 lib
    else
        mkdir -p "${CHROOT}"/{lib,usr/lib}
fi
mkdir -p /var/log/${PN} "${CHROOT}"/var/log/${PN} "${CHROOT}"/var/run "${CHROOT}"/var/tmp
chown -R ${PN}:${PN} /var/log/${PN} "${CHROOT}"/var/log/${PN}
chmod -R o-rwx /var/log/${PN} "${CHROOT}"/var/log/${PN}

# Extract package.
tar -xjphf `ls ${PKGDIR}/${CATEGORY}/${PN}-0* |tail -n 1` -C "${CHROOT}"

# Copy nessesury libriary.
cp -pRPd /lib/ld-* "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/bin/freshclam" | awk '{print $3}'|grep "^/lib"` "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/bin/freshclam" | awk '{print $3}'|grep "^/usr/lib"` "${CHROOT}/usr/lib"

# Copy user information and nessesury libriary for it.
cp -pRPd /lib/libnss* /lib/libnsl* /lib/libresolv* "${CHROOT}/lib"
cp /usr/lib/libnss3.so "${CHROOT}/usr/lib"
grep "^${PN}" "/etc/passwd" > "${CHROOT}/etc/passwd"
grep "${PN}" "/etc/group" > "${CHROOT}/etc/group"

# fstab stuff.
if [[ `grep "Clamav chroot stuff." /etc/fstab` == '' ]]
    then
        cat >> /etc/fstab << EOF

# Clamav chroot stuff.
/var/lib/${PN}                  ${CHROOT}/var/lib/${PN}         none    bind,nodev,noexec,nosuid,rw                                     0 0
/var/log/${PN}                  ${CHROOT}/var/log/${PN}         none    bind,nodev,noexec,nosuid,rw                                     0 0
/var/tmp/havp                   ${CHROOT}/var/tmp                               none    bind,nodev,noexec,nosuid,user=${PN},ro                          0 0
none                            ${CHROOT}/var/run                       tmpfs   rw,nodev,noexec,nosuid,relatime,size=1024k,mode=755             0 0
none                            ${CHROOT}/dev                           tmpfs   rw,noexec,nosuid,relatime,size=1024k,nr_inodes=384443,mode=755          0 0
EOF
fi
mount -a

# Configuration.
cp -fp /etc/freshclam.conf ${CHROOT}/etc/
cp -fp /etc/clamd.conf ${CHROOT}/etc/
cd ${WORKD}
cp -f clamd /etc/init.d/
cp -f clamd ${CHROOT}/etc/init.d/

exit 0

Chrooted Dante Sockd

FILE /etc/init.d/dante-sockdchrooted dante-sockd
#!/sbin/runscript
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

CHROOT=/usr/chroot/dante
SOCKD_OPT=""
[ "${SOCKD_FORKDEPTH:-1}" -gt 1 ] && SOCKD_OPT="${SOCKD_OPT} -N ${SOCKD_FORKDEPTH}"
[ "${SOCKD_DEBUG:-0}" -eq 1 ] && SOCKD_OPT="${SOCKD_OPT} -d"
[ "${SOCKD_DISABLE_KEEPALIVE:-0}" -eq 1 ] && SOCKD_OPT="${SOCKD_OPT} -n"
PIDFILE=/var/run/dante/sockd.pid
SOCKDIR=/var/lock/dante-sockd/

depend() {
        need net
}

checkconfig() {
        # first check that it exists
        if [ ! -f ${CHROOT}/etc/socks/sockd.conf ] ; then
                eerror "You need to setup /etc/socks/sockd.conf first"
                eerror "Examples are in /usr/share/doc/dante[version]/example"
                eerror "for more info, see: man sockd.conf"
                return 1
        fi

        /usr/sbin/sockd -V -f ${CHROOT}/etc/socks/sockd.conf >/tmp/dante-sockd.checkconf 2>&1
        if [ $? -ne 0 ]; then
                cat /tmp/dante-sockd.checkconf
                eerror "Something is wrong with your configuration file"
                eerror "for more info, see: man sockd.conf"
                return 1
        fi
        rm /tmp/dante-sockd.checkconf

        DAEMON_UID=`sed -e '/^[ \t]*user[.]notprivileged[ \t]*:/{s/.*:[ \t]*//;q};d' /etc/socks/sockd.conf`

        if [ -n "$DAEMON_UID" ]; then
                checkpath --quiet --mode 755 --owner "${DAEMON_UID}":root --directory `dirname ${CHROOT}${PIDFILE}`
                checkpath --quiet --mode 750 --owner "${DAEMON_UID}":root --directory "${CHROOT}${SOCKDIR}"
        else
                checkpath --quiet --mode 755 --directory `dirname ${CHROOT}${PIDFILE}`
                checkpath --quiet --mode 750 --directory "${CHROOT}${SOCKDIR}"
        fi

        return 0
}

start() {
        checkconfig || return 1
        ebegin "Starting chrooted dante sockd"
        start-stop-daemon --start --quiet \
                --background --pidfile ${CHROOT}$PIDFILE --make-pidfile --env TMPDIR=$SOCKDIR \
                --exec chroot ${CHROOT} /usr/sbin/sockd -- ${SOCKD_OPT} >/dev/null 2>&1
        eend $? "Failed to start sockd"
}

stop() {
        ebegin "Stopping chrooted dante sockd"
        start-stop-daemon --stop --quiet --pidfile ${CHROOT}$PIDFILE
        eend $? "Failed to stop sockd"
}
FILE dante-chroot.shBuild chrooted dante-sockd
#!/bin/bash
# 20150922
# GPL-3

PKGDIR="/usr/portage/packages"
CATEGORY="net-proxy"
PN="dante"
CHROOT="/usr/chroot/${PN}"
USER="sockd"
WORKD=`pwd`

# Cleaning chroot directory.
umount "${CHROOT}"/var/lock/ "${CHROOT}"/var/log/${PN} "${CHROOT}"/var/run "${CHROOT}"/dev "${CHROOT}"/tmp 1>/dev/null 2>&1
rm -rf "${CHROOT}"

# Make comon directory and symlinks.
mkdir -p "${CHROOT}"/{dev,etc}
if [ -d /lib64 ]
    then
        mkdir -p "${CHROOT}"/lib64
        cd "${CHROOT}" && ln -s lib64 lib
    else
        mkdir -p "${CHROOT}"/{lib}
fi
mkdir -p /var/log/${PN} /var/tmp/${PN} "${CHROOT}"/var/log/${PN} "${CHROOT}"/var/lock "${CHROOT}"/var/run "${CHROOT}"/tmp
chown -R ${USER}:root /var/log/${PN} /var/tmp/${PN} "${CHROOT}"/var/log/${PN}
chmod -R o-rwx /var/log/${PN} /var/tmp/${PN} "${CHROOT}"/var/log/${PN}

# Extract package.
tar -xjphf `ls ${PKGDIR}/${CATEGORY}/${PN}* |tail -n 1` -C "${CHROOT}"

# Copy necessury libriary.
cp -pRPd /lib/ld-* "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/sbin/${USER}" |awk '{print $3}'|grep "^/lib"` "${CHROOT}/lib"

# Copy user information and necessury libriary for it.
cp -pRPd /lib/libnss* /lib/libnsl* /lib/libresolv* "${CHROOT}/lib"
cp /usr/lib/libnss3.so "${CHROOT}/usr/lib"
grep "^${USER}" "/etc/passwd" > "${CHROOT}/etc/passwd"

# fstab stuff.
if [[ `grep "Dante chroot stuff." /etc/fstab` == '' ]]
    then
        cat >> /etc/fstab << EOF

# Dante chroot stuff.
/var/log/${PN}                  ${CHROOT}/var/log/${PN}                 none    bind,nodev,noexec,nosuid,rw                                     0 0
/var/tmp/${PN}                  ${CHROOT}/tmp                   none    bind,nodev,noexec,nosuid,rw                                     0 0
none                            ${CHROOT}/var/lock                              tmpfs   rw,nodev,noexec,nosuid,relatime,size=1024k,mode=755             0 0
none                            ${CHROOT}/var/run                               tmpfs   rw,nodev,noexec,nosuid,relatime,size=1024k,mode=755             0 0
EOF
fi
mount -a

# Configuration.
cp -fp /etc/socks/* ${CHROOT}/etc/socks/
cp -fp /etc/conf.d/${PN}-sockd ${CHROOT}/etc/conf.d/
cd ${WORKD}
cp -f ${PN}-sockd /etc/init.d/
cp -f ${PN}-sockd ${CHROOT}/etc/init.d/

exit 0

Chrooted HAVP + libClamAV

FILE /etc/init.d/havpchrooted havp
#!/sbin/runscript
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

CHROOT=/usr/chroot/${SVCNAME}
PIDFILE=/var/run/${SVCNAME}/${SVCNAME}.pid

depend() {
#       need net
        use clamd \
#               squid apache2 bfilter mman junkbuster oops polipo privoxy tinyproxy tor wwwoffled
#       #havp could be used in conjuction with any parent proxies enumerated above
}

get_havp_opt() {
        eval HAVP_$1=`awk '/^[ \t]*'$1'[ \t]+/ { print $2; }' < /etc/${SVCNAME}/${SVCNAME}.config`
}

checkconfig() {
        if [ ! -f ${CHROOT}/etc/${SVCNAME}/${SVCNAME}.config ] ; then
                eerror "No ${CHROOT}/etc/${SVCNAME}/${SVCNAME}.config file exists!"
                return 1
        fi

        local HAVP_USER
        get_havp_opt USER
        if [ -n "${HAVP_USER}" ] && ! getent passwd ${HAVP_USER} > /dev/null ; then
                eerror "${HAVP_USER} user is missing!"
                return 1
        fi
        local HAVP_GROUP
        get_havp_opt GROUP
        if [ -n "${HAVP_GROUP}" ] && ! getent group ${HAVP_GROUP} > /dev/null ; then
                eerror "${HAVP_GROUP} group is missing!"
                return 1
        fi

        if [ ! -c ${CHROOT}/dev/null ] ; then
                mknod -m 666 ${CHROOT}/dev/null c 1 3
                mount -ro remount ${CHROOT}/dev
        fi

        checkpath --directory \
            --owner "${HAVP_USER:-havp}:${HAVP_GROUP:-havp}" --mode 0755 --directory `dirname ${CHROOT}${PIDFILE}`
        checkpath --directory \
            --owner "${HAVP_USER:-havp}:${HAVP_GROUP:-havp}" --mode 0700 ${CHROOT}/var/log/havp
        checkpath --directory \
            --owner "${HAVP_USER:-havp}:${HAVP_GROUP:-havp}" --mode 0750 "${CHROOT}/var/tmp/${SVCNAME}"
}

start() {
        checkconfig || return 1

        ebegin "Starting chrooted HTTP AntiVirus Proxy"
        start-stop-daemon --start --pidfile=${CHROOT}${PIDFILE} --exec chroot ${CHROOT} /usr/sbin/${SVCNAME} > /dev/null
        eend $?
}

stop() {
        local HAVP_PIDFILE
        get_havp_opt PIDFILE

        ebegin "Stopping chrooted HTTP AntiVirus Proxy"
        start-stop-daemon --stop --pidfile=${CHROOT}${PIDFILE}
        eend $?
}
FILE havp-chroot.shBuild chrooted havp
#!/bin/bash
# 20150922  havp-chroot.sh
# GPL-3

PKGDIR="/usr/portage/packages"
CATEGORY="net-proxy"
PN="havp"
CHROOT="/usr/chroot/${PN}"
WORKD=`pwd`

# Cleaning chroot directory.
umount "${CHROOT}"/var/lib/clamav "${CHROOT}/var/log/${PN}" "${CHROOT}"/var/run "${CHROOT}"/var/tmp "${CHROOT}"/dev 1>/dev/null 2>&1
rm -rf "${CHROOT}"

# Make comon directory and symlinks.
mkdir -p "${CHROOT}"/{dev,etc}
if [ -d /lib64 ]
    then
        mkdir -p "${CHROOT}"/{lib64,usr/lib64}
        cd "${CHROOT}" && ln -s lib64 lib
        cd "${CHROOT}/usr" && ln -s lib64 lib
    else
        mkdir -p "${CHROOT}"/{lib,usr/lib}
fi
mkdir -p /var/log/"${PN}" "/var/tmp/${PN}" "${CHROOT}"/var/lib/clamav "${CHROOT}/var/log/${PN}" "${CHROOT}"/var/tmp/ "${CHROOT}"/var/run
chown -R ${PN}:${PN} /var/log/${PN} /var/tmp/${PN} "${CHROOT}/var/log/${PN}"
chmod -R o-rwx /var/log/${PN} /var/tmp/${PN} "${CHROOT}/var/log/${PN}"
chmod -R g-rwx /var/log/${PN} "${CHROOT}"/var/log/${PN}

# Extract package.
tar -xjphf `ls ${PKGDIR}/${CATEGORY}/${PN}* |tail -n 1` -C "${CHROOT}"

# Copy nessesury libriary.
cp -pRPd /lib/ld-* "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/sbin/${PN}" |awk '{print $3}'|grep "^/lib"` "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/sbin/${PN}" |awk '{print $3}'|grep "^/usr/lib"` "${CHROOT}/usr/lib"
cp -pRPd /usr/lib/libclam* "${CHROOT}/usr/lib"
cp `ldd "${CHROOT}/usr/lib/libclamav.so" |awk '{print $3}'|grep "^/lib"` "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/lib/libclamav.so" |awk '{print $3}'|grep "^/usr/lib"` "${CHROOT}/usr/lib"
cp `ldd "${CHROOT}/usr/lib/libclamunrar_iface.so" |awk '{print $3}'|grep "^/lib"` "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/lib/libclamunrar_iface.so" |awk '{print $3}'|grep "^/usr/lib"` "${CHROOT}/usr/lib"
cp `ldd "${CHROOT}/usr/lib/libclamunrar.so" |awk '{print $3}'|grep "^/lib"` "${CHROOT}/lib"

# Copy user information and nessesury libriary for it.
cp -pRPd /lib/libnss* /lib/libnsl* /lib/libresolv* "${CHROOT}/lib"
cp /usr/lib/libnss3.so "${CHROOT}/usr/lib"
grep "^${PN}" "/etc/passwd" > "${CHROOT}/etc/passwd"
grep "^${PN}" "/etc/group" > "${CHROOT}/etc/group"

# fstab stuff.
if [[ `grep "HAVP chroot stuff." /etc/fstab` == '' ]]
    then
        cat >> /etc/fstab << EOF

# HAVP chroot stuff.
/var/lib/clamav                 ${CHROOT}/var/lib/clamav                        none    bind,nodev,noexec,nosuid,rw                                     0 0
/var/log/${PN}                  ${CHROOT}/var/log/${PN}                 none    bind,nodev,noexec,nosuid,rw                                     0 0
/var/tmp/${PN}                  ${CHROOT}/var/tmp                       none    bind,nodev,noexec,nosuid,rw                                     0 0
none                            ${CHROOT}/var/run                       tmpfs   rw,nodev,noexec,nosuid,relatime,size=1024k,mode=755             0 0
none                            ${CHROOT}/dev                           tmpfs   rw,noexec,nosuid,relatime,size=1024k,nr_inodes=384443,mode=755          0 0
EOF
fi
mount -a

# Configuration.
cp -fpRPd /etc/${PN}/* ${CHROOT}/etc/${PN}/
cd ${WORKD}
cp -f ${PN} /etc/init.d/
cp -f ${PN} ${CHROOT}/etc/init.d/

exit 0

Chrooted Privoxy

FILE /etc/init.d/privoxychrooted privoxy
#!/sbin/runscript
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

CHROOT=/usr/chroot/${SVCNAME}
CONFFILE=/etc/${SVCNAME}/config
PIDFILE=/var/run/${SVCNAME}/${SVCNAME}.pid

depend() {
        need net
}

checkconfig() {
        if [ ! -f "${CHROOT}/${CONFFILE}" ]; then
                eerror "Configuration file ${CHROOT}/${CONFFILE} not found!"
                return 1
        fi
        checkpath --quiet --mode 755 \
                --owner "${SVCNAME}":"${SVCNAME}" \
                --directory `dirname ${CHROOT}${PIDFILE}`
        if [ ! -c ${CHROOT}/dev/null ] ; then
                mknod -m 666 ${CHROOT}/dev/null c 1 3
                mount -ro remount ${CHROOT}/dev
        fi
}

start() {
        checkconfig || return 1

        ebegin "Starting chrooted privoxy"
        start-stop-daemon --start --quiet \
                --pidfile "${CHROOT}${PIDFILE}" \
                --exec chroot ${CHROOT} /usr/sbin/privoxy \
                -- --pidfile "${PIDFILE}" \
                --user privoxy.privoxy "${CONFFILE}" #2>/dev/null
        eend $?
}

stop() {
        ebegin "Stopping chrooted privoxy"
        start-stop-daemon --stop --quiet --pidfile "${CHROOT}${PIDFILE}"
        eend $?
}
FILE privoxy-chroot.shBuild chrooted privoxy
#!/bin/bash
# 20150922
# GPL-3

PKGDIR="/usr/portage/packages"
CATEGORY="net-proxy"
PN="privoxy"
CHROOT="/usr/chroot/${PN}"
WORKD=`pwd`

# Cleaning chroot directory.
umount "${CHROOT}"/var/log/${PN} "${CHROOT}"/var/run "${CHROOT}"/dev 1>/dev/null 2>&1
rm -rf "${CHROOT}"

# Make comon directory and symlinks.
mkdir -p "${CHROOT}"/{dev,etc}
if [ -d /lib64 ]
    then
        mkdir -p "${CHROOT}"/{lib64,usr/lib64}
        cd "${CHROOT}" && ln -s lib64 lib
        cd "${CHROOT}/usr" && ln -s lib64 lib
    else
        mkdir -p "${CHROOT}"/{lib,usr/lib}
fi

# Extract package.
tar -xjphf `ls ${PKGDIR}/${CATEGORY}/${PN}* |tail -n 1` -C "${CHROOT}"

# Copy nessesury libriary.
cp -pRPd /lib/ld-* "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/sbin/${PN}" | awk '{print $3}'|grep "^/lib"` "${CHROOT}/lib"
cp `ldd "${CHROOT}/usr/sbin/${PN}" | awk '{print $3}'|grep "^/usr/lib"` "${CHROOT}/usr/lib"

# Copy user information and nessesury libriary for it.
cp -pRPd /lib/libnss* /lib/libnsl* /lib/libresolv* "${CHROOT}/lib"
cp /usr/lib/libnss3.so "${CHROOT}/usr/lib"
grep "^${PN}" "/etc/passwd" > "${CHROOT}/etc/passwd"
grep "^${PN}" "/etc/group" > "${CHROOT}/etc/group"

# fstab stuff.
if [[ `grep "Privoxy chroot stuff." /etc/fstab` == '' ]];
    then
        cat >> /etc/fstab << EOF

# Privoxy chroot stuff.
/var/log/${PN}          ${CHROOT}/var/log/${PN}         none    bind,nodev,noexec,nosuid,rw                                     0 0
none                            ${CHROOT}/var/run                       tmpfs   rw,nodev,noexec,nosuid,relatime,size=1024k,mode=755             0 0
none                            ${CHROOT}/dev                           tmpfs   rw,noexec,nosuid,relatime,size=1024k,nr_inodes=384443,mode=755          0 0
EOF
fi
mount -a

# Configuration.
cp -frp /etc/${PN}/* ${CHROOT}/etc/${PN}/
cd ${WORKD}
cp -f ${PN} /etc/init.d/
cp -f ${PN} ${CHROOT}/etc/init.d/

exit 0

Chrooted Tor

FILE /etc/init.d/torchrooted tor
#!/sbin/openrc-run
# Copyright 1999-2017 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

CHROOT=/opt/torchroot
PIDFILE=/var/run/tor/tor.pid
CONFFILE=/etc/tor/torrc
SVCNAME=tor
GRACEFUL_TIMEOUT=${GRACEFUL_TIMEOUT:-60}

# See bug #523552, and https://trac.torproject.org/projects/tor/ticket/5525
# Graceful = wait 30 secs or so until all connections are properly closed.
extra_commands="checkconfig"
extra_started_commands="graceful gracefulstop reload"
description="Anonymizing overlay network for TCP"
description_checkconfig="Check for valid config file."
description_reload="Reload the configuration."
description_graceful="Gracefully restart."
description_gracefulstop="Gracefully stop."

depend() {
        need net
}

checkconfig() {
        # first check that it exists
        if [ ! -f ${CHROOT}${CONFFILE} ] ; then
                eerror "You need to setup ${CHROOT}${CONFFILE} first"
                eerror "Example is in ${CHROOT}${CONFFILE}.sample"
                return 1
        fi

        if [ ! -c ${CHROOT}/dev/random ] ; then
                mknod -m 666 ${CHROOT}/dev/null c 1 3
                mknod -m 644 ${CHROOT}/dev/random c 1 8
                mknod -m 644 ${CHROOT}/dev/urandom c 1 9
                mount -ro remount ${CHROOT}/dev
        fi

        #checkpath --quiet --mode 755 --owner "${SVCNAME}":"${SVCNAME}" --directory `dirname ${CHROOT}${PIDFILE}`

        # now verify whether the configuration is valid
        /usr/bin/${SVCNAME} --verify-config -f ${CHROOT}${CONFFILE} > /dev/null 2>&1
        if [ $? -eq 0 ] ; then
                einfo "Tor configuration (${CHROOT}${CONFFILE}) is valid."
                return 0
        else
                eerror "Tor configuration (${CHROOT}${CONFFILE}) not valid."
                /usr/bin/${SVCNAME} --verify-config -f ${CHROOT}${CONFFILE}
                return 1
        fi
}

start() {
        checkconfig || return 1
        ebegin "Starting chrooted Tor"
        HOME=/var/lib/${SVCNAME}
        start-stop-daemon --start --pidfile "${CHROOT}${PIDFILE}" --quiet --exec chroot ${CHROOT} /usr/bin/${SVCNAME} -- -f "${CONFFILE}" --runasdaemon 1 --PidFile "${PIDFILE}" > /dev/null 2>&1
        eend $?
}

stop() {
        ebegin "Stopping chrooted Tor"
        start-stop-daemon --stop --pidfile "${CHROOT}${PIDFILE}"
        eend $?
}

graceful() {
        gracefulstop
        start
        eend $?
}

gracefulstop() {
        local rc=0
        ebegin "Gracefully stopping chrooted Tor"
        ebegin "This can take up to ${GRACEFUL_TIMEOUT} seconds"
        start-stop-daemon -P --stop --signal INT -R ${GRACEFUL_TIMEOUT} --pidfile "${CHROOT}${PIDFILE}"
        rc=$?
        eend "done"
        eend $rc
}

reload() {
        if [ ! -f ${CHROOT}${PIDFILE} ]; then
                eerror "${SVCNAME} isn't running"
                return 1
        fi
        checkconfig || return 1
        ebegin "Reloading chrooted Tor configuration"
        start-stop-daemon --signal HUP --pidfile ${CHROOT}${PIDFILE}
        eend $?
}
FILE tor-chroot.shBuild chrooted tor
#!/bin/bash
# 20170826
# CC0
# torchroot generation script
export TORCHROOT=/opt/torchroot

mkdir -p $TORCHROOT
mkdir -p $TORCHROOT/etc/tor
mkdir -p $TORCHROOT/dev
mkdir -p $TORCHROOT/usr/bin
mkdir -p $TORCHROOT/usr/lib
mkdir -p $TORCHROOT/usr/share/tor
mkdir -p $TORCHROOT/var/lib

ln -s /usr/lib  $TORCHROOT/lib
# Replace this line if you want to copy your own torrc instead of the default one.
cp /etc/tor/torrc       $TORCHROOT/etc/tor/

cp /usr/bin/tor         $TORCHROOT/usr/bin/
cp /usr/share/tor/geoip* $TORCHROOT/usr/share/tor/
cp /lib/ld-linux-*.so* $TORCHROOT/usr/lib/
cp /lib/libnss* /lib/libnsl* /lib/libresolv* $TORCHROOT/usr/lib/
cp $(ldd /usr/bin/tor | awk '{print $3}'|grep --color=never "^/") $TORCHROOT/usr/lib/
cp -r /var/lib/tor      $TORCHROOT/var/lib/
chown -R tor:tor $TORCHROOT/var/lib/tor

sh -c "grep --color=never ^tor /etc/passwd > $TORCHROOT/etc/passwd"
sh -c "grep --color=never ^tor /etc/group > $TORCHROOT/etc/group"

mknod -m 644 $TORCHROOT/dev/random c 1 8
mknod -m 644 $TORCHROOT/dev/urandom c 1 9
mknod -m 666 $TORCHROOT/dev/null c 1 3

if [[ "$(uname -m)" == "x86_64" ]]; then
  cp /lib64/ld-linux-*.so* $TORCHROOT/usr/lib/
  ln -s /usr/lib ${TORCHROOT}/lib64
fi

Reminder

Also you must:

  • proper configure iptables, so only tor service can output packets to Internet;
  • proper setup proxy variables to all you internet applications and torify them;
  • install and proper configure some privacy addons to you browser.

See also