Monday, January 30, 2012

Setup a Pure-FTPd FTP server with virtual users

Setup a Pure-FTPd FTP server with virtual users

Pure-FTPd is a free (BSD), secure, production-quality and standard-conformant FTP server.

This guide provides instructions for using the virtual user system to manage and control users. By using virtual users, FTP accounts can be administrated without affecting system accounts.

Let's initiate Pure-FTPd's installation by entering the following commands:

% su
# portsnap update
# cd /usr/ports/ftp/pure-ftpd
# make config-recursive

A menu containing Pure-FTPd options will pop-up. In my case, I've opted to leave these options at their defaults.

# cat /var/db/ports/pure-ftpd/options
WITH_UTF8=true
WITH_LARGEFILE=true

# make install clean distclean
# rehash

Having finished the installation process we now move into the configuration stage. We'll start by copying the sample configuration file and set the configuration options:

# cd /usr/local/etc
# cp pure-ftpd.conf.sample pure-ftpd.conf
# chmod 444 pure-ftpd.conf

The chmod command was run to be able to edit the file (default permissions are set to -r--r--r--).

# vim pure-ftpd.conf
# Port range for passive connections replies. - for firewalling.
PassivePortRange 30000 30900

# IP address/port to listen to (default=all IP and port 21).
Bind 192.168.100.1,21

# If you want to log all client commands, set this to "yes".
# This directive can be duplicated to also log server responses.
VerboseLog yes

# PureDB user database (see README.Virtual-Users)
PureDB /usr/local/etc/pureftpd.pdb

# Create an additional log file with transfers logged in the standard W3C
# format (compatible with most commercial log analyzers)
AltLog w3c:/var/log/pureftpd.log

# Automatically create home directories if they are missing
CreateHomeDir yes

# Disallow anonymous connections. Only allow authenticated users.
NoAnonymous yes

# Disallow anonymous users to upload new files (no = upload is allowed)
AnonymousCantUpload yes

The CreateHomeDir option makes adding virtual users more easy by creating a user's home directory upon login (if it doesn't already exist).

We can either import users with system-level accounts (defined in /etc/master.passwd) at once or create new users manually. To import users that already exist on your system into the virtual user database, enter these commands:

# pure-pwconvert >> /usr/local/etc/pureftpd.passwd
# chmod 600 /usr/local/etc/pureftpd.passwd
# pure-pw mkdb

It should be noted that pure-pwconvert only imports accounts that have shell access. Accounts with the shell set to nologin have to be added manually.

To add users to the Pure-FTPd virtual user database manually, we need to create a system-level account that will be associated with virtual users. Create a new user named ftp like this:

# pw useradd -n ftp -s /sbin/nologin -w no -d /home/ftp -c "FTP user" -m

Note: When you install pureftp, an ftp group is created, but no ftp user; this results in the error "mail pure-ftpd:(?:?) [ERROR] Unable to find the 'ftp' account". So we need to manually create the ftp user.

Having done this we can now add users to the virtual users database using the commands below:

# pure-pw useradd ftp_test -u ftp -g ftp -d /home/ftp/ftp_test
# pure-pw mkdb

Replace user with the desired username. With -d flag, the user will be chrooted. If you want to give user access to the whole filesystem, use -D instead of -d.

If you want to add additional users, just repeat the commands above with a different user.

Allow clients' IP addresse:
# pure-pw usermod user_name -r 209.17.11.12
# pure-pw mkdb

To reset a user's password:
# pure-pw passwd user_name
# pure-pw mkdb

To view info about one user:
# pure-pw show user_name

To view a list of users:
# pure-pw list

To remove a user:
# pure-pw userdel user_name
# pure-pw mkdb

Now to start Pure-FTPd:

# /usr/local/etc/rc.d/pure-ftpd onestart

Initiate a FTP connection to test the server:

% ftp localhost
    Trying 127.0.0.1...
    Connected to localhost.
    220---------- Welcome to Pure-FTPd [TLS] ----------
    220-You are user number 2 of 50 allowed.
    220-Local time is now 13:39. Server port: 21.
    220-IPv6 connections are also welcome on this server.
    220 You will be disconnected after 15 minutes of inactivity.
    Name (localhost:username):
Now log in with a user account created as explained above. Commands such as ls, cp, pwd and less work just like in tcsh and bash shells. To quit the FTP session type exit.

