Announcing ftpsesame... one of those christmas time projects.  :-)

ftpsesame helps the FTP protocol get through your pf firewall without 
having to open up whole ranges of ports.  It works for FTP clients and 
FTP servers, and you do not have to redirect any traffic.

How does it work?

ftpsesame sniffs FTP control connections using bpf, and adds rules to 
allow active or passive data connections into an anchor when appropriate.  
For full details, see the manpage below.

It was developed on OpenBSD -current and should work fine on 3.4.  It can 
be made to work on 3.3 if tagging support is removed (drop me a note if 
you want the diff).

Because anchor support is essential, OpenBSD 3.2 and below are not 
supported.

Download: http://www.sentia.org/downloads/ftpsesame-0.7.tar.gz

Comments, suggestions, etc. welcome.

--
Cam



NAME                 
 ftpsesame - automagic packet filter configurator for FTP

SYNOPSIS                 
 ftpsesame [-d] [-D level] [-i interface] [-t tag] [-q queue] [expression]

DESCRIPTION                 
 ftpsesame tracks FTP control connections to be able to timely add pf(4)
 packet filter rules that allow active and passive FTP data transfers to
 commence. This results in the efficiency of a packet filter, and the
 fine-grained control of a proxy. It can run on both FTP clients and FTP
 servers, or a firewall in front thereof.

 ftpsesame uses bpf(4) to get a copy of the data inside all FTP control
 connections passing the specified interface. This data is searched for
 negotiations about data connections. For passive mode, this is a port
 that a client should use to connect to a server. For active mode this is
 a port and an IP address that a server should use to connect to a client.

 Assuming the FTP control connection is from $client to $server, and $port
 is negotiated, ftpsesame adds one of the following rules to pf(4), inside
 the anchor named "ftpsesame".

 In case of active mode (PORT or EPRT):
 pass in log quick inet proto tcp \
     from $server to $client port $port flags S/SAFR keep state

 In case of passive mode (PASV or EPSV):
 pass in log quick inet proto tcp \
     from $client to $server port $port flags S/SAFR keep state

 In the special case of passive mode where the client is subject to NAT,
 an extra rule is added, where $client_real is the client's real IP ad-
 dress:
 pass in log quick inet proto tcp \
     from $client_real to $server port $port flags S/SAFR keep state

 The options are as follows:

  -D level
 Debug level, ranging from 0 to 7. Higher is more verbose. The
 default is 5. (These levels correspond to the syslog (3) levels.)

  -d
 Do not daemonize. The process will stay in the foreground, log-
 ging to stderr.

  -i interface
 Listen on interface.

  -t tag
 Create rules with tag tag. Also, option quick is not used. This
 way the anchor always returns to the main ruleset, with the tag
 set on approved FTP data connections. The tag can then be used
 in pass rules below the anchor.

  -q queue
 Create rules with queue queue appended.

 expression
 Selects the packets that bpf(4) will pass on to ftpsesame. An
 expression consist of the primitives described in tcpdump(8).
 For efficiency, the expression should narrow down the traffic as
 much as possible. The default is "tcp and port 21".

CONFIGURATION EXAMPLES               
 To use the rules set up by ftpsesame, pf.conf(5) should be modified to
 use the anchor. Below are examples that show most of the possibilities.

 # (1) Allow internal LAN to access FTP servers anywhere.
 # (passive mode only if $lan is subject to NAT, see below)
 # cmd: ftpsesame -i $ext_if
 anchor ftpsesame on { $int_if, $ext_if }
 pass in quick on $int_if proto tcp from $lan to any port 21 keep state
 pass out quick on $ext_if proto tcp from $lan to any port 21 keep state

 # (2) Allow access to FTP servers in the DMZ, while queueing the data
 # transfers.
 # cmd: ftpsesame -i $dmz_if -q ftp
 queue ftp bandwidth 10%
 # passive
 anchor ftpsesame in on $ext_if proto tcp from any to { $ftp_servers }
 anchor ftpsesame out on $dmz_if proto tcp from any to { $ftp_servers }
 # active
 anchor ftpsesame in on $dmz_if proto tcp from { $ftp_servers } to any
 anchor ftpsesame out on $ext_if proto tcp from { $ftp_servers } to any
 # ... rules for port 21 omitted ...

 # (3) Allow access to FTP servers in the DMZ, using tagging for fine
 # grained control.
 # cmd: ftpsesame -i $dmz_if -t ftpok
 anchor ftpsesame
 # passive
 pass in quick on $ext_if proto tcp from to any to $realftp \
     port > 49151 tagged ftpok keep state
 pass in quick on $ext_if proto tcp from any to $msftp \
     port 1023 >< 5001 tagged ftpok keep state
 pass out quick on $dmz_if all tagged ftpok keep state
 # active
 pass in quick on $dmz_if proto tcp from $realftp to any \
     tagged ftpok keep state
 pass in quick on $dmz_if proto tcp from $msftp port 20 to any \
     tagged ftpok keep state
 pass out quick on $ext_if all tagged ftpok keep state
 # ... rules for port 21 omitted ...

 Keep state is mandatory on the control connection (port 21), because
 ftpsesame checks that these connections are in the statetable, before al-
 lowing data connections.

NAT ISSUES               
 To enable passive mode connections from clients subject to NAT, ftpsesame
 must listen on the interface where the NAT has already taken place, typi-
 cally the external interface. Otherwise ftpsesame cannot add the extra
 rule with the real client address. Note that this does not have to be a
 problem, if there are other rules taking care of that.

 Active mode connections from clients subject to NAT are not supported,
 because it requires commands inside the control connection to be rewrit-
 ten. ftp-proxy(8) can be used for that purpose. With the -n option it
 is a great combination with ftpsesame, because ftpsesame can then handle
 all passive mode connections from the clients, plus the active mode con-
 nections originating from the ftp-proxy itself.

SECURITY                 
 Ports below 1024 are not allowed.

 The negotiated IP address for active mode is ignored for security rea-
 sons. This makes third party file transfers impossible.

 ftpsesame checks that the ftp control connection is in the packet filter
 statetable before it will trust its contents.

 ftpsesame chroots to "/var/empty" and changes to user "proxy" to drop
 privileges. It does keep a file descriptor to both bpf(4) and pf(4) so
 it is still very powerful.

CAVEATS                 
 There is always a slight delay before a rule gets added to the anchor.
 If the data connection is opened within this period, it will get blocked.
 If ftpsesame runs on a firewall between the client and server, this only
 introduces a slight delay, as TCP will retry within seconds. If
 ftpsesame runs on a client or server itself, the network stack reacts
 differently on blocked packets ("no route to host") and either active or
 passive may mode not work.

SEE ALSO               
 ftp(1), ftp-proxy(8), pf(4), pf.conf(5)

Reply via email to