Building a Secure FTP Server (Solaris 9, Sparc)

Building a Secure FTP Server (Solaris 9, Sparc)

by Ross Moffatt, September 2008

This tech tip shows how to create a secure ftp server.  The ftp daemon is run as a non-root user, listening on chosen user defined ports, in a chroot jail environment.  This implementation could be changed to run ftpd as a root user using the standard ftp ports.  It only allows pre-defined users to login, with configurable access rights.  Of course you need to be a root user to create this jail environment.

Note: This has only been tested on Solaris version 9, Sparc.

Choose where the ftp jail should be located, I will use /ftpjail in this article.
This should be its own mounted filesystem with enough space for the ftp server binaries and configuration files, about 8 Mbytes, plus space for files that are going to be transferred via ftp.

Here is an appendix showing the complete file list for the FTP jail environment as described in this Tech Tip.

Build the <ftp jail root> (/ftpjail) jail environment

Create the directories and a symbolic link under the <ftp jail root> (/ftpjail) directory

mkdir -p /ftpjail
cd /ftpjail
mkdir -p dev etc etc/ftpd etc/default usr/bin usr/sbin usr/lib/security usr/lib/locale usr/lib/security/sparcv9 usr/lib usr/share/lib/zoneinfo upload
chmod 100 usr/sbin
chmod 444 dev etc/default usr/share usr/share/lib usr/share/lib/zoneinfo
chmod 555 etc etc/ftpd usr usr/bin usr/lib usr/lib/locale usr/lib/security
chmod 777 upload
Create ln -s usr/bin bin

Create special device files required in the jail environment

Find the current special device files and the major and minor numbers by first listing out the device symbolic links.

cd /dev
ls -l conslog null tcp ticlts ticotsord udp zero
lrwxrwxrwx   1 root     other         31 Aug  8 12:36 conslog -> ../devices/pseudo/log@0:conslog
lrwxrwxrwx   1 root     other         27 Aug  8 12:36 null -> ../devices/pseudo/mm@0:null
lrwxrwxrwx   1 root     other         27 Aug  8 12:36 tcp -> ../devices/pseudo/tcp@0:tcp
lrwxrwxrwx   1 root     other         29 Aug  8 12:36 ticlts -> ../devices/pseudo/tl@0:ticlts
lrwxrwxrwx   1 root     other         32 Aug  8 12:36 ticotsord -> ../devices/pseudo/tl@0:ticotsord
lrwxrwxrwx   1 root     other         27 Aug  8 12:36 udp -> ../devices/pseudo/udp@0:udp
lrwxrwxrwx   1 root     other         27 Aug  8 12:36 zero -> ../devices/pseudo/mm@0:zero

Now list out the actual device files.

cd ../devices/pseudo
ls -l log@0:conslog mm@0:null tcp@0:tcp tl@0:ticlts tl@0:ticotsord udp@0:udp mm@0:zero
crw-rw-rw-   1 root     sys       21,  0 Aug  8 12:36 log@0:conslog
crw-rw-rw-   1 root     sys       13,  2 Sep 25 11:47 mm@0:null
crw-rw-rw-   1 root     sys       13, 12 Aug  8 12:36 mm@0:zero
crw-rw-rw-   1 root     sys       42,  0 Aug  8 12:36 tcp@0:tcp
crw-rw-rw-   1 root     sys      105,  2 Aug  8 12:36 tl@0:ticlts
crw-rw-rw-   1 root     sys      105,  1 Aug  8 12:36 tl@0:ticotsord
crw-rw-rw-   1 root     sys       41,  0 Aug  8 12:36 udp@0:udp

Using the major and minor number found above, create new device files in the jail environment.

