Historical FTP proxies: do not use

Various older PF versions still linger in some systems. The content that follows is not recommended, but is kept here mainly because any attempt at removing it has produced requests to bring it back.

Warning

If your configuration is based on a PF version that is old enough to warrant using any of the FTP proxies described in the following paragraphs, I strongly urge you to upgrade to a more recent system.

We will present the antiquated solutions in roughly chronological order according to their ages. The original FTP proxy for PF is described below in the Section called Ancient FTP through NAT: ftp-proxy. We then move on to two newer, intermediate solutions developed by Camiel Dobbelaar in the Section called Ancient: FTP, PF and routable addresses: ftpsesame, pftpx and ftp-proxy! before finally moving on to the modern FTP proxy which was introduced in OpenBSD 3.9 in the Section called ftp-proxy, slightly new style.

Ancient FTP through NAT: ftp-proxy

Warning

If your configuration is based on a PF version that is old enough to warrant using this FTP proxy, I strongly urge you to upgrade to a more recent system.

NoteOpenBSD 3.8 or earlier equivalents only
 

This section is headed for purely historical status when the last PF port to other systems has caught up. In November 2005, the old ftp-proxy (/usr/libexec/ftp-proxy) was replaced in OpenBSD-current with the new ftp-proxy, which lives in /usr/sbin. This is the software which is included in OpenBSD 3.9 onwards and what you will be using on modern PF versions. See the Section called ftp-proxy, slightly new style for details.

The old style ftp-proxy which is a part of the base system on systems which offer a PF version based on OpenBSD3.8 or earlier is usually called via the inetd "super server" via an appropriate /etc/inetd.conf entry.[1]

The line quoted here specifies that ftp-proxy runs in NAT mode on the loopback interface, lo0:

127.0.0.1:8021 stream tcp nowait root /usr/libexec/ftp-proxy \
  ftp-proxy -n

This line is by default in your inetd.conf, commented out with a # character at the beginning of the line. To enable your change, you restart inetd.

On FreeBSD, NetBSD and other rcNG based BSDs you do this with the command

FreeBSD$ doas /etc/rc.d/inetd restart

or equivalent. Consult man 8 inetd if you are unsure. At this point inetd is running with your new settings loaded.

Now for the actual redirection. Redirection rules and NAT rules fall into the same rule class. These rules may be referenced directly by other rules, and filtering rules may depend on these rules. Logically, rdr and nat rules need to be defined before the filtering rules.

We insert our rdr rule immediately after the nat rule in our /etc/pf.conf

rdr on $int_if proto tcp from any to any port ftp -> 127.0.0.1 \
         port 8021

In addition, the redirected traffic must be allowed to pass. We achive this with

pass in on $ext_if inet proto tcp from port ftp-data to ($ext_if) \
    user proxy flags S/SA keep state

Save pf.conf, then load the new rules with

$ doas pfctl -f /etc/pf.conf

At this point you will probably have users noticing that FTP works before you get around to telling them what you've done.

This example assumes you are using NAT on a gateway with non routable addresses on the inside.

Ancient: FTP, PF and routable addresses: ftpsesame, pftpx and ftp-proxy!

Warning

If your configuration is based on a PF version that is old enough to warrant using any of the following FTP proxy programs, I strongly urge you to upgrade to a more recent system.

In cases where the local network uses official, routable address inside the firewall, I must confess I've had trouble making ftp-proxy work properly. When I'd already spent too much time on the problem, I was rather relieved to find a solution to this specific problen offered by a friendly Dutchman called Camiel Dobbelaar in the form of a daemon called ftpsesame.

Local networks using official addresses inside a firewall are apparently rare enough that I'll skip over any further treatment. If you need this and you are running OpenBSD 3.8 or earlier or one of the other PF enabled operating systems, you could do worse than installing ftpsesame.

On FreeBSD, ftpsesame is available through the ports system as ftp/ftpsesame. Alternatively you can download ftpsesame from Sentia at http://www.sentia.org/projects/ftpsesame/.

Once installed and running, ftpsesame hooks into your rule set via an anchor, a named sub-ruleset. The documentation consists of a man page with examples which you can more likely than not simply copy and paste.

ftpsesame never made it into the base system, and Camiel went on to write a new solution to the same set of problems.

The new program, at first called pftpx, is available from http://www.sentia.org/downloads/pftpx-0.8.tar.gz and through the FreeBSD ports system as ftp/pftpx. pftpx comes with a fairly complete and well written man page to get you started.

A further developed version, suitably renamed as the new ftp-proxy, became a part of the the OpenBSD base system in time for the OpenBSD 3.9. The new program, /usr/sbin/ftp-proxy, and how to set it up, is described in the Section called ftp-proxy, slightly new style below.

ftp-proxy, slightly new style

Warning

If your configuration is based on a PF version that is old enough to warrant using the FTP proxy described here, I strongly urge you to upgrade to a more recent system.

NoteAncient: For OpenBSD 3.9 and newer
 

If you are upgrading to OpenBSD 3.9 or newer equivalents or working from a fresh OpenBSD install, this is the ftp-proxy version to use.

Just like its predecessor, the pftpx successor ftp-proxy configuration is mainly a matter of cut and paste from the man page.

If you are upgrading to the new ftp-proxy from an earlier version, you need to remove the ftp-proxy line from your inetd.conf file and restart inetd or disable it altogether if your setup does not require a running inetd.

Next, enable ftp-proxy by adding the following line to your /etc/rc.conf.local or /etc/rc.conf

ftpproxy_flags=""

You can start the proxy manually by running /usr/sbin/ftp-proxy if you like.

Moving on to the pf.conf file, you need two anchor definitions in the NAT section:

nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"

Both are needed, even if your setup does not use NAT. If you are migrating from a previous version, your rule set probably contains the appropriate redirection already. If it does not, you add it:

rdr pass on $int_if proto tcp from any to any port ftp -> 127.0.0.1 \
         port 8021

Moving on down to the filtering rules, you add an anchor for the proxy to fill in,

anchor "ftp-proxy/*"

and finally a pass rule to let the packets pass from the proxy to the rest of the world

pass out proto tcp from $proxy to any port 21 keep state

where $proxy expands to the address the proxy daemon is bound to.

This example covers the simple setup with clients who need to contact FTP servers elsewhere. For other variations and more complicated setups, see the ftp-proxy man page.

If you are looking for ways to run an FTP server protected by PF and ftp-proxy, you could look into running a separate ftp-proxy in reverse mode (using the -R option).

Notes

[1]

You may need to enable inetd by adding a inetd_enable="YES" line to your rc.conf and possibly adjust other inetd related configuration settings.