LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

Re: ftp and firewalling (never really works as it is supposed to)

To: lvs-users@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: ftp and firewalling (never really works as it is supposed to)
From: Roberto Nibali <ratz@xxxxxx>
Date: Sun, 06 May 2001 14:18:26 +0200
Hi Alois,

> > I allow now only ports 61250:61299 as data ports in passive ftp.
> >
> > I find that this set of rules works, to allow both active ftp (like
> > from an ncftp client) and passive ftp (like from netscape browser):
> 
> I have to withdraw this statement: it does not work.

Thanks :) You saved me some time debugging your ipchains rules.

> It seems to have worked accidentally when I tested at first, but now
> I suddenly get different ports assigned.

Where on the proftpd daemon running behind the LVS_NAT'd director (your
defined PASV port-range), the director allocated NAT'd ports (61000-
65535 as defined in ../include/net/ip_masq.h) or the on the client side?
 
> I am back to field 1.
> I seem unable to setup ftp, without opening all ports above 1024 on both
> the director and the VIP.

That's the current impact we have to face for your setup. We have multiple
choices if we want to narrow down the input ipchains rules on the front 
interface of the LVS box:

1. Use ftp via LVS. (this is not a solution actually, we still need special
   input rules on the EXT_IF for 1024:65535)
2. Use ftp without LVS but with SNAT. (a pain in the ass to setup and 
   ugly. To phrase it in pure year 1291 swiss german: "saugruusig")
3. Use SuSE ftp proxy suite. (We're investigating this. Memo will follow
   on monday I hope.)
4. Use 2.4 kernel and ip_conntrack_ftp (no comment, ask Rusty)
5. Don't use ftp at all. (YES, yes, yes, this is what we want :)

The biggest problem I see is, that the ip_masq_ftp module is extremely dumb!
It should create an ip_fw entry in the masq_table for the PORT port. It doesn't
do this that's why we have to open the whole bloody port range. And for the
PASV we have to DNAT the range. 

ipchains -A forward -i $EXT_IF -s $INTERNAL_NET $UNPRIV_PORTS -d $DEP -j MASQ

I looked at the code. Maybe it is not difficult to do a :

append_to_chain(struct ip_chain *chainptr, struct ip_fwkernel *rule) 
from ../net/ipv4/ip_masq_ftp.c: masq_ftp_out()

The ftp protocol is so f**king broken I've to vomit on my keyboard soon! Only 
IRC and games like quake, sin, UT and black & white can beat this, oh yes, and 
of course IPX (but this is not a protocol anyway :)).

Let's summarize:
================

   FTP is a bitch and totally broken by design.

   FTP is a rather complicated protocol thought out by sadists to give
   security people the greatest possible headaches. (Well, ok, later the
   guys who thought out RPC or the Win*-equivalents running over Port 137
   topped this).

   FTP is made up of two connections, the Control- and the Data
   Connection.

FTP Control Connection

   This is the easy part. The Client contacts the Servers port 21 from an
   UNPRIV Port. Easy. Not trouble, standard, plain, vanilla
   TCP-Connection. Nice, we all love it. Over this connection the client
   sends commands to the server. We will see examples later.

FTP Data Connection

   This is, where the trouble starts. As soon as data is transferred
   between server and client, this is done via a second connection.
   "Data" can be either the content of a file (sent as e.g. the result of
   a "get" or "put" command) or the content of a directory-listing (i.e.
   the result of a "ls" or "dir" command).

   Now you would expect, that usually the client opens this second
   connection to the server. Wrong. Usually the server opens this second
   connection. He uses his port 20 as sourceport (this is a well-known
   port, usually called ftp-data). But which port on the client should he
   connect to? To the port the client announces via a "port"-command over
   the control connection. Nasty: Ports are negotiated on
   application-level. This method is called "Active FTP".

   Now, you guessed it, there is also "Passive FTP". In this case the
   client opens the data-connection to the server. Of course you already
   guessed, that in this case the server announces the port the client
   should connect to. The server does this in his reply to the clients
   "pasv"-command which starts passive FTP (active is the default). Of
   course this is some unknown UNPRIV port and of course the client also
   uses some random UNPRIV port. So as a result: if we have a server
   protected by a packetfilter and people want to use passive FTP (as all
   Mickysoft-clients do by default), UNPRIV->UNPRIV has to be open

