Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[HOWTO] Chroot Jails && pam_chroot
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
Reikinio
Apprentice
Apprentice


Joined: 14 Aug 2005
Posts: 203
Location: Uruguay

PostPosted: Sun Aug 28, 2005 1:31 am    Post subject: [HOWTO] Chroot Jails && pam_chroot Reply with quote

Introduction
Chroot jails are powerful mechanisms to secure your system, the idea is to lock certain users/daemons to run with a restricted filesystem, , surrounded only by files chosen by a paranoid system administrator.
Quote:
... pam_chroot is a Linux-PAM module that allows a user to be chrooted in auth, account, or session. The pam_chroot configuration employs a flexible syntax which allows for a user to be selectively chrooted based upon username or group membership. ...

So, instead of using the ugly 'su, sudo' mechanism you can use pam_chroot, which is better.
See how useful PAM is ? 8)

System organization
It is very important to be tidy, here is an example:
Directories:

'/root/jailskels/' This directory contains 'chroot jails' related material, which includes: jail-maker scripts, and any other stuff.
Jail-maker scripts:
*<nameofjail>_build # script to build the chroot jail
*<nameofjail>_setperms # script to set the permissions of the chroot jail

'/home/jails/' Directory where the real chroot jails will live.
* irssi '/home/jails/irssi' chroot jail
* p2p '/home/jails/p2p' chroot jail

Users && Groups information:
User: | Chroot Jail | Group
esclavo1 -- irssi -- esclavos
esclavo2 -- p2p -- esclavos
...
Note: it is wise to have primitive jail-maker scripts, this are very basic, and they are used as a starting point to construct
other jails, for example:
*primitive_build # script to build chroot jail - bash, ls, lynx, strace, whoami, and network support
*primitive_setperms





Building the chroot jails
Grab a pen and a piece of paper and wrote down exactly how you constructed the chroot jails in order to create the jail-maker scripts afterwards.
Some important rules(security wise):
* add only what is absolutely needed
* less is more
* no compilers
* no mknod, ln, chmod, and the like
* _never_ run the chroot jail as root
* no setuid root programs, programs must never run as root( some daemons needs to run first as root, make sure they give up privileges as soon as possible)
* complex chroot jails are inversely proportional to security
* No proc inside the chroot
* Do not bind the real /tmp inside the chroot jail

Ok, creating chroot jails is consider to be something hard and painful to do, and it's true, things will not work out of the box, and investigation is required, so put your Sherlock Holmes suit and good luck.
Example:
Code:

mkdir <nameofjail>
cd <nameofjail>
mkdir -p bin dev etc/lynx etc/terminfo/r usr/lib64 tmp
mkdir -p home/<nameofprisioner>
#if amd64 then create the proper links:
##ln -s lib64 lib
## cd usr && ln -s lib64 lib && cd ..
# create the necessary nodes(varies per plataform)
mknod dev/random c 1 8
mknod dev/tty c 5 0
mknod dev/urandom c 1 9
mknod dev/zero 1 5
# Populate bin/
cp /bin/bash bin/
cp /bin/ls bin/

It's time now, to find out which shared libraries your programs use, unless of course they were compiled statically(which I doubt) :
ldd </path/to/bin>
example:
Code:

ldd /bin/bash
        libdl.so.2 => /lib/libdl.so.2 (0x00002aaaaabc1000)
        libc.so.6 => /lib/libc.so.6 (0x00002aaaaacc4000)
        /lib64/ld-linux-x86-64.so.2 (0x00002aaaaaaab000)

Now copy each library to the respective directories, do not modify the path

Since some applications load libraries dinamically, you need to use strace to find out.
First copy strace to the bin/ directory
Now Sherlock, start digging:
Code:

example:
 chroot  jailtestarena/ strace -o /tmp/trace.out ls -l
# After it finish, investigate the output:
less tmp/trace.out
cat jailtestarena/tmp/trace.out | grep open
cat jailtestarena/tmp/trace.out | grep access

Some config files are also needed, be sure you copy them to the chroot jail as well.
Now, figure out what kind of perms your chroot jail must have.
Code:
chown -R esclavo$n:esclavos /home/jails/$a[irssi or p2p]/home/esclavo$n