To configure Pure-FTPd to start at boot time:

# echo 'pureftpd_enable="YES"' >> /etc/rc.conf

To restart Pure-FTPd and determine if it is running:

# /usr/local/etc/rc.d/pure-ftpd restart
# /usr/local/etc/rc.d/pure-ftpd status

# sockstat | grep :21

Rotate pure-ftpd log file:
# vim /etc/newsyslog.conf
/var/log/pureftpd.log 600 7 100000 * JC /var/run/pure-ftpd.pid

# /etc/rc.d/newsyslog restart

Pure-FTPd provides useful features for personal users as well as hosting providers. I've only touched the tip of the iceberg so do take a look at the project's website for the excellent documentation that is available.

PF supports FTP servers and FTP clients behind NAT

WAN0 IP: 11.11.11.11
WAN1 IP: 22.22.22.22

FTP0 server (behind NAT) IP: 192.168.100.1
FTP1 server (behind NAT) IP: 192.168.100.2

# vim /etc/rc.local
### ftp-proxy for outside world FTP clients accessing internal FTP server behand NAT.
/usr/sbin/setfib 0 /usr/sbin/ftp-proxy -R 192.168.100.1 -p 21 -b 11.11.11.11
/usr/sbin/setfib 1 /usr/sbin/ftp-proxy -R 192.168.100.2 -p 21 -b 22.22.22.22

### Note:
### -b // bind to the external IP.
### -R // redirect to internal FTP server IP.

### ftp-proxy for internal FTP clients behand NAT accessing outside world FTP servers.
/usr/sbin/ftp-proxy -p 8021 -b 127.0.0.1

# vim /etc/pf.conf
### [FTP] RDR DMZ to Outside (through ftp-proxy)
### Note: make sure you have this line "ftpproxy_enable="YES"" in your /etc/rc.conf.
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr pass proto tcp from $dmz_if/24 to any port 21 -> 127.0.0.1 port 8021

### enabloe log for debugging purpose.
block log all

### [FTP] from ROUTER to ANY
pass out quick log on $wan_if0 proto tcp from $wan_if0 to any port 21 rtable 0
pass out quick log on $wan_if0 proto tcp from $wan_if0 to any port > 1023 rtable 0

pass out quick log on $wan_if1 proto tcp from $wan_if1 to any port 21 rtable 1
pass out quick log on $wan_if1 proto tcp from $wan_if1 to any port > 1023 rtable 1

### [FTP] from ANY to $dmz_ftp0_ip0 $dmz_ftp1_ip0
pass in quick log on $wan_if0 proto tcp from any to $wan_if0 port 21 rtable 0
pass in quick log on $wan_if0 proto tcp from any to $dmz_ftp0_ip0 port 30000:30900 rtable 0
pass in quick log on $wan_if1 proto tcp from any to $wan_if1 port 21 rtable 1
pass in quick log on $wan_if1 proto tcp from any to $dmz_ftp1_ip0 port 30000:30900 rtable 1

pass out quick log on $dmz_if proto tcp from $dmz_if to $dmz_ftp0_ip0 port 21 rtable 0
pass out quick log on $dmz_if proto tcp from $dmz_if to $dmz_ftp0_ip0 port 30000:30900 rtable 0
pass out quick log on $dmz_if proto tcp from $dmz_if to $dmz_ftp1_ip0 port 21 rtable 1
pass out quick log on $dmz_if proto tcp from $dmz_if to $dmz_ftp1_ip0 port 30000:30900 rtable 1

### [FTP] We need to have an anchor for ftp-proxy.
anchor "ftp-proxy/*"

### [FTP] from DMZ to ANY
pass in quick log on $dmz_if proto tcp from $dmz_if/24 to any port 21 rtable 0

Flush the pf.conf setting:
# pfctl -f /etc/pf.conf

Try to connect to ftp:
# ftp ftp.freebsd.org
Name: anonymous
Password: anonymous

Reference:
Setup a Pure-FTPd FTP server with virtual users
http://gala4th.blogspot.com/2012/01/setup-pure-ftpd-ftp-server-with-virtual.html

http://gala4th.blogspot.com/2012/01/pf-supports-ftp-servers-and-ftp-clients.html
http://forums.freebsd.org/showthread.php?t=591

No comments: