http://www.perlmonks.org?node_id=712533


in reply to Net::FTPServer problem with active/passive connections

To Net::FTPServer, 'proxy ftp' enabled means the server is allowed to connect to any machine in the world. That error message makes me think the server's trying to connect back to an address other than what it thinks is the client address. Is there anything about your setup that would cause this?

HTH,
mtp


email: perl -e 'print reverse map { chr( ord($_)-1 ) } split //, "\x0bufo/hojsfufqAofc";'
  • Comment on Re: Net::FTPServer problem with active/passive connections

Replies are listed 'Best First'.
Re^2: Net::FTPServer problem with active/passive connections
by isync (Hermit) on Sep 19, 2008 at 15:34 UTC
    Actually my intuition already was that Net::FTPServer isn't the problem...

    A look into the code of Net::FTPServer revealed that the error is raised by
    if (!$self->{_test_mode} && $hostaddrstring ne $self->{peeraddrstr +ing}) { # See RFC 2577 section 3. $self->reply (504, "Proxy FTP is not allowed on this server.") +; return; }
    so $self->{peeraddrstring} is compared with $hostaddrstring.

    Data::Dumper shows me that $self->{peeraddrstring} correctly holds the IP of my client machine. And $hostaddrstring is constructed from the address my client sends to the ftp-server via the PORT command.

    Here lies the error. As I could see in my gFTP log, gFTP sends: PORT "192,168,xxx,xxx,xxx,xxx"
    And this finally ends up in the $hostaddrstring. But as you can see from the address, this is the local-network-address of my workstation on our LAN here and not my actual public IP. That's why the test in Net::FTPServer fails.

    My FTP client does this all the time and I don't know why other FTP servers never complained. Net::FTPServer seems to be stricter here.

    Anyway, now that we know Net::FTPServer isn't the actual problem. Does anyone know where in my client/workstation/linux-machine setup the flaw is? (as a reminder: if the test would pass, for example by enabling proxy ftp, my ftp-client goes into infinite wait with "150 Opening data connection for file listing.")

      Here lies the error. As I could see in my gFTP log, gFTP sends: PORT "192,168,xxx,xxx,xxx,xxx" And this finally ends up in the $hostaddrstring. But as you can see from the address, this is the local-network-address of my workstation on our LAN here and not my actual public IP. That's why the test in Net::FTPServer fails.

      NAT doesn't work well with clients that are actually servers. FTP in active mode is such a client. When requesting a file (including a directory listing), the server creates a connection to the client over which the data is sent.

      FTP, being a very common protocol, is usually intercepted by NAT and "fixed". Instances of PORT are rewritten from the client's internal address to the router's external address.

      Your problem is that this is not occurring. I can think of three reasons

      • Your NAT software isn't capable of fixing FTP PORT commands. (Not likely)
      • Your NAT software isn't configured to fix FTP PORT commands.
      • Your NAT software doesn't realize your connection is an FTP communication. (Most likely)

      How does NAT know whether a socket is a used as an FTP command connection? Commonly,

      • Any outgoing connection to TCP port 21 is presumed to be an FTP command connection.
      • All other connections are presumed to not be FTP command connections.

      Is your server running on port 21?

      Does anyone know where in my client/workstation/linux-machine setup the flaw is?

      Simply put, you aren't using passive mode. Most FTP clients default to passive mode. That way, all the connections are made from client to server.

      Section 3 of RFC 2577 describes how to mitigate or eliminate bounce attacks for proxy FTP. It recommends specifically against opening a port below 1024 on the remote host at the request of the PORT command. It also allows for disabling the PORT command altogether to prevent that particular form of network abuse. Disabling PORT for a mismatched address is a convenient security workaround.

      The code you quote is, in the latest Net::FTPServer on CPAN anyway, wrapped in a configuration if-block:

      unless ($self->config ("allow proxy ftp")) { if (!$self->{_test_mode} && $hostaddrstring ne $self->{peeraddrstr +ing}) { # See RFC 2577 section 3. $self->reply (504, "Proxy FTP is not allowed on this server.") +; return; } }
      I suggest that if you absolutely need to use the PORT command for FTP which validly appears to the server to be proxy FTP, that you enable 'allow proxy ftp' in the configuration. This is explained in this part of the documentation for the module:
      allow proxy ftp

      Allow proxy FTP. If this is set, then the FTP server can be told to actively connect to addresses and ports on any machine in the world. This is not such a great idea, but required if you follow the RFC very closely. If not set (the default), the FTP server will only connect back to the client machine.

      My preferred suggestion is to fix your NAT so that it handles FTP properly. As a last resort, open your server to attacking every machine on the Internet if you really must. That's what enabling proxy FTP does.