cd /dev
ls -l conslog null tcp ticlts ticotsord udp zero
lrwxrwxrwx   1 root     other         31 Aug  8 12:36 conslog -> ../devices/pseudo/log@0:conslog
lrwxrwxrwx   1 root     other         27 Aug  8 12:36 null -> ../devices/pseudo/mm@0:null
lrwxrwxrwx   1 root     other         27 Aug  8 12:36 tcp -> ../devices/pseudo/tcp@0:tcp
lrwxrwxrwx   1 root     other         29 Aug  8 12:36 ticlts -> ../devices/pseudo/tl@0:ticlts
lrwxrwxrwx   1 root     other         32 Aug  8 12:36 ticotsord -> ../devices/pseudo/tl@0:ticotsord
lrwxrwxrwx   1 root     other         27 Aug  8 12:36 udp -> ../devices/pseudo/udp@0:udp
lrwxrwxrwx   1 root     other         27 Aug  8 12:36 zero -> ../devices/pseudo/mm@0:zero

Now list out the actual device files.

cd ../devices/pseudo
ls -l log@0:conslog mm@0:null tcp@0:tcp tl@0:ticlts tl@0:ticotsord udp@0:udp mm@0:zero
crw-rw-rw-   1 root     sys       21,  0 Aug  8 12:36 log@0:conslog
crw-rw-rw-   1 root     sys       13,  2 Sep 25 11:47 mm@0:null
crw-rw-rw-   1 root     sys       13, 12 Aug  8 12:36 mm@0:zero
crw-rw-rw-   1 root     sys       42,  0 Aug  8 12:36 tcp@0:tcp
crw-rw-rw-   1 root     sys      105,  2 Aug  8 12:36 tl@0:ticlts
crw-rw-rw-   1 root     sys      105,  1 Aug  8 12:36 tl@0:ticotsord
crw-rw-rw-   1 root     sys       41,  0 Aug  8 12:36 udp@0:udp

Using the major and minor number found above, create new device files in the jail environment.

cd  /ftpjail/dev
mknod conslog c 21 0
mknod null c 13 2
mknod zero c 13 12
mknod tcp c 42 0
mknod ticlts c 105 2
mknod ticotsord c 105 1
mknod udp c 41 0
chmod 666 conslog null tcp ticlts ticotsord udp zero

To check what you have done.

ls -l
crw-rw-rw-   1 root     other     21,  0 Sep 25 11:57 conslog
crw-rw-rw-   1 root     other     13,  2 Sep 25 11:57 null
crw-rw-rw-   1 root     other     42,  0 Sep 25 11:57 tcp
crw-rw-rw-   1 root     other    105,  2 Sep 25 11:57 ticlts
crw-rw-rw-   1 root     other    105,  1 Sep 25 11:57 ticotsord
crw-rw-rw-   1 root     other     41,  0 Sep 25 11:57 udp
crw-rw-rw-   1 root     other     13, 12 Sep 25 11:57 zero

 Create configuration files in ftp jail environment

Use an editor such as vi to create these files.

/ftpjail/etc/group

other::1:root
ftp::30000:

/ftpjail/etc/pam.conf

ftp auth required /usr/lib/security/pam_unix.so.1
ftp account required /usr/lib/security/pam_unix.so.1
ftp session required /usr/lib/security/pam_unix.so.1

/ftpjail/etc/passwd

Note: Replace gftp with a username you want to login to ftp server with.  You can add other users to use the ftp server in this file.

root:x:0:1:::
ftp:x:30000:30000::/upload:/bin/false
gftp:x:30000:30000::/upload:/bin/sh

/ftpjail/etc/shadow
Note: Replace gftp with a username you want to login to ftp server with, replace $$ with the encrypted password for this user.
To generate the encrypted passowrd, use the password facility to change the password of a user on the host that you know the password of.  Then copy the encrypted password from /etc/shadow.  Remember to change the password back for the user using the passwd utility again.  The users in this file must match the users in var/ftpjail/etc/passwd.

root:*LK*:6445::::::
ftp:*LK*:13651::::::
gftp:$$:13651::::::

ftpjail/etc/shells

/bin/sh

/ftpjail/etc/ftpd/ftpaccess

hostname ftpserver
defaultserver private
class   all   real,guest,anonymous  *
# all the following default to "yes" for everybody
delete          no      real,guest,anonymous
overwrite       no      real,guest,anonymous
rename          no      real,guest,anonymous
chmod           no      real,guest,anonymous
umask           no      real,guest,anonymous
# specify the upload directory information
upload  /       *       no
upload  /       /upload yes
greeting terse
noretrieve *
#allow-retrieve /upload/*
defumask 777

