Subject: RE: PASV ftp ports

From: Roger Hanke <[email-masked]>
Date: Wed, 2 Sep 1998 10:00:35 -0400

Matt,
 Pedro Melo did the first patch for PASV port range that I know of.
He did submit it to Stans bug list but it has not made it into a
subsequent
release, perhaps because its considered a feature vs bug?
Anyway several other people have since published their own patches
doing essentially the same thing proving that it is indeed a quite
common
need. Have included Pedros last patch below to save you the 
digging if you want to use it. You can go back into the archives if you
want to find one of the newer ones by different authors.
Enjoy,
	Roger Hanke
------------------------------------------------------------------------
-------------
Some time ago I made a patch for beta12 that allows you to restrict the
port ranges used by passive mode ftp. 

This is helpfull for people who dont want to open just a part of their
port
space in their firewall.

So far, the pacth is compile time only. You cannot specify in the
config
file the port range to use. You have to change the values of
PASSIVE_BASE
and PASSIVE_SPAN in the patched ftpd.c and recompile... For ex, if you
want
to open ports 4000 to 5000, use PASSIVE_BASE 4000 and PASSIVE_SPAN 1000

Apply to the ftpd.c in the src directory...

I've been working with this patch for a coupple of month now, no
problems.

*** ftpd.c.orig	Fri Mar 21 02:15:09 1997
--- ftpd.c	Fri Mar 21 02:19:00 1997
***************
*** 394,399 ****
--- 394,401 ----
      struct sockaddr_in *virtual_ptr;
  #endif
  
+     srandom(getpid());
+ 
  #ifdef AUX
      setcompat(COMPAT_POSIX | COMPAT_BSDSETUGID);
  #endif
***************
*** 3246,3251 ****
--- 3248,3256 ----
   * response by Jon Postel in a telephone conversation with Rick Adams
on
25
   * Jan 89. */
  
+ #define PASSIVE_BASE 3000
+ #define PASSIVE_SPAN 500
+ 
  void
  #ifdef __STDC__
  passive(void)
***************
*** 3253,3259 ****
  passive()
  #endif
  {
!     int len;
      register char *p,
       *a;
  
--- 3258,3264 ----
  passive()
  #endif
  {
!     int len, bind_error;
      register char *p,
       *a;
  
***************
*** 3268,3281 ****
          return;
      }
      pasv_addr = ctrl_addr;
!     pasv_addr.sin_port = 0;
      delay_signaling(); /* we can't allow any signals while euid==0:
kinch
*/
      (void) seteuid((uid_t) 0);		/* XXX: not needed if >
1024 */
!     if (bind(pdata, (struct sockaddr *) &pasv_addr, sizeof(pasv_addr))
<
0) {
!         (void) seteuid((uid_t) pw->pw_uid);
!         enable_signaling(); /* we can allow signals once again: kinch
*/
!         goto pasv_error;
      }
      (void) seteuid((uid_t) pw->pw_uid);
      enable_signaling(); /* we can allow signals once again: kinch */
      len = sizeof(pasv_addr);
--- 3273,3293 ----
          return;
      }
      pasv_addr = ctrl_addr;
! 
      delay_signaling(); /* we can't allow any signals while euid==0:
kinch
*/
      (void) seteuid((uid_t) 0);		/* XXX: not needed if >
1024 */
!     do {
!         pasv_addr.sin_port = PASSIVE_BASE + random() % PASSIVE_SPAN;
!         if (log_commands) syslog(LOG_DEBUG, "PASV trying %d",
pasv_addr.sin_port);
!         bind_error = bind(pdata, (struct sockaddr *) &pasv_addr,
sizeof(pasv_addr));
!     } while(errno==EADDRINUSE);
!     if (bind_error < 0) {
!               (void) seteuid((uid_t) pw->pw_uid);
!               enable_signaling(); /* we can allow signals once again:
kinch */
!               goto pasv_error;
      }
+     if (log_commands) syslog(LOG_DEBUG, "PASV got %d",
pasv_addr.sin_port);
+ 
      (void) seteuid((uid_t) pw->pw_uid);
      enable_signaling(); /* we can allow signals once again: kinch */
      len = sizeof(pasv_addr);
--
************** Pedro Melo ([email-masked]) BOFH ******************
*   TELENET, Servicos de Telecomunicacoes, SA - Tel +351 1 3139190   *
* finger [email-masked] or search key servers for PGP key *
*           It's management's job to support the geniuses,           *
*                      not to tell them what to do                   *
**********************************************************************

>-----Original Message-----
>From:	Matt Engen [SMTP:[email-masked]]
>Sent:	Tuesday, September 01, 1998 9:34 PM
>To:	[email-masked]
>Subject:	PASV ftp ports
>
>Hi,
>
>I would like to restrict PASV ftp to a given port range.  It is my
>understanding
>that when the client sends the PASV command, the server opens a random
>high numbered port and informs the client of the port number. The client
>then
>does and active open to the server on that specified port.  This is a
>problem
>when the ftp server is located behind a firewall.  The incoming
>connection
>is blocked. For security reasons, I would much rather open up a "range"
>of
>ports for inbound traffic rather than anything over 1024. Can this be
>done with
>wu-ftp? Am I missing something else?
>
>According to RFC 1579
>
>  "Further precautions can be taken by modifying the FTP server so that
>   it only uses very high-numbered ports for the data channel.  It is
>   comparatively easy to ensure that no dangerous services live in a
>   given port range.  Again, this is feasible because of the small
>   number of servers. "
>
>I have read through various READMEs and the FAQ and do not see it. A
>pointer to the correct document would be greatly appreciated.
>
>Thanks.
>
>-Matt
>

---

From: Gregory A Lundberg <[email-masked]>
Date: Wed, 2 Sep 1998 10:58:17 -0400 (EDT)

> !     } while(errno==EADDRINUSE);

All the original patches use this loop which effectively hangs the server
until it can find an available port. Disliking the possibilty of someone
forcing the daemon into this infinite loop, I changed to the use of a
linear search which has the ability of terminating deterministicly, but
the disadvantage of predictive use. Using the former method, the daemon
is open to DoS, and the latter allows connection stealing.

I'm working on a way which offers both random selection and deterministic
termination.  Basically, what I'm considering right now is populating an
array of port numbers with one occurance of each number in the port range
in a random sequence then running through this array some fixed number of
times (three probably) before declaring that there are no available ports. 
Comments? 

----

Gregory A Lundberg		Senior Partner, VRnet Company
1441 Elmdale Drive              [email-masked]
Kettering, OH 45409-1615 USA    1-800-809-2195