P w/ ftp-proxy, using both active/passive FTP

Duckbreath duckbreath at yahoo.com
Wed Oct 10 00:16:54 UTC 2012

My goal is to get my FTP server working for both passive and active type FTP connections with the following 
1) Running PF firewall on a FreeBSD machine, which is also the FTP machine.
2) Without opening up all ports > 1024 (or any upper-swath of ports), except where this occurs dynamically.

I have chosen to take an ftp-proxy based solution.  I'm also limited to 1 box here, so ftp-proxy is running on the 
same machine as the target FTP server, although I understand it is typically used in a gateway/forwarding situation.

After a lot of playing around with my firewall rules, I've ended up in a mutually exclusive situation.

With this line:
rdr pass on $std_int proto tcp from any to $std_int port 21 -> port 8021

PASSIVE FTP WORKS!! Yay!!!!  Woooo *cheering in background*.
But.... Active fails.

If I comment it out, in thus fashion:
#rdr pass on $std_int proto tcp from any to $std_int port 21 -> port 8021

ACTIVE FTP WORKS!! Yay!!!! Wooooo *cheering in background*.
But..... Passive fails.

I would also like to mention that just commenting it out and restarting the firewall is all I did.  ftp-proxy server 
process is still running.  Also both tests were from the same host, using the same ftp program, with only 
active/passive settings on ftp client used appropriately for each respective test; all other settings identical.

So I took a look at the handbook, which claimed I need to understand active/passive better (although I thought 
I already did... funny how that works?) - and the handbook linked the site http://slacksite.com/other/ftp.html

Here I got this awesome description from slacksite:
"In active mode FTP the client connects from a random unprivileged port (N > 1023) to the FTP server's command port, 
port 21. Then, the client starts listening to port N+1 and sends the FTP command PORT N+1 to the FTP server. 
The server will then connect back to the client's specified data port from its local data port, which is port 20."

So my first assumption was, "Either I can't connect to the client's local port, or my firewall isn't letting anything 
out on port 20."  I look at the rules... hmm, don't think so.  I just open up everything and try anyway,
try ftp-proxy with & without "-r" option, and no dice.  Same situation for both tests.  Nothing changes.

Examples of what I put in:
pass in quick on $std_int proto tcp from any to any
pass out quick on $std_int proto tcp from any to any
below rdr directive (which is required by pf.conf ordering).

Then I have a Face Palm.... exactly how did any of that have to do with it working when the rule was commented out?  Absolutely nothing, that's what!  I feel like such an idiot!!

Ok.. so what does that rule mean?  Let's revisit the rule:
rdr pass on $std_int proto tcp from any to $std_int port 21 -> port 8021

So all traffic on port 21, either in or out, goes to localhost 8021.  Hmmmm.  The rule failed when I tried to 
specify 'in' or 'out' on the rdr directive.  I don't think pf works rdr that way.

My only logical conclusion is FTP has become stubborn and is using Active mode on port 21, and not 20, for whatever 
reason.  The connection starts to succeed, but then the ACK packet from the client of course gets redirected to 8021, 
and the active connection being attempted from 21 misses it, resulting in a "half-open" connection, thus causing the 
FTP data channel to fail.  It is the only possible explanation I can come up with, yet that is not in 
accordance to know what I know about FTP behavior (i.e., according to slacksite's description).

Somewhere between convention and the IETF, I think I got lost.

Does anyone know how to get passive + active both working with the stated goals of using PF w/ ftp-proxy?

If this question is outside the scope of this list but better suited to be asked freebsd-pf, apologies in advance.  Since the question is not about the development of the firewall itself, I thought it appropriate to ask here.

More information about the freebsd-questions mailing list