NetBSD base system comes with a simple and convenient ftpd(8) server.
Today we discuss how to set up a file server on NetBSD using ftpd, with both anonymous and privileged access. We'll rely on the inetd(8) super-server daemon to manage the service.
Known system users, once authenticated, will be granted full access (r/w) to their respective home directories (to which they're going to be chrooted), while anonymous users will only be allowed to download files from the public ftp dir.
This setup also covers how to configure NPF and blacklistd accordingly.
DISCLAIMER: ftpd doesn't support FPTS (FTP over SSL), nor SFTP, so you may want to rather install something like net/proftpd if encryption is a major concern.
preliminary tasks
Create a ftp user –with restricted class capabilities– for anonymous connections
$ useradd -g guest -L guest -G users -s /sbin/nologin -c "Anonymous FTP user" -d /ftp ftp
Set up a suitable environment for anonymous access under /ftp
$ for d in bin etc hidden incoming pub
> do mkdir -p /ftp/${d}
> done
$ for f in ls gzip sh tar
> do cp /bin/${f} /ftp/bin
> done
$ for f in group master.passwd motd passwd
> do cp /etc/${f} /ftp/etc
> done
$ cd /ftp
$ chown -R ftp:guest pub incoming
$ chmod -R 755 pub
$ chmod -R 555 bin
$ chmod -R 5770 incoming
As for the incoming dir perms, notice that:
- 4000 for SUIDDIR
- 1000 for sticky bit
- 770 to set give full access to anon users and guest group
Edit anon chroot's master.passwd file so as to contain only relevant information (delete everything else)
$ vipw -d /ftp
It should look like that
default:*:0:0::::::
nobody:*:32767:39::0:0:Unprivileged user:/nonexistent:/sbin/nologin
ftp*************:1005:31:guest:0:0:Anonymous FTP user:/ftp:/sbin/nologin`
...and build a corresponding password database
$ pwd_mkdb -d /ftp -p /ftp/etc/master.passwd
Edit the anon chroot's group file so as to contain only relevant information. It should look like that:
default:*:0:
guest:*:31:ftp
users:*:100:ftp
nobody:*:39:
nogroup:*:32766
After that, the content of /ftp/etc, should appear as below:
-rw-r--r-- 1 root wheel 74 Jul 24 11:58 group
-rw------- 1 root wheel 162 Jul 24 12:57 master.passwd
-rw------- 1 root wheel 1272 Jul 24 13:30 motd
-rw-r--r-- 1 root wheel 132 Jul 24 12:58 passwd
-rw-r--r-- 1 root wheel 40960 Jul 24 12:58 pwd.db
-rw------- 1 root wheel 40960 Jul 24 12:58 spwd.db
Configuration files
Change working directory to /etc and edit the following files
# Default umask
#
umask chroot 027
umask guest 227
# Force PASV/PSV/LPSV mode
#
passive all
# Set the address to advertise in response to PASV/PSV/LPSV commands
advertise all host.domain.ext
# Set the range of port number which will be users for passive data transfer
portrange all 65525 65535
# Message of the day file to display after login
#
motd all .motd
# Check PORT command for validity; prevents denial of service attempt.
#
checkportcmd all
# Use `chroot' as a template for user vincent
# Use `guest' as a template for `anonymous 'and `ftp' login attempts
#
template vincent chroot
template anonymous guest
template ftp guest
# For anonymous connections, when a directory is entered show the contents
# of `.banner' if it exists, and notify about any files that start
# with `README'.
#
display guest .message
notify guest README*
# Prevent uploads & modification commands for anonymous connections
#
upload guest off
modify guest off
# Hide symlink references to anon users
#
hidesymlinks guest on
# Chroot anonymous connections to a directory different than $HOME
#
homedir guest /ftp
# Deny connection wherever REAL class is given as USER
#
denyquick real on
# Limit transfers for anonymous users 512 KB/s
#
rateget guest 512k
rateput guest 512k
# Limit the number of simultaneous `chroot' class connections to 3,
# and display /etc/ftptoomany when this limit is reached.
# As `localchroot' uses the `chroot' settings via the template above, override
# this specifically for `localchroot' entries to unlimited.
#
limit chroot 3 ftptoomany
limit localchroot -1
# Only permit file names which don't start with a ‘.’ and only comprise of
# characters from the set “[-+,._A-Za-z0-9]”.
#
sanenames chroot off
# Limit the number of bytes to write(2) at a time.
#
writesize chroot 100m
# Set the maximum size of an uploaded file to size
maxfilesize chroot 128m
# Support automatic conversions.
# The first entry supports compression of files, and there's no suppression
# character. `%s' is replaced by the filename.
# The next two entries support tar-ing and tar+gzip of files and directories,
# unless `.notar' exists in the current directory.
# The `--' in the command strings should prevent a filename with a leading
# `-' being interpreted as an argument to gzip/tar.
# For anonymous connections, ~ftp/usr/bin should be a symlink to ~ftp/bin,
# and gzip and tar should exist in the latter directory as statically
# linked executables, to avoid the effort of setting up shared libraries
# correctly under ~ftp.
#
conversion all .gz f . /usr/bin/gzip -c -- %s
conversion all .tar df .notar /usr/bin/tar -cf - -- %s
conversion all .t:wqar.gz df .notar /usr/bin/tar -zcf - -- %s
# List of users denied (or allowed) ftp access.
# Read by ftpd(8).
# The first matching entry is used.
#
# Deny various system users
root deny
toor deny
real deny
stunnel deny
daemon deny
operator deny
bin deny
sys deny
kmem deny
news deny
games deny
postfix deny
named deny
ntpd deny
sshd deny
uucp deny
nobody deny
clamav deny
# Allowed staff users [chroot them into their home as per ftpchroot(5)]
vincent allow chroot
# Allowed anon users with restricted privileges
anonymous allow guest
ftp allow guest
# list of users given ftp access to a chrooted area.
# read by ftpd(8).
vincent
anonymous
ftp
concurrent connections limit reached! please try later
# This a sample banner I use for my server
\\`-______,----__ Welcome to Sehnsucht's
\\ __,---`_ Anandamide Server
\\ `.____
\\-______,----`-
\\
\\
\\ Hosted on NetBSD!
Now link the banner to the ftpwelcome standard file
$ ln -sf banner ftpwelcome
update firewall and blacklistd configurations
npf.conf
# allow incoming FTP connections
pass stateful in final proto tcp to $int_if port ftp apply "log"
# allow FTP PSV on safer ports
pass stateful in final proto tcp to $int_if port 65525-65535
blacklistd.conf
# service type proto owner name nfail disable
[local]
ftp stream * root $host 5 24h
Now you can apply changes
$ npfctl reload
$ service blacklistd restart
make inetd start ftpd
Add the following lines to /etc/inetd.conf (for both IPv4 and IPv6)
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -ldr -a /ftp -L /var/log/ftpd/xferlog
ftp stream tcp6 nowait root /usr/libexec/ftpd ftpd -ldr -a /ftp -L /var/log/ftpd/xferlog
Understanding server options:
- -a: Define anondir as the directory to chroot(2) into for anonymous logins
- -dl: full session loggin to syslog via a LOG_FTP facility
- -L: Log wu-ftpd style ‘xferlog’ entries to xferlogfile
start the service
$ echo inetd=YES >> /etc/rc.conf
$ service inetd start