Don't use the dot "." to set the perms in the jail, it will set the permisions for / aswell and you will have troubles loggin in
Code:
#example -- dont do it this way:
cd <nameofjail>
chown -R root:root  .
chmod -R a=  .


When done, create the <nameofjail>_build and <nameofjail>_setperms scripts, so you won't have to do it all over again next time.




Install pam_chroot module
Currently, portage does not have the pam_chroot module, check /lib/security/ to see if you do, also ask portage for it.
If not, then:
http://www.kernel.org/pub/linux/libs/pam/modules.html # not up to date, use the other one instead
http://sourceforge.net/projects/pam-chroot/
Install it:
The PAM modules are plugged in, just like that, so they are very easy to install.
Code:
 make && make install
cp chroot.conf /etc/security/

Configure chroot.conf
Very simple example:
Code:

esclavo1 /home/jails/irssi
esclavo2 /home/jails/p2p

When this users login, PAM will check chroot.conf for a match, if a match is found it will send this users to jail :)

Edit /etc/pam.d/login: # PAM will check for a match at login
Code:
#add this line:
session required /lib/security/pam_chroot.so debug


Edit /etc/pam.d/su: # PAM will check for a match when su'ing
Code:
#add this line:
session    required             pam_chroot.so debug


Read the following files that came with the pam_chroot module:
TROUBLESHOOTING
options
[edit]
Some of the examples in /etc/security/chroot requires certain options, you can see a full list in the 'options' file that came with pam_chroot, you enable this options at the pam_chroot line in /etc/pam.d/login (and /etc/pam.d/su) in order to use them.
[/edit]


Adding the prisioners
Set the group for all the prisioners:
Code:

groupadd -f esclavos

Per prisioner:
useradd -d /home/$a[irssi or p2p] -G prisioners -s /bin/bash esclavo$n
passwd esclavo$n

Test it:
Code:

tail -f /var/log/messages   # to see what goes on
su - esclavo$n


Logging using syslog-ng
Edit /etc/syslog-ng/syslog-ng.conf:
Code:

source src {
        unix-stream("/dev/log");
        internal();
        unix-stream("/home/jails/$a[irssi or p2p]//dev/log");
        pipe("/proc/kmsg");
};


Jail-maker scripts examples
Irssi:
irssi_build:
Code:

#!/bin/bash
echo "################################"
echo " Jail-maker script -  irssi     "
echo "################################"
echo ""
echo -n "Prisioner name: "
read a
# Building the Jail
cd /home
mkdir -p jails/irssi
cd jails/irssi
# Safety check
if [ `pwd` != "/home/jails/irssi" ]; then
echo "Wrong location"
echo "Aborted"
exit 0
else
mkdir -p home/$a bin dev lib64 etc/lynx etc/terminfo/r usr/lib64 tmp
mkdir -p etc/terminfo/l
ln -s lib64 lib
cd usr
ln -s lib64 lib
cd ..
# the nodes varies per plataform
mknod dev/null c 1 3
mknod dev/random c 1 8
mknod dev/tty c 5 0
mknod dev/urandom c 1 9
mknod dev/zero c 1 5
# Populating bin/
cp /bin/bash bin/
cp /bin/ls bin/
cp /bin/grep bin/
cp /usr/bin/lynx bin/
cp /usr/bin/strace bin/
cp /usr/bin/irssi bin/
cp /bin/mkdir bin/
cp /bin/whoami bin/
# Bring the libs
cp /lib64/libdl.so.2 lib64/
cp /lib64/libc.so.6 lib64/
cp /lib64/ld-linux-x86-64.so.2 lib64/
cp /lib64/librt.so.1 lib64/
cp /lib64/libncurses.so.5 lib64/
cp /lib64/libpthread.so.0 lib64/
cp /lib64/libgpm.so.1 lib64/
cp /lib64/libz.so.1 lib64/
cp /lib64/libresolv.so.2 lib64/
cp /lib64/libnsl.so.1 lib64/
cp /lib64/libnss_compat.so.2 lib64/
cp /lib64/libnss_dns.so.2 lib64/
cp /lib64/libnss_files.so.2 lib64/
cp /lib64/libnss_nis.so.2 lib64/
cp /lib64/libpthread.so.0 lib64/
cp /lib64/libm.so.6 lib64/
cp /lib64/libcrypt.so.1 lib64/
cp /lib64/libutil.so.1 lib64/
cp /usr/lib64/libssl.so.0.9.7 usr/lib64/
cp /usr/lib64/libcrypto.so.0.9.7 usr/lib64/
cp /usr/lib64/libperl.so.1 usr/lib64/
cp /usr/lib64/libgmodule-2.0.so.0 usr/lib64/
cp /usr/lib64/libglib-2.0.so.0 usr/lib64/
mkdir -p usr/lib64/perl5
cp -Rp /usr/lib64/perl5/* usr/lib64/perl5/
# irssi stuff
mkdir -p usr/lib64/irssi/modules
cp -p /usr/lib64/irssi/modules/* usr/lib64/irssi/modules/
mkdir -p usr/share/irssi
cp -Rp /usr/share/irssi usr/share/irssi
# Populating etc/
cp /etc/localtime etc/
cp /etc/lynx/lynx.cfg etc/lynx/
cp /etc/lynx/lynx.lss etc/lynx/
cp /etc/nsswitch.conf etc/
cp /etc/resolv.conf etc/
cp /etc/terminfo/r/rxvt etc/terminfo/r/
cp /etc/terminfo/l/linux etc/terminfo/l/   #lynx from console
cp /etc/irssi.conf etc/
# /etc/passwd && /etc/group
touch etc/passwd
touch etc/group
cat /etc/passwd | grep ^root >> etc/passwd
cat /etc/passwd | grep ^$a >> etc/passwd
cat /etc/group | grep ^root >> etc/group
cat /etc/group | grep $a >> etc/group
# irssi will start as soon as the prisioner enters
echo "irssi" >> home/$a/.bash_profile
# Colors
mkdir etc/bash
echo ". /etc/bash/bashrc" >> etc/profile
cp -p /etc/DIR_COLORS etc/
cp -p /etc/bash/bashrc etc/bash/
cd ..
echo "Don't forget to set the perms"
fi

irssi_setperms:
Code:

#!/bin/bash

echo "########################################"
echo "##  Set Permissions on jail - irssi "
echo "##"
echo -n "Prisioner name: "
read a
cd /home/jails/irssi
if [ `pwd` != "/home/jails/irssi" ]; then
echo "Wrong location"
echo "Aborted"
exit 0
else
chmod a=rw dev/null
chmod a=x   bin/
chmod a=x bin/*
chmod a=rx   etc/
chmod -R u+rw etc/
chmod -R go+r etc/
chown -R $a:prisioners home/$a
echo "It's Done"
cd ..
fi


p2p: # using mldonkey, the interface I use is the web interface, so I just connect to 127.0.0.1:<port>
p2p_build:
Code:

#!/bin/bash
echo "################################"
echo " Jail-maker script -  p2p "
echo "################################"
echo ""
echo -n "Prisioner name: "
read a
# Building the Jail
cd /home
mkdir -p jails/p2p
cd jails/p2p
# Safety check
if [ `pwd` != "/home/jails/p2p" ]; then
echo "Wrong location"
echo "Aborted"
exit 0
else
mkdir -p home/$a bin dev lib64 etc/lynx etc/terminfo/r usr/lib64 tmp
mkdir -p etc/terminfo/l
ln -s lib64 lib
cd usr
ln -s lib64 lib
cd ..
# the nodes varies per plataform
mknod dev/null c 1 3
mknod dev/random c 1 8
mknod dev/tty c 5 0
mknod dev/urandom c 1 9
mknod dev/zero c 1 5
# Populating bin/
cp /bin/bash bin/
cp /bin/ls bin/


cp /bin/grep bin/
cp /usr/bin/lynx bin/
cp /usr/bin/strace bin/
cp /bin/whoami bin/
cp /usr/bin/mlnet bin/
cp /usr/bin/mlnet+gui bin/
# Bring the libs
cp /lib64/libdl.so.2 lib64/
cp /lib64/libc.so.6 lib64/
cp /lib64/ld-linux-x86-64.so.2 lib64/
cp /lib64/librt.so.1 lib64/
cp /lib64/libncurses.so.5 lib64/
cp /lib64/libpthread.so.0 lib64/
cp /lib64/libgpm.so.1 lib64/
cp /lib64/libz.so.1 lib64/
cp /lib64/libresolv.so.2 lib64/
cp /lib64/libnsl.so.1 lib64/
cp /lib64/libnss_compat.so.2 lib64/
cp /lib64/libnss_dns.so.2 lib64/
cp /lib64/libnss_files.so.2 lib64/
cp /lib64/libnss_nis.so.2 lib64/
cp /lib64/libpthread.so.0 lib64/
cp /usr/lib64/libssl.so.0.9.7 usr/lib64/
cp /usr/lib64/libcrypto.so.0.9.7 usr/lib64/
# mlnet(mldonkey shared libraries)
cp /usr/lib64/libgtk-x11-2.0.so.0 usr/lib64/
cp /usr/lib64/libgdk-x11-2.0.so.0 usr/lib64/
cp /usr/lib64/libatk-1.0.so.0 usr/lib64/
cp /usr/lib64/libgdk_pixbuf-2.0.so.0 usr/lib64/
cp /lib64/libm.so.6 lib64/
cp /usr/lib64/libpangoxft-1.0.so.0 usr/lib64/
cp /usr/lib64/libpangox-1.0.so.0 usr/lib64/
cp /usr/lib64/libpango-1.0.so.0 usr/lib64/
cp /usr/lib64/libgobject-2.0.so.0 usr/lib64/
cp /usr/lib64/libgmodule-2.0.so.0 usr/lib64/
cp /usr/lib64/libglib-2.0.so.0 usr/lib64/
cp /usr/lib64/libX11.so.6 usr/lib64/
cp /usr/lib64/libXrandr.so.2 usr/lib64/
cp /usr/lib64/libXi.so.6 usr/lib64/
cp /usr/lib64/libXinerama.so.1 usr/lib64/
cp /usr/lib64/libXft.so.2 usr/lib64/
cp /usr/lib64/libfreetype.so.6 usr/lib64/
cp /usr/lib64/libfontconfig.so.1 usr/lib64/
cp /usr/lib64/libXfixes.so.3 usr/lib64/
cp /usr/lib64/libXcursor.so.1 usr/lib64/
cp /usr/lib64/libXrender.so.1 usr/lib64/
cp /usr/lib64/libXext.so.6 usr/lib64/
cp /usr/lib64/libpangoft2-1.0.so.0 usr/lib64/
cp /usr/lib64/libexpat.so.0 usr/lib64/
#cp /usr/lib64/librsvg-2.so.2 usr/lib64/
#cp /usr/lib64/libgsf-1.so.1 usr/lib64/
#cp /usr/lib64/libcroco-0.6.so.3 usr/lib64/
#cp /usr/lib64/libart_lgpl_2.so.2 usr/lib64/
#cp /usr/lib64/libxml2.so.2 usr/lib64/
#cp /lib64/libbz2.so.1 lib64/
#mkdir -p usr/lib64/X11
#cp -Rp /usr/lib64/X11/locale usr/lib64/X11/
# Populating etc/
cp /etc/localtime etc/
cp /etc/lynx/lynx.cfg etc/lynx/
cp /etc/lynx/lynx.lss etc/lynx/
cp /etc/nsswitch.conf etc/
cp /etc/resolv.conf etc/
cp /etc/terminfo/r/rxvt etc/terminfo/r/
cp /etc/terminfo/l/linux etc/terminfo/l/   #lynx from console
cp /etc/host.conf etc/
echo "127.0.0.1       localhost Laura" >> etc/hosts
# /etc/passwd && /etc/group
touch etc/passwd
touch etc/group
cat /etc/passwd | grep ^root >> etc/passwd
cat /etc/passwd | grep ^$a >> etc/passwd
cat /etc/group | grep ^root >> etc/group
cat /etc/group | grep $a >> etc/group
echo "mlnet" >> home/$a/.bash_profile
# Colors       
mkdir etc/bash
echo ". /etc/bash/bashrc" >> etc/profile
cp -p /root/jailskels/miscstuff/bashrc etc/bash/
cp -p /etc/DIR_COLORS etc/
cd ..
echo "Don't forget to set the perms"
fi

p2p_setperms:
Code:

#!/bin/bash

echo "########################################"
echo "##  Set Permissions on jail - p2p "   
echo "##"
echo -n "Prisioner name: "
read a
cd /home/jails/p2p
if [ `pwd` != "/home/jails/p2p" ]; then
echo "Wrong location"
echo "Aborted"
exit 0
else
chmod a=rw dev/null
chmod a=x   bin/
chmod a=x bin/*
chmod a=rx   etc/
chmod -R u+rw etc/
chmod -R go+r etc/
chown -R $a:prisioners home/$a
echo "It's Done"
fi

And just to make your life easier, here are my primitive jail-maker scripts:
primitive_build:
Code:

#!/bin/bash
echo "################################"
echo " Jail-maker script -  primitive "
echo "################################"
echo ""
echo -n "Prisioner name: "
read a
# Building the Jail
cd /home
mkdir -p jails/primitive
cd jails/primitive
# Safety check
if [ `pwd` != "/home/jails/primitive" ]; then
echo "Wrong location"
echo "Aborted"
exit 0
else
mkdir -p home/$a bin dev lib64 etc/lynx etc/terminfo/r usr/lib64 tmp
mkdir -p etc/terminfo/l
ln -s lib64 lib
cd usr
ln -s lib64 lib
cd ..# the nodes varies per plataform
mknod dev/null c 1 3
mknod dev/random c 1 8

mknod dev/tty c 5 0
mknod dev/urandom c 1 9
mknod dev/zero c 1 5
# Populating bin/
cp /bin/bash bin/
cp /bin/ls bin/
cp /bin/grep bin/
cp /usr/bin/lynx bin/
cp /usr/bin/strace bin/
cp /bin/whoami bin/
# Bring the libs
cp /lib64/libdl.so.2 lib64/
cp /lib64/libc.so.6 lib64/
cp /lib64/ld-linux-x86-64.so.2 lib64/
cp /lib64/librt.so.1 lib64/
cp /lib64/libncurses.so.5 lib64/
cp /lib64/libpthread.so.0 lib64/
cp /lib64/libgpm.so.1 lib64/
cp /lib64/libz.so.1 lib64/
cp /lib64/libresolv.so.2 lib64/
cp /lib64/libnsl.so.1 lib64/
cp /lib64/libnss_compat.so.2 lib64/
cp /lib64/libnss_dns.so.2 lib64/
cp /lib64/libnss_files.so.2 lib64/
cp /lib64/libnss_nis.so.2 lib64/
cp /lib64/libpthread.so.0 lib64/
cp /usr/lib64/libssl.so.0.9.7 usr/lib64/
cp /usr/lib64/libcrypto.so.0.9.7 usr/lib64/
# Populating etc/
cp /etc/localtime etc/
cp /etc/lynx/lynx.cfg etc/lynx/
cp /etc/lynx/lynx.lss etc/lynx/
cp /etc/nsswitch.conf etc/
cp /etc/resolv.conf etc/
cp /etc/terminfo/r/rxvt etc/terminfo/r/
cp /etc/terminfo/l/linux etc/terminfo/l/   #lynx from console
# /etc/passwd && /etc/group
touch etc/passwd
touch etc/group
cat /etc/passwd | grep ^root >> etc/passwd
cat /etc/passwd | grep ^$a >> etc/passwd
cat /etc/group | grep ^root >> etc/group
cat /etc/group | grep $a >> etc/group
# Colors       
mkdir etc/bash
echo ". /etc/bash/bashrc" >> etc/profile
cp -p /etc/bash/bashrc etc/bash/
cp -p /etc/DIR_COLORS etc/
cd ..
echo "Don't forget to set the perms"
fi



Problems ?
* ping: icmp open socket: Operation not permitted
A: if you want to use it you must do: 'chmod a+s bin/ping' #not needed nor recommended, dont bring ping inside the jail

* How to make a program start automatically when I enter the chroot jail ?
A: example:
Code:
echo "irssi" >> .bash_profile


* I don't want to give the prisioners a shell, what can I do ?
A: :) use pdmenu instead, just add it to /etc/shells (outside chroot), and when adding a prisioner make sure you use pdmenu instead of bash. Also you need to configure pdmenu for the prisioners, this is all explained here:
http://freshmeat.net/projects/pdmenu/
Using pdmenu with a chroot jail, will make the jail more secure
[TIP] pdmenu is also very useful for old computers with no fancy graphics

* I just update X program to a newer version, what shall I do ?
A: Copy the new binary, and check to see if it uses new libraries, if it does copy those as well,

Notes:
The following programs can help you create and manage chroot jails more easily than what this little guide presented:
* jailkit: http://olivier.sessink.nl/jailkit/ # I didn't used this one, if you did let me know if it is good, it seems to be one of the best available out there.
* makejail http://www.floc.net/makejail/ # It didn't worked for me, note though that I didn't put much effort either
* Root Jail http://freshmeat.net/projects/rj/ # I haven't used it
* Jail Tool http://www.westfalen.de/~gb/ # I haven't used, it seems to be Debian specific
* Jail http://www.jmcresearch.com/projects/jail/ # It did not worked as expected


Suggestions, ideas, etc.. are welcomed :D


Last edited by Reikinio on Thu Jan 19, 2006 8:13 am; edited 1 time in total
Back to top
View user's profile Send private message
Seather
Apprentice
Apprentice


Joined: 23 May 2003
Posts: 194
Location: South Africa

PostPosted: Sun Dec 25, 2005 10:44 pm    Post subject: Thanks and some questions Reply with quote

Thanks a lot, it seems I am going to have to start using this.

I currently run a box that has some people working on it, but I would like to lock them out of certain directories only, not because it is nescesarry or a risk, but because it would make me sleep better at night. For example /etc /var/www /var/log and so on.

My question is this. How usefull would it be to create a jail for users and link *everything* in (/bin /usr) and so on, expect those directories that I don't want them to have access to. Would they be able to break out of it?

Thanks
Back to top
View user's profile Send private message
Maedhros
Bodhisattva
Bodhisattva


Joined: 14 Apr 2004
Posts: 5511
Location: Durham, UK

PostPosted: Mon Dec 26, 2005 9:29 am    Post subject: Reply with quote

Looks interesting - I'm going to have to have a go at this.

Thanks a lot! :D
_________________
No-one's more important than the earthworm.
Back to top
View user's profile Send private message
Reikinio
Apprentice
Apprentice


Joined: 14 Aug 2005
Posts: 203
Location: Uruguay

PostPosted: Thu Dec 29, 2005 6:08 am    Post subject: Re: Thanks and some questions Reply with quote

Seather wrote:

My question is this. How usefull would it be to create a jail for users and link *everything* in (/bin /usr) and so on, expect those directories that I don't want them to have access to. Would they be able to break out of it?
Thanks


Hi, I wouldn't do that, I don't think you can just "link everything" like that, and even if you somehow manage to do it, either via mounting certain partitions read-only or whatever, you would end up giving them tools they shouldn't have, that could be used for breaking out.
From what I had read, more programs in your chroot enviroment means more complexity, and with more complexity less security.

The way I see it is, you have at least two options:
1) Use permissions, create a new group for your users and perform a permissions audit of the system(It's called something like this). This way is easier and pretty secure, you could also change their shell to pdmenu(read first post), this way all they would get will be a menu with the apps you arbitrarly choosed for them and nothing more.

2) Chrooting them, this means taking the time to investigate what you should put in the chroot(s). If your users use a lot of programs, I would suggest that you try some of the programs I mentioned in the first post instead of doing it all by hand(It's a PITA).
The pam_chroot module has some nice stuff to play with, for example:
Code:

#the default and commented chroot.conf

# /etc/security/chroot.conf
# basic format:
# username      chroot_dir
#foo    /home/foo

# Or, if you've specified use_regex,
# username_regex        chroot_dir
#^bar.*         /home/bar

# using @group syntax (specify use_groups):

# chroot members of group "baz" to /home/groups/baz
#@baz                   /home/groups/baz

# extended regexes and backreferences (specify use_ext_regex):

# chroot users in group web-whatever to /www/whatever
#^web-(.*)$             /www/%1

# chroot members of group "ftpusers" to /ftp/users/${username}
#@ftpusers      /ftp/users/%u

# chroot users with username user-whatever into /users/${pgroup}
#  where ${pgroup} is the user's primary group
#^user-.*               /users/%g

# chroot user named www-whatever or ftp-whatever into /www/XX or /ftp/XX
#  as appropriate:
#  username "www-uploads" -> /www/uploads
#  username "ftp-admin" -> /ftp/admin
#^(www|ftp)-(.*)                /%1/%2


Maedhros wrote:

Looks interesting - I'm going to have to have a go at this.

Thanks a lot! :D

You're welcomed.


Regards && and happy new year.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum