Topic: freebsd,pf,nat,ftp

FTP Client running PF --> NAT Router      --internet--    NAT Router --> FTP Server


From the FTP Client, FTP works just fine WITHOUT packet filter enabled, but with it enabled I receive:

"500 I won't open a connection to 192.168.2.14 (only to 76.69.36.xyz)" 
after I connect and type 'ls'


ftp-proxy is running, and I've also tried ftp-proxy -a <external wan ip>


int_if="ed1"
int_loopback="lo0"

internal_ip="192.168.2.14"

lan_cdir="192.168.2.0/24"

defaultrouter="192.168.2.1"


outbound_tcp_allowed_ports="{ 22, 80, 443, 5999, 20, 21 }"
outbound_udp_allowed_ports="{ 43, 53, 123 }"

#Must touch file first, chmod 700
table <overflow_www> persist file "/etc/pf_overflow_www.tbl"

set limit { states 100000, frags 50000 }

#production the $ext_if
set loginterface $int_if
#usual: set loginterface none

set optimization normal
set block-policy drop
set require-order yes


set skip on lo0

scrub in all fragment reassemble


nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr pass on $int_if proto tcp from $lan_cdir to any port 21 -> ($int_if) port 8021


block in all
block out all

antispoof quick for {$int_loopback, $int_if}


anchor "ftp-proxy/*"


pass in log quick on $int_if proto tcp from any to any port 22 flags S/SA keep state
pass out quick on $int_if proto tcp from any to any port $outbound_tcp_allowed_ports flags S/SA keep state
pass out quick on $int_if proto udp from any to any port $outbound_udp_allowed_ports keep state
pass in quick on $int_if proto tcp from any to $internal_ip port 80 flags S/SA keep state

Re: freebsd,pf,nat,ftp

This setup generally won't work; at least one party involved in an FTP transfer must not be NATed. If it is at all possible, I recommend you use some other file sharing protocol, e.g. http or sftp.

In special circumstances (i.e., when the FTP client or server knows about NAT and advertises the external IP instead of its own, and there is port-forwarding), it can be made to work, but it gets quite complicated.

Re: freebsd,pf,nat,ftp

Thanks Maxlor,

it's only bothering me because when packet filter is off, it works fine, i can ftp on the cmd line.  my windows box is uploading files right now and it's behind the same nat router as the BSD/pf machine i'm trying to get going.

so do you mean: if packet filter is running, you must not be NATed ?

Re: freebsd,pf,nat,ftp

Well, ok, let me explain a bit more:

FTP has two modes, active and passive. Active mode works like this:
the client connects to the server's port 21; this is the control connection. When a data transfer is started, the client starts listening on some random port; it sends the port number to the server, which then opens a connection to the specified port of the client; when the connection is established, data is sent.

Passive mode works like this:
the client connects to the server's port 21; this is the control connection. When a data transfer is started, the server starts listening on some random port; it sends the port number to the client, which then opens a connection to the specified port of server (it has now two connections to the server: one to port 21, one to some random port); when the connection is established, data is sent.

When firewalls and NAT are involved, there are problems:
- when a client is behind a NAT router, active FTP doesn't work by default: the NAT router receives a connection request but doesn't know its related to the existing FTP connection because the ports are different (unless it's a really smart NAT router; most aren't). The solution is port forwarding, but the difficulty lies in determining which port to forward: as mentioned above, the port that is used is somewhat random. If the FTP client can be restricted to a small range (say, a range of 5 ports that it picks one from), then all of this range can be forwarded, but with many clients this cannot be configured; and forwarding ranges of 20000 ports is inpractical when there is more than a single host behind a NAT router.

- when a client is behind a firewall, active FTP will not work by default because the firewall will block the incoming connection to the random port; a firewall rule needs to be defined to allow it, but again, the randomness of the chosen port makes this difficult.

- when the server is behind a NAT router, passive FTP will not work by default; the reason is the same as for the client above, except this time its the server that listens for an incoming connection on a random port. The situation is slightly better here, because with most FTP servers, the port range that they use for passive connections can be configured.

- when the server is behind a firewall, passive FTP will not work by default; the reason is the same as for the client above.

The easiest way to deal with NAT, firewalls and FTP is to use either active or passive FTP, depending on whether the server or the client are behind a NAT router/firewall, because then no special configuration is required. If both hosts are behind a NAT router/firewall, then at least one of the hosts needs to have its random ports restricted to a specific range, and the appropriate port forwarding and firewall rules need to be defined (on the client side for active FTP, on the server side for passive FTP), and of course the client needs to know whether active or passive FTP should be used...

As I said, it gets complicated. Other protocols are much easier to configure... forward/allow one single port on the server and everything works.

Re: freebsd,pf,nat,ftp

Thanks again for the great reply,

Just to get this working, what i've done is open up port {20, >2000} in and out ... it's basically punching a huge hole because we don't know the passive port range the server will tell us to use.