311 lines
12 KiB
HTML
311 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>ProFTPD: Firewalls, Routers, and NAT</title>
|
|
</head>
|
|
|
|
<body bgcolor=white>
|
|
|
|
<hr>
|
|
<center><h2><b><i>ProFTPD: Firewalls, Routers, and NAT</i></b></h2></center>
|
|
<hr>
|
|
|
|
<p>
|
|
<b>Basic NAT information</b><br>
|
|
NAT (<b>N</b>etwork <b>A</b>ddress <b>T</b>ranslation) is a system that acts
|
|
like a proxy, but on a "packet" level. When a computer on your
|
|
local network connects to a computer on the Internet, the NAT replaces the
|
|
"from" information of packets with its own address, making your
|
|
local network invisible to the Internet. Many firewalls perform NAT
|
|
duties as well, so the following information is valid in firewalled
|
|
environments as well.
|
|
|
|
<p>
|
|
For server systems, NAT can improve security and enable multiple servers to be
|
|
accessed using a single IP address. This is done by allowing certain ports
|
|
forwarded "inward" to the local network. However, the part of the
|
|
FTP protocol known as "passive" data transfers is not by default
|
|
compatible with NAT solutions. But NAT functionality <i>is</i> possible with
|
|
ProFTPD versions 1.2rc2 and later.
|
|
|
|
<p>
|
|
<b>Note</b>: for details on NAT configuration for Linux, read the Linux
|
|
IP-masq HOWTO at:
|
|
<pre>
|
|
<a href="http://tldp.org/HOWTO/IP-Masquerade-HOWTO/">tldp.org/HOWTO/IP-Masquerade-HOWTO/</a>
|
|
</pre>
|
|
or search for information concerning your OS of choice.
|
|
|
|
<p>
|
|
<b>Configuring ProFTPD behind NAT</b><br>
|
|
First configure your installed <code>proftpd</code> so that it works correctly
|
|
from inside the NAT. There are example configuration files included with the
|
|
source. Then add the <a href="../modules/mod_core.html#MasqueradeAddress"><code>MasqueradeAddress</code></a> directive
|
|
to your <code>proftpd.conf</code> file to define the public name or IP address
|
|
of the NAT. For example:
|
|
<pre>
|
|
MasqueradeAddress ftp.mydomain.com # using a DNS name
|
|
MasqueradeAddress 123.45.67.89 # using an IP address
|
|
</pre>
|
|
Now your <code>proftpd</code> will hide its local address and instead use the
|
|
public address of your NAT.
|
|
|
|
<p>
|
|
However, one <b>big</b> problem still exists. The passive FTP connections
|
|
will use ports from 1024 and up, which means that you must forward <i>all</i>
|
|
ports 1024-65535 from the NAT to the FTP server! And you have to allow many
|
|
(possibly) dangerous ports in your firewalling rules! Not a good situation.
|
|
For a good description of active versus passive FTP data transfers, see:
|
|
<pre>
|
|
<a href="http://slacksite.com/other/ftp.html">http://slacksite.com/other/ftp.html</a>
|
|
</pre>
|
|
To resolve this, simply use the <a href="../modules/mod_core.html#PassivePorts"><code>PassivePorts</code></a> directive
|
|
in your <code>proftpd.conf</code> to control what ports <code>proftpd</code>
|
|
will use for its passive data transfers:
|
|
<pre>
|
|
PassivePorts 60000 65535 # These ports should be safe...
|
|
</pre>
|
|
Note that if the configured range of ports is too small, connecting clients
|
|
may experience delays or be completely unable to operate when they
|
|
request passive data transfers. When the daemon cannot use one of the
|
|
ports in the configured range, it will fall back to using a kernel-assigned
|
|
port, and log a message reporting the issue. The clients' ability to
|
|
use this non-configured port will then depend on any NAT, router, or firewall
|
|
configuration.
|
|
<p>
|
|
Now start the FTP daemon and you should see something like:
|
|
<pre>
|
|
123.45.67.89 - Masquerading as '123.45.67.89' (123.45.67.89)
|
|
</pre>
|
|
in the log files.
|
|
|
|
<p>
|
|
<b>A Linux Example</b><br>
|
|
This example is for Linux kernel version 2.2.<i>x</i> with
|
|
<code>ipchains</code> and <code>ipmasqadm</code>. The examples below assume
|
|
that your FTP server has local address <code>192.168.1.2</code>.
|
|
|
|
<p>
|
|
First we need to enable NAT for our FTP server. As <code>root</code>:
|
|
<pre>
|
|
$ echo "1">/proc/sys/net/ipv4/ip_forward
|
|
$ ipchains -P forward DENY
|
|
$ ipchains -I forward -s 192.168.1.2 -j MASQ
|
|
</pre>
|
|
Now we load the <code>autofw</code> kernel module and forward ports 20 and 21
|
|
to the FTP server:
|
|
<pre>
|
|
$ insmod ip_masq_autofw
|
|
$ ipmasqadm autofw -A -r tcp 20 21 -h 192.168.1.2
|
|
</pre>
|
|
Then we forward ports for passive FTP transfers. In our
|
|
<code>proftpd.conf</code> file we restricted passive transfers to ports
|
|
60000-65535, so that is what we use here as well:
|
|
<pre>
|
|
$ ipmasqadm autofw -A -r tcp 60000 65535 -h 192.168.1.2
|
|
</pre>
|
|
|
|
<p>
|
|
If instead your Linux system uses IP Filters, then you might do something
|
|
like the following. First, update your <code>ipf.conf</code> with:
|
|
<pre>
|
|
# Allow passive FTP transfers from ports 49152 to 65534, the IANA-registered
|
|
# ephemeral port range.
|
|
pass in quick proto tcp from any to any port 49151 >< 65535 flags S keep state
|
|
</pre>
|
|
Then make sure that the changes take effect by using:
|
|
<pre>
|
|
$ ipf -Fa -f /path/to/ipf.conf
|
|
</pre>
|
|
|
|
<p>
|
|
<b>Double Checking</b><br>
|
|
Setting up <code>proftpd</code> that allows passive data transfers srequires
|
|
that a range of ports be forwarded from the NAT to the local network. This
|
|
could be a security hazard, but since you can specify what port range to use,
|
|
you are still able to setup relatively tight firewalling rules. To be sure
|
|
that you have no other processes listening on the ports you have specified
|
|
for passive transfers, use a port scanner such as <code>nmap</code>:
|
|
<pre>
|
|
$ nmap -sT -I -p 60000-65535 localhost
|
|
</pre>
|
|
If the result says something like:
|
|
<pre>
|
|
All 5536 scanned ports on localhost (127.0.0.1) are: closed
|
|
</pre>
|
|
then you should be safe.
|
|
|
|
<p><a name="FAQ">
|
|
<b>Frequently Asked Questions</b><br>
|
|
|
|
<p>
|
|
<font color=red>Question</font>: How do I know if my
|
|
<code>MasqueradeAddress</code> and <code>PassivePorts</code> configuration is
|
|
working?<br>
|
|
<font color=blue>Answer</font>: When performing a passive data transfer, an
|
|
FTP client sends the <code>PASV</code> command to the FTP server. The server
|
|
responds with the address and port to which the client should connect. For
|
|
example:
|
|
<pre>
|
|
227 Entering Passive Mode (127,0,0,1,19,6).
|
|
</pre>
|
|
The address and port are contained in the parentheses, formatted as
|
|
<i>a1,a2,a3,a4,p1,p2</i>, where the IP address is:
|
|
<pre>
|
|
a1.a2.a3.a4
|
|
</pre>
|
|
and the port number is:
|
|
<pre>
|
|
p1 * 256 + p2
|
|
</pre>
|
|
If the address seen in the server's response is not a public IP address
|
|
or the port is not in the port range configured by your
|
|
<code>PassivePorts</code>, double-check your <code>proftpd.conf</code>.
|
|
Non-public IP addresses are defined by <a href="http://www.faqs.org/rfcs/rfc1918.html">RFC 1918</a>, and include <code>10.<i>x</i></code>,
|
|
<code>172.16.<i>x</i></code> and <code>192.168.0.<i>x</i></code>.
|
|
|
|
<p>
|
|
<font color=red>Question</font>: I am using the <code>PassivePorts</code>
|
|
directive, but my FTP client still doesn't work. In the proftpd debug logging,
|
|
I see:
|
|
<pre>
|
|
May 20 17:00:55 www.example.com proftpd[10078] wwww.example.com (::ffff:1.2.3.4[::ffff:1.2.3.4]): Refused PORT 192,168,1,2,193,116 (address mismatch)
|
|
</pre>
|
|
<font color=blue>Answer</font>: The <code>PORT</code> there means that the
|
|
FTP client is requesting an <i>active</i> data transfer; this means that
|
|
proftpd is being asked to <i>actively</i> connect <b>to</b> the client
|
|
(to the given address 192.168.1.2, port 49524).
|
|
|
|
<p>
|
|
The first problem is, as the log message indicates, that the IP address
|
|
given in the <code>PORT</code> command, 192.168.1.2, does <b>not</b> match
|
|
the IP address from which the client connected (<i>i.e.</i> 1.2.3.4). By
|
|
default, proftpd will refuse to create a data transfer connection to anywhere
|
|
<b>except</b> back to the requesting client's IP address; see the
|
|
<a href="../howto/FXP.html"><code>AllowForeignAddress</code></a> directive for
|
|
more information.
|
|
|
|
<p>
|
|
The next problem is that 192.168.1.2 IP address is not a publicly routable I
|
|
address; specifically, it is part of an
|
|
<a href="http://www.faqs.org/rfcs/rfc1918.html">RFC 1918</a> address space.
|
|
This means that is <b>not possible</b> for proftpd to connect to that
|
|
address (unless proftpd is located in the same LAN).
|
|
|
|
<p>
|
|
The solution for these situations is to <i>a)</i> configure proftpd to use
|
|
<b>both</b> <code>PassivePorts</code> <i>and</i> <code>MasqueradeAddress</code>,
|
|
and <i>b)</i> to configure your FTP client to request <i>passive</i> data
|
|
transfers (via the <code>PASV</code> and <code>EPSV</code> commands), rather
|
|
than active data transfers.
|
|
|
|
<p>
|
|
<font color=red>Question</font>: I am using <code>MasqueradeAddress</code>
|
|
in my config, using the external DNS name for my site, but <code>proftpd</code>
|
|
still returns the internal/LAN IP address in the <code>PASV</code> response.
|
|
Is it a bug?<br>
|
|
<font color=blue>Answer</font>: Most likely not. If you use something like:
|
|
<pre>
|
|
MasqueradeAddress <i>ftp.example.com</i>
|
|
</pre>
|
|
and see the internal IP address in the <code>PASV</code> response, it
|
|
suggests that <code>proftpd</code>, when starting up, resolves that DNS name
|
|
from within your LAN, and gets that internal IP address. Rather than using
|
|
the DNS name, you should explicitly use the external IP address in your
|
|
<code>MasqueradeAddress</code> directive:
|
|
<pre>
|
|
MasqueradeAddress <i>1.2.3.4</i>
|
|
</pre>
|
|
where "1.2.3.4" is your real external IP address.
|
|
|
|
<p>
|
|
<font color=red>Question</font>: Can I configure <code>proftpd</code> so that
|
|
it refuses to handle passive transfers?<br>
|
|
<font color=blue>Answer</font>: If you are using a version of
|
|
<code>proftpd</code> older than 1.2.10rc1, no. In 1.2.10rc1, support for
|
|
placing limits on the <code>PASV</code> and <code>PORT</code> (and their
|
|
IPv6 equivalents <code>EPSV</code> and <code>EPRT</code>) was added, so that
|
|
you could do the following:
|
|
<pre>
|
|
<Limit EPSV PASV>
|
|
DenyAll
|
|
</Limit>
|
|
</pre>
|
|
|
|
<p><a name="UsingClasses">
|
|
<font color=red>Question</font>: How can I make <code>proftpd</code> use
|
|
a different <code>MasqueradeAddress</code> based on the address of the
|
|
connecting client?<br>
|
|
<font color=blue>Answer</font>: This question usually arises in the case
|
|
where FTP clients connecting from inside the LAN see the same
|
|
<code>MasqueradeAddress</code> as external clients, which causes problems.
|
|
That <code>MasqueradeAddress</code> may be necessary in order to allow
|
|
external FTP clients to do passive data transfers. The internal clients
|
|
do not need it. To handle this, create a <code><VirtualHost></code>
|
|
section in your <code>proftpd.conf</code> to handle the LAN address of
|
|
the FTP server, the address that the internal clients are contacting.
|
|
In this <code><VirtualHost></code> section, make sure there is no
|
|
<code>MasqueradeAddress</code> directive. This way, the external FTP
|
|
clients "see" the configuration with the
|
|
<code>MasqueradeAddress</code> they need, and the internal FTP clients
|
|
"see" a different configuration, one with no
|
|
<code>MasqueradeAddress</code>.
|
|
|
|
<p>
|
|
For those that need to see a concrete example configuration of this:
|
|
<pre>
|
|
ServerName "Some Server Name"
|
|
MasqueradeAddress my.domain.com
|
|
PassivePorts 60000 65535
|
|
|
|
<font color=green># Note that your LAN address should be used here</font>
|
|
<VirtualHost 192.168.0.10>
|
|
ServerName "Some Other Server Name"
|
|
|
|
<font color=blue># Note that there is <b>no</b> MasqueradeAddress directive
|
|
# used in this section!</font>
|
|
</VirtualHost>
|
|
</pre>
|
|
|
|
<p>
|
|
On the other hand, there <em>can</em> be cases where you really do need
|
|
different <code>MasqueradeAddress</code> values, <i>in the same vhost</i>,
|
|
depending on the client IP address. For these situations, you should
|
|
use <a href="Classes.html">classes</a> and the
|
|
<a href="../contrib/mod_ifsession.html"><code>mod_ifsession</code></a>
|
|
module, like so:
|
|
<pre>
|
|
<IfModule mod_ifsession.c>
|
|
# Define a class for internal clients
|
|
<Class internal>
|
|
From 10.0.0.0/8
|
|
</Class>
|
|
|
|
# Internal clients get a different MasqueradeAddress
|
|
<IfClass internal>
|
|
MasqueradeAddress 10.1.2.3
|
|
</IfClass>
|
|
|
|
# All other clients get some different, public MasqueradeAddress
|
|
<IfClass !internal>
|
|
MasqueradeAddress 1.2.3.4
|
|
</IfClass>
|
|
</IfModule>
|
|
</pre>
|
|
|
|
<p>
|
|
<hr>
|
|
Contributor: Tobias Ekbom <tobias <i>at</i> vallcom <i>dot</i>com><br>
|
|
<hr>
|
|
|
|
<p>
|
|
<hr>
|
|
<font size=2><b><i>
|
|
© Copyright 2017 The ProFTPD Project<br>
|
|
All Rights Reserved<br>
|
|
</i></b></font>
|
|
<hr>
|
|
|
|
</body>
|
|
</html>
|