Fun With Active/Passive FTP and a PF Firewall
Here at work we’ve recently been moving off of a Linux/IPTables firewall setup to an OpenBSD/PF firewall. Well, anyone who has worked with firewalls knows the fun time you have with getting FTP to work through them. This includes client and server side. Well, this is my little ‘how-to’ on doing just that with PF and PureFTP.
I originally started with this tutorial from OpenBSD and was a good starting point but I felt it left out a few things.
First off. The tutorial above uses the ftp-proxy server on the box to allow proxying down to the ftp server. However, I didn’t exactly see any benefit of using it and didn’t seem to make anything easier. If I’m completely misunderstanding the usage of it please contact me and help me out. I DO want to do things right.
Here’s the overall layout of what is to happen:
[Client] <—> [PF Firewall] <—> [FTP Server]
Now, a few observations I’ve made while working with the firewall and maybe a bit clearer for others.
Here’s a great explanation of the overall FTP process from Tech Republic. Here’s the overall communication ports for the 2 different modes (as the PF firewall sees it – at least in my experience).
Active FTP:
-Inbound-
— Authentication/Commands —
Incoming: 21 (External interface – FW)
Outgoing: 21 (Internal interface – FW)
Incoming: 21 (FTP Server Interface)-Outbound-
— Data Transfer —
Outgoing: > 30000 (FTP Server Interface)
Outgoing: > 30000 (External interface – FW)Passive FTP:
-Inbound-
— Authentication/Commands —
Incoming: 21 (External interface – FW)
Outgoing: 21 (Internal interface – FW)
Incoming: 21 (FTP Server Interface)
— Data Transfer —
Incoming: 49000-51000 (External interface – FW)
Outgoing: 49000-50000 (Internal interface – FW)
Incoming: 49000-50000 (FTP Server Interface)-Outbound-
Outgoing: 49000-50000 (FTP Server Interface)
Outgoing: 49000-50000 (External interface – FW)
Alright enough chat and on to the code. First we need to configure the ftp server. In the below examples I’ll cover PureFTP and ProFTPd for just the primary pieces of passive port configuration (I’ll give a nice ProFTP advanced configuration in a post to come). We’ll also assume the default ‘listening’ port 21 of any standard FTP install/configuration. This is also on a Gentoo server so modify accordingly for your given distro.
PureFTPd:
MISC_OTHER=”[various options/flags] -p 49000:51000 -P [Public IP]“
ProFTPd:
PassivePorts 49000 51000
MasqueradeAddress [Public IP]
PF Firewall Rules: (Just the FTP Rules)
# Interface Definitions:
ftp_ext=”[Public IP]”
ftp_int=”[Private IP]”# NAT Rules
nat on $ext_if from { $ftp_int } to any -> $ftp_ext# Redirect Rules
rdr pass on $ext_if inet proto tcp from any to $ftp_ext port 21 -> $ftp_int port 21
rdr pass on $ext_if inet proto tcp from any to $ftp_ext port 49000:51000 -> $ftp_int# Firewall Rules
pass out quick on $ext_if inet proto tcp from $ftp_ext to any port > 1024 keep statepass out quick log on $int_if inet proto tcp from any to $ftp_int port 21 keep state tag FTP label “ftp”
pass out quick log on $int_if inet proto tcp from any to $ftp_int port 49000:51000 keep state tag FTP_PASV label “ftp-passive”
That should be all you need for the PF rules and configuration on the FTP servers to get everything working and passing through. Feel free to contact me should you have any additional fixes or have a good explanation of how the ftp-proxy works and benefits of. I’ve just gotta find the time to do some experimenting.
I recently upgraded to Snow Leopard (Mac OS X 10.6). I’m quite used to using MacFUSE to remotely mount (via SSH) development systems for ease of coding. However, I just noticed that MacFUSE now refuses to establish a connection to the remote server. So, here is a fix for just that.
Pure-FTP is a powerful ftp server. If you are like me however, you don’t like to create system accounts for each individual user. Well, this is where we are in luck! Pure-FTP has the ability to tie into both PostgreSQL and MySQL. In this example I have tied it into a PostgreSQL database. I will also include the MySQL snippet of the configuration but it hasn’t been tested by me. Also note that this is a Gentoo based installation but the general configuration should be the same.
At my job we are moving to Nginx for the load balancing of our sites. Nginx is a very powerful load balancing/proxy server tool. It allows weighting, ssl acceleration, among other functionality while remaining light weight and easy to configure.
Its often necessary to add bonding (NIC teaming – in windows world) to a linux config. This gives you 2 things: higher throughput on the interfaces and redundancy (if a card or switch happens to die). I made this post just as a quick reference for how to do such on a Gentoo system.



