Subject: Correction: NAT, PASV, and "connection refused"

From: Paul Robertson <[email-masked]>
Date: Fri, 16 Apr 1999 22:35:31 -0400 (EDT)

Our public wu-ftpd server (2.4.2-vr16 on RedHat 5.2) is sitting behind
an Iproute box that does address translation and packet-filtering for
us. The ftp server has a private IP address behind the Iproute box. All
outbound traffic is permitted by the packet filter. Only inbound packets
on specific ports are permitted. Pretty standard stuff, I think.

We discovered yesterday that we had problems with FTP clients that ran
in passive mode. After doing a little research, we:

 - added the following lines to the /etc/ftpaccess file:

   passive address 192.168.2.112  192.168.2.0/24
   passive address 206.123.123.123 0.0.0.0/0
   passive ports 0.0.0.0/0 33300 33350

   The intent was that internal clients would see the private
   address. External clients would see the public address (which gets
   translated 192.168.2.112). We also configured the packet-filter to
   allow port range 33300-33350 inbound for the client connects to the
   server data port.

Unfortunately, when we attempt a passive connection from an external
ftp client, we see the following:

petunia:~>ftp ftp.whatever.com
Connected to ftp.whatever.com.
220 gatekeeper.whatever.com FTP server ready.
Name (ftp.whatever.com:smith): ftp
331 Guest login ok, send your complete e-mail address as password.
Password:
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pass
Passive mode on.
ftp> dir
227 Entering Passive Mode (206,123,123,123,139,128)
ftp: connect: Connection refused

>From an external address, I can telnet to 206.123.123.123 on all ports
in the range 33300 to 33350, so I know that the packet filter is
passing the packets. What's very strange is that when I run "netstat
-a" on the ftp server after running the PASV command, I see the
following entry:

Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 206.123.123.123:33305   *:*
LISTEN

So the server IS listening on the data port, but why is the "Local
Address" the EXTERNAL IP address (203.123.123.123), and not the internal
(192.168.2.112) address? Does this imply that the ftp server is somehow
listening on another address? Even from the internal network, with the
listening connection as above, I cannot complete the transfer with
"telnet 192.168.2.112 33305": I get "connection refused".

In the ftpaccess man page, the relevant note says:

 "NOTE: this does not change the address the daemone actually lis-
  tens on, only the address reported to the client.  This feature
  allows the daemon to operate correctly behind IP-renumbering
  firewalls."

Any suggestions as to why external ftp clients are unable to connect
in passive mode? I've scanned the archives and cannot find anything
that seems relevant to my experience.
  
Thanks in advance,
  
Paul

-- 
Paul Robertson
Phone:   (781) 213-9101  Fax: (508) 793-2972 
E-Mail:  [email-masked]

---

From: Gregory A Lundberg <[email-masked]>
Date: Sat, 17 Apr 1999 01:34:29 -0400 (EDT)

> tcp        0      0 206.123.123.123:33305   *:*

First point:  Your server is set up incorrectly.  You're using NAT and the
bind() to the outside address was successful.  That means the machine has
an interface listening on the external address.  You don't want that.  It
defeats the purpose of NAT.  Probably it's a leftover from before using
VR16.

What you should be seeing is:

425 Can't open passive connection: Cannot assign requested address.

Use ifconfig to determine which interface is listening on the wrong
address block.  Disable that interface immedeately with ifconfig and
correct the startup scripts of the machine so it doesn't come back.

Second point:  Guess what.  You're right.  The wrong address is being
bind()'d.  Here's a patch for VR16.  If the patch won't apply cleanly,
it's because of whitespace.  I've put it in my FTP site if you need a
clean copy:

  ftp://ftp.vr.net/private/lundberg/quickfix/passive_address.patch

Index: ftpd.c
===================================================================
RCS file: /cvsroot/wu-ftpd/src/ftpd.c,v
retrieving revision 1.4
diff -c -r1.4 ftpd.c
*** ftpd.c	1999/03/04 06:43:36	1.4
--- ftpd.c	1999/04/17 06:29:34
***************
*** 4471,4477 ****
      if (data != -1)
          lreply(0, "     Data connection open");
      else if (pdata != -1 || usedefault == 0){
!       sin = ( usedefault == 0 ? &data_dest : &pasv_addr );
        a = (u_char *) & sin->sin_addr;
        p = (u_char *) & sin->sin_port;
  #define UC(b) (((int) b) & 0xff)
--- 4471,4482 ----
      if (data != -1)
          lreply(0, "     Data connection open");
      else if (pdata != -1 || usedefault == 0){
!       if (usedefault == 0)
!           sin = &data_dest;
!       else if (route_vectored)
!           sin = &vect_addr;
!       else
!           sin = &pasv_addr;
        a = (u_char *) & sin->sin_addr;
        p = (u_char *) & sin->sin_port;
  #define UC(b) (((int) b) & 0xff)
***************
*** 5350,5358 ****
          (void) setsockopt(pdata, SOL_SOCKET, SO_SNDBUF, (char *) &TCPwindowsize, sizeof(TCPwindowsize));
          (void) setsockopt(pdata, SOL_SOCKET, SO_RCVBUF, (char *) &TCPwindowsize, sizeof(TCPwindowsize));
      }
- if (route_vectored)
-     pasv_addr = vect_addr;
- else
      pasv_addr = ctrl_addr;
      pasv_addr.sin_port = 0;
      delay_signaling(); /* we can't allow any signals while euid==0: kinch */
--- 5355,5360 ----
***************
*** 5446,5452 ****
      if (listen(pdata, 1) < 0)
          goto pasv_error;
      usedefault = 1;
!     a = (char *) &pasv_addr.sin_addr;
      p = (char *) &pasv_addr.sin_port;
  
  #define UC(b) (((int) b) & 0xff)
--- 5448,5457 ----
      if (listen(pdata, 1) < 0)
          goto pasv_error;
      usedefault = 1;
!     if (route_vectored)
!         a = (char *) &vect_addr.sin_addr;
!     else
!         a = (char *) &pasv_addr.sin_addr;
      p = (char *) &pasv_addr.sin_port;
  
  #define UC(b) (((int) b) & 0xff)

-- 

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

---

From: Paul Robertson <[email-masked]>
Date: Sat, 17 Apr 1999 08:34:32 -0400 (EDT)

Greg,

Great support! I sent my question on a Friday night at 10:30PM, and had
an answer three hours later.

The patch worked fine, and I can now do passive ftp transfers correctly.
I'll look into the interface problem you mention.

Cheers,

Paul