Running a FTP server behind an IPNAT machine

Abstract

These are some notes about running a FTP server in a LAN behind an IPNAT machine. The FTP server is supposed to do passive FTP. The setup is one machine doing the NAT and another one running an FTP server. We use NetBSD 1.5.x as the operating system and lukemftpd as FTP server.

1. Introduction

This document covers the problem of running a FTP server that is able to run in passive mode (for futher explanation see below) in a LAN behind a IPNAT machine.

                       _____
        +--------+   _(    _)        +-------+   +--------+
        | Client |--(____    )-------| IPNAT |---| Server |
        +--------+    (_(___)        +-------+   +--------+

                     INTERNET

This might lead to problems as it causes the FTP server to run in active mode. There are, however, some FTP clients that aren't able to communicate in active mode, e. g. most web browsers. So one might want to run passive FTP.

I found a document dealing with this problem on OpenBSD [1]. It's rather complicated and I never actually managed to get the described setup working with my NetBSD machines. But then there's the ftpd daemon that comes with NetBSD and which is available for other Unices, too: lukemftpd. (You may use a different FTP server with similar capabilities to those mentioned in section 3.2, see also [2].) Using this server causes the whole problem to vanish and hide to a lonely, dark and forgotten place. :-)

I'll use two NetBSD machines (around release 1.5) for NAT and FTP server. They're running IP Filter v3.4.9 and NetBSD-ftpd 20010329. (Note that the NetBSD ftpd is called «lukemftpd» in most distributions.)

2. Passive FTP and NAT

First let me say a few things about the FTP protocol. I cite Ph. LelÚdy [1]

It uses two channels between client and server. The first one is used the usual way - the client settles a connection to port 21 of the server - , it is used only for commands and is permanent. The second is settled each time a data transfer has to occur (directory listings as well as file transfers); which side settles the connection is a matter of choice: in passive mode, it's up to the client, in active mode it's up to the server. This connection is difficult to manage, the IP address may be wrong and the port number isn't fixed.

Now, there's a problem with the passive mode. Again I quote Ph. LelÚdy [1]:

Before data connection is settled, the passive side informs the other side of the address where the call-back has to occur. It's done via the famous PORT command.

When the passive side issuing the PORT command is behind a NAT-ing gateway, this address is usually wrong. This address contains two parts, the IP address and the port number. If the IP adress is wrong, you will get the infamous ``invalid PORT command'' message. If only the port number is wrong you will wait for ever for the data transfer to occur. Usually the port number choosen by the passive side is one that is not allowed to pass through the firewall.

3. Solution

I found that there's a really easy way to deal with this problem with IP Filter and lukemftpd.

3.1 Setting up the IPNAT machine

First you have to add the following lines to /etc/ipnat.conf on your IPNAT machine (gateway):

# Redirect all traffic on port 21 to our FTP server
rdr <ext-if> 0.0.0.0/0 port 21 -> <ftp-ip> port 21

<ext-if> is the external network interface of the IPNAT machine and <ftp-ip> is the IP address of your FTP server. The second thing is to redirect all ports that are in the port range (see below) for passive FTP to the FTP server's IP address:

# Redirect passive FTP ports
rdr <ext-if> 0.0.0.0/0 port 50000 -> <ftp-ip> port 50000
rdr <ext-if> 0.0.0.0/0 port 50001 -> <ftp-ip> port 50001
rdr <ext-if> 0.0.0.0/0 port 50002 -> <ftp-ip> port 50002
rdr <ext-if> 0.0.0.0/0 port 50003 -> <ftp-ip> port 50003
...
rdr <ext-if> 0.0.0.0/0 port 50010 -> <ftp-ip> port 50010

After having changed this file you need to reload the IPNAT tables:

/etc/rc.d/ipnat reload

3.2 Setting up the FTP server

To make your FTP server handle passive FTP correctly you need to edit /etc/ftpd.conf (see ftpd.conf(5)). Add the following lines:

# Set the address to advertise in the response to the PASV and LPSV commands
advertise all <ext-ip>

# Set the range of port number which will be used for the passive data port
portrange all 50000 50010 

Note that <ext-ip> is the IP address of the external interface of the IPNAT machine. You also might want to specify a bigger port range for passive connections; make sure you change the IPNAT configuration for passive port redirection when you change the port range. -- Well, that's it. :-)

4. Contact

Please feel free to contact me for questions, remarks, corrections on this document: <chris+www@westworks.ch>


References:

[1] «FTP and NAT: solutions», http://www.parinux.org/ressources/mini-howtos/natFTP.html

[2] «IPFilter FAQ: I have an FTP server behind an IPF firewall, and I'm having problems serving passive FTP.», http://home.earthlink.net/~jaymzh666/ipf/IPFprob.html#14