Server behind PF

     * Allow UNIVERSE/UNPRIV --tcp--> Server/21 (for control onnection)
     * Allow Server/20 --tcp-->UNIVERSE/UNPRIV (for active data
       connection)
     * Allow UNIVERSE/UNPRIV --tcp--> Server/UNPRIV (for passive data
       connection

   Now if you just replace "UNIVERSE" by "Client" and "Server" by
   "UNIVERSE" you get:

Client behind PF

     * Allow Client/UNPRIV --tcp--> UNIVERSE/21
     * Allow UNIVERSE/20 --tcp--> Client/20
     * Allow Client/UNPRIV --tcp--> UNIVERSE/UNPRIV

Summary

   As you can easily see, if we have to protect a client, we would like
   to only allow passive ftp, because then we do not have to allow
   incoming connections. If we have to protect a server, we would like to
   only allow active ftp, because then we only have to allow the incoming
   control-connection. Clearly there is a deadlock.

Talk FTP

   Now for an example. We need 2 xterms (I call them x1 and x2 in the
   following), netcat and an ftp-server somewhere. Ratz has one running
   on his machine (zar, 172.23.2.30) which I will abuse.

   x1: Open the control-connection to the server:
$ netcat zar 21
220 zar.terreactive.ch FTP server (Version 6.4/OpenBSD/Linux-ftpd-0.16) ready.
user ftp
331 Guest login ok, send your complete e-mail address as password.
pass ftp
230 Guest login ok, access restrictions apply.
pasv
227 Entering Passive Mode (172,23,2,30,169,29)

   Now what was this last 2 lines? I start with passive mode (because it
   is conceptionally easier) and sent "pasv" to the server. He answered
   with 6 numbers: 172,23,2,30 is the IP I have to connect to, and
   (169*256+29=43293) is the Port (oh, I forgot, you need a calculator as
   well). So in x2 I open with a second netcat the connection:

$ netcat 172.23.2.30 43293

   and magically I have a connection, because the server has established
   a listener there. Now in x1 (remember, the control-connection) I order
   a directory-listing with the "list" command:
$ list
list
150 Opening ASCII mode data connection for '/bin/ls'.
226 Transfer complete.

   and magically in x2 the listing appears.

   Now for active mode. I use the same control-connection in x1 as above.
   But I want the server to open a connection. Therefore I first need a
   listener. I do it with netcat in x2:
$ netcat -l -p 2560

   and netcat listens. Now I tell the server on the control connection to
   connect:
port 172,23,2,8,10,0
200 PORT command successful.


   Now you see, why I used port 2560 8). 172.23.2.8 is, of course, my own
   IP-address. And now finally I ask again for a directory-listing (in
   x1) with the list command and watch it magically appear in x2. For
   completeness sake, here is the the full in/output. First the xterm 1:
---------- mt@mt --------1
~-> netcat zar 21
220 zar.terreactive.ch FTP server (Version 6.4/OpenBSD/Linux-ftpd-0.16) ready.
user ftp
331 Guest login ok, send your complete e-mail address as password.
pass ftp
230 Guest login ok, access restrictions apply.
pasv
227 Entering Passive Mode (172,23,2,30,169,29)
list
150 Opening ASCII mode data connection for '/bin/ls'.
226 Transfer complete.
port 172,23,2,8,10,0
200 PORT command successful.
list
150 Opening ASCII mode data connection for '/bin/ls'.
226 Transfer complete.
quit
221 Goodbye.
---------- mt@mt --------2
~->

   and here now xterm 2:
---------- mt@mt --------1
~-> netcat 172.23.2.30 43293
total 7
dr-x--x--x   2 root     root         1024 Jul 26  2000 bin
drwxr-xr-x   2 root     root         1024 Jul 26  2000 dev
dr-x--x--x   2 root     root         1024 Aug 20  2000 etc
drwxr-xr-x   2 root     root         1024 Jul 26  2000 lib
drwxr-xr-x   2 root     root         1024 Jul 26  2000 msgs
dr-xr-xr-x  11 root     root         1024 Mar 15 14:26 pub
drwxr-xr-x   3 root     root         1024 Mar 11  2000 usr
---------- mt@mt --------2
~-> netcat -l -p 2560
total 7
dr-x--x--x   2 root     root         1024 Jul 26  2000 bin
drwxr-xr-x   2 root     root         1024 Jul 26  2000 dev
dr-x--x--x   2 root     root         1024 Aug 20  2000 etc
drwxr-xr-x   2 root     root         1024 Jul 26  2000 lib
drwxr-xr-x   2 root     root         1024 Jul 26  2000 msgs
dr-xr-xr-x  11 root     root         1024 Mar 15 14:26 pub
drwxr-xr-x   3 root     root         1024 Mar 11  2000 usr
---------- mt@mt --------3
~->

#END OF MEMO
=============================================================================

Best regards,
Roberto Nibali, ratz, who will investigate the best solution to run ftp on
monday.

-- 
mailto: `echo NrOatSz@xxxxxxxxx | sed 's/[NOSPAM]//g'`


<Prev in Thread] Current Thread [Next in Thread>