BSD FTP-Proxy: PF Firewall Allow Outgoing Active / Passive FTP Connections

Posted on in Categories , , , , last updated November 9, 2009

Q. I’ve FreeBSD based Apache webserver. I need to allow outgoing ftp client requests so that BSD ports collection can download from various ftp sites. How do I allow outgoing FTP connection via PF network firewall software under FreeBSD or OpenBSD operating system?

A. You need to use ftp-proxy, which is a proxy for the Internet File Transfer Protocol. ftp-proxy is installed by default along with PF firewall.

Step # 1: Turn on ftp-proxy under FreeBSD

Open /etc/rc.conf file under FreeBSD
# vi /etc/rc.conf
Append following line:
If you are using OpenBSD, type the following command to start the ftp proxy on boot:
echo 'ftpproxy_flags=""' >>/etc/rc.conf.local
By default ftp proxy listen on 8021 port bind to IP address.

Step # 2: Configure pf and ftp-proxy

Open your /etc/pf.conf file and add following into your NAT section:
To activate it, put something like this in the NAT section of pf.conf:
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr pass proto tcp from any to any port ftp -> port 8021

All three rules required, even if your setup does not use NAT. Find your filtering rule and append the following rules:
anchor "ftp-proxy/*"
Save and close the file.

Sample pf.conf rules

Here is my own working sample /etc/pf.conf file that allows outgoing ftp, along with ssh, http, dns service. It only allows incomming traffic on port 53, 80:

#### First declare a couple of variables ####
# outgoing services
tcp_services = "{ ssh, smtp, domain, www, https, ntp, 43}"
udp_services = "{ domain, ntp }"
icmp_types = "{ echoreq, unreach }"
martians = "{,,,,,,, }"
ext_if = "em1" # Internet
int_if = "em0" # vpn / lan
proxy="" # ftp proxy IP
proxyport="8021" # ftp proxy port
#### Normalization
scrub in all
#### NAT and RDR start
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
# Redirect ftp traffic to proxy
rdr pass proto tcp from any to any port ftp -> $proxy port $proxyport
#### Start filtering 
# Drop incoming everything
block in all
# Default connection refused message to client 
block return  
# keep stats of outging connections
pass out keep state
# We need to have an anchor for ftp-proxy
anchor "ftp-proxy/*"
# Unlimited traffic for lo0 and VPN/Lan interface
set skip on {lo0, $int_if}
# activate spoofing protection for all interfaces
block in quick from urpf-failed
# Antispoof is a common special case of filtering and blocking. This mechanism protects against activity from spoofed or forged IP addresses
antispoof log for $ext_if
#Block RFC 1918 addresses
block drop in log (all)  quick on $ext_if from $martians to any
block drop out log (all) quick on $ext_if from any to $martians
# Allow outgoing via ssh, smtp, domain, www, https, whois etc
pass out on $ext_if proto tcp to any port $tcp_services
pass out on $ext_if proto udp to any port $udp_services
# Allow outgoing Trace route
pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state
# Allow incomming named udp / tcp 53
pass in on $ext_if proto udp from any to any port 53
# All tcp service protected using synproxy
pass in on $ext_if proto tcp from any to any port 53 flags S/SA synproxy state
# Allow http traffic
pass in on $ext_if proto tcp from any to any port 80 flags S/SA synproxy modulate state
# SSH 
pass in on $ext_if proto tcp from any to any port 22 flags S/SA synproxy modulate state
# Allow ICMP ping
pass inet proto icmp all icmp-type $icmp_types keep state

Step # 3: Restart PF firewall

Type the following command under FreeBSD:
# /etc/rc.d/pf restart
OR type the following under OpenBSD (also works under FreeBSD):
# pfctl -nf /etc/pf.conf
# pfctl -f /etc/pf.conf

Step # 4: Start ftp-proxy

Type the following command to start ftp-proxy under, FreeBSD:
# /etc/rc.d/ftp-proxy start
Under OpenBSD, you can simply type the following to start ftp-proxy:
# /usr/sbin/ftp-proxy

Test your setup

Use ftp client to test your test, enter:
$ ftp

Further readings:

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin and a trainer for the Linux operating system/Unix shell scripting. He has worked with global clients and in various industries, including IT, education, defense and space research, and the nonprofit sector. Follow him on Twitter, Facebook, Google+.

10 comment

  1. I’ve got ftp-proxy working on my firewall for all the clients behind it. However I can’t ftp (using Active or Passive) from the actual firewall itself, which is making installing/upgrading ports tedious.

    For example:
    #pkg_add -r
    Error: FTP Unable to get Operation not permitted
    pkg_add: unable to fetch ‘’ by URL

    I’m guessing that this is because no redirection is being done as the request is being sent straight out the default route interface (I verified this by pausing the pkg_add command, and executing netstat -f inet | grep ftp).
    Any suggestions as to how I can get around this. Surely this is something that others have encountered.

  2. @Vivek
    Thanks, that would make sense. Unfortunately it also means that my block out rule is essentially rendered useless. A few people here use personal laptops with the BBC iPlayer installed which can eat bandwidth. By only allowing out required traffic, it makes life a lot easier.
    Any chance I can keep my cake and eat it :-)

  3. Hi Vivek,

    I think there is an error here:

    # pfctl -nf /etc/rc.conf
    # pfctl -f /etc/rc.conf

    Should be this:
    # pfctl -nf /etc/pf.conf
    # pfctl -f /etc/pf.conf

    In any case, thanks for a useful page and a very useful site. I keep coming back.


  4. Thank you for good article.
    But if I use the rule
    # keep stats of outging connections
    pass out keep state
    I don’t need any other rules such as
    # Allow outgoing via ssh, smtp, domain, www, https, whois etc
    pass out on $ext_if proto tcp to any port $tcp_services
    pass out on $ext_if proto udp to any port $udp_services

  5. Thanks for the great article, and explanation. The comments are also very informative. It helped me recently with an instance of PF, FreeBSD and FTP.

Comments are closed.