/ftpjail/usr/bin/runme

/usr/sbin/in.ftpd -P 2020 -p 2021 -S -u 022 -W -a -Q

Correct newly created file permissions

cd /ftpjail/etc
chmod 444 group pam.conf passwd shadow shells /ftpjail/etc/ftpd/ftpaccess
chmod 100 /ftpjail/usr/bin/runme

Copy current files, correcting permissions, into the ftp jail environment

cp -p /etc/default/init /ftpjail/etc/default/init
cp /usr/bin/sh /ftpjail/usr/bin/sh; chmod 111 /ftpjail/usr/bin/sh
cp /usr/sbin/in.ftpd /ftpjail/usr/sbin/in.ftpd; chmod 6100 /ftpjail/usr/sbin/in.ftpd; chown 30000:30000 /ftpjail/usr/sbin/in.ftpd
cp -rp /usr/lib/locale/* /ftpjail/usr/lib/locale
cp -rp /usr/share/lib/zoneinfo/*  /ftpjail/usr/share/lib/zoneinfo
cd /ftpjail/usr/lib
cp -p /usr/lib/libbsm.so.1 .
cp -p /usr/lib/libc.so.1 .
cp -p /usr/lib/libcmd.so.1 .
cp -p /usr/lib/libdl.so.1 .
cp -p /usr/lib/libgen.so.1 .
cp -p /usr/lib/libmd5.so.1 .
cp -p /usr/lib/libmp.so.2 .
cp -p /usr/lib/libnsl.so.1 .
cp -p /usr/lib/libpam.so.1 .
cp -p /usr/lib/libresolv.so.2 .
cp -p /usr/lib/libsecdb.so.1 .
cp -p /usr/lib/libsocket.so.1 .
cp -p /usr/lib/ld.so.1 .
cp -p /usr/lib/nss_user.so.1 .
cp -p /usr/lib/nss_files.so.1 .
chmod 555 *
cd /ftpjail/usr/lib/security
cp -p /usr/lib/security/crypt_bsdbf.so.1 .
cp -p /usr/lib/security/crypt_bsdmd5.so.1 .
cp -p /usr/lib/security/crypt_sunmd5.so.1 .
cp -p /usr/lib/security/pam* .
cd /ftpjail/usr/lib/security/sparcv9
cp -p /usr/lib/security/sparcv9/* .
 
Initial test to look around the new environment

Oh, by the way, if you want to be able to use the ls command you need to add it into the jail environment, I suggest you delete this file after testing.

cp /usr/bin/ls /ftpjail/usr/bin/ls; chmod 111 /ftpjail/usr/bin/ls

Running a sh shell in the jail environment.

Note: there are limited commands in the jail, but cd and ls work to look around.

chroot /ftpjail /usr/bin/sh
Starting up the ftp server

Note: There will be a ftpd process created running in the jail environment listening on ports defined in the runme command.

chroot /ftpjail /usr/bin/sh -c runme

To check the server has started.

Note: As I don't have an entry in the system /etc/password file for UID 30000 it is shown as the numeric only.

ps -ef|grep ftpd
0030000 26704     1  0 09:04:30 ?        0:00 /usr/sbin/in.ftpd -P 2020 -p 2021 -S -u 022 -W -a -Q
To test the ftp server

Note: You can only upload files as setup in /ftpjail/etc/ftpd/ftpaccess.

ftp 127.0.0.1 2021
login gftp/<as set in /ftpjail/etc/shadow>

About the Author
Ross Moffatt has been a UNIX system administrator for 10+ years and can be contacted at ross.stuff@telstra.com.


Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

Sign up or Log in to add a comment or watch this page.


The individuals who post here are part of the extended Sun Microsystems community and they might not be employed or in any way formally affiliated with Sun Microsystems. The opinions expressed here are their own, are not necessarily reviewed in advance by anyone but the individual authors, and neither Sun nor any other party necessarily agrees with them.

Copyright 1994-2009 Sun Microsystems, Inc.
Powered by Atlassian Confluence
Sun Guidelines on Public Discourse Privacy Policy Terms of Use Trademarks Site Map Employment Investor Relations Contact