shorewall_code/docs/FTP.xml
judas_iscariote 109b948d42 I always forget to update the pub date, this is not going
to happend anymore. :)


git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@4194 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
2006-07-07 01:04:16 +00:00

368 lines
15 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<article id="FTP">
<!--$Id$-->
<articleinfo>
<title>Shorewall and FTP</title>
<authorgroup>
<author>
<firstname>Tom</firstname>
<surname>Eastep</surname>
</author>
</authorgroup>
<pubdate><?dbtimestamp format="Y/m/d"?></pubdate>
<copyright>
<year>2003</year>
<year>2004</year>
<year>2005</year>
<year>2006</year>
<holder>Thomas M. Eastep</holder>
</copyright>
<legalnotice>
<para>Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License, Version
1.2 or any later version published by the Free Software Foundation; with
no Invariant Sections, with no Front-Cover, and with no Back-Cover
Texts. A copy of the license is included in the section entitled
<quote><ulink url="GnuCopyright.htm">GNU Free Documentation
License</ulink></quote>.</para>
</legalnotice>
</articleinfo>
<caution>
<para><emphasis role="bold">This article applies to Shorewall 3.0 and
later. If you are running a version of Shorewall earlier than Shorewall
3.0.0 then please see the documentation for that
release.</emphasis></para>
</caution>
<section>
<title>FTP Protocol</title>
<para>FTP transfers involve two TCP connections. The first <emphasis
role="bold">control</emphasis> connection goes from the FTP client to port
21 on the FTP server. This connection is used for logon and to send
commands and responses between the endpoints. Data transfers (including
the output of <quote>ls</quote> and <quote>dir</quote> commands) requires
a second data connection. The <emphasis role="bold">data</emphasis>
connection is dependent on the <emphasis role="bold">mode</emphasis> that
the client is operating in:</para>
<variablelist>
<varlistentry>
<term>Passive Mode</term>
<listitem>
<para>(often the default for web browsers) -- The client issues a
PASV command. Upon receipt of this command, the server listens on a
dynamically-allocated port then sends a PASV reply to the client.
The PASV reply gives the IP address and port number that the server
is listening on. The client then opens a second connection to that
IP address and port number.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Active Mode</term>
<listitem>
<para>(often the default for line-mode clients) -- The client
listens on a dynamically-allocated port then sends a PORT command to
the server. The PORT command gives the IP address and port number
that the client is listening on. The server then opens a connection
to that IP address and port number; the <emphasis role="bold">source
port</emphasis> for this connection is 20 (ftp-data in
/etc/services).</para>
</listitem>
</varlistentry>
</variablelist>
<para>You can see these commands in action using your linux ftp
command-line client in debugging mode. Note that my ftp client defaults to
passive mode and that I can toggle between passive and active mode by
issuing a <quote>passive</quote> command:</para>
<programlisting>[teastep@wookie Shorewall]$ <emphasis role="bold">ftp ftp1.shorewall.net</emphasis>
Connected to lists.shorewall.net.
220-=(&lt;*&gt;)=-.:. (( Welcome to PureFTPd 1.0.12 )) .:.-=(&lt;*&gt;)=-
220-You are user number 1 of 50 allowed.
220-Local time is now 10:21 and the load is 0.14. Server port: 21.
220 You will be disconnected after 15 minutes of inactivity.
500 Security extensions not implemented
500 Security extensions not implemented
KERBEROS_V4 rejected as an authentication type
Name (ftp1.shorewall.net:teastep): <command>ftp</command>
331-Welcome to ftp.shorewall.net
331-
331 Any password will work
Password:
230 Any password will work
Remote system type is UNIX.
Using binary mode to transfer files.
ftp&gt; <emphasis role="bold">debug</emphasis>
Debugging on (debug=1).
ftp&gt; <emphasis role="bold">ls</emphasis>
---&gt; <emphasis>PASV</emphasis>
<emphasis>227 Entering Passive Mode (192,168,1,193,195,210)</emphasis>
---&gt; LIST
150 Accepted data connection
drwxr-xr-x 5 0 0 4096 Nov 9 2002 archives
drwxr-xr-x 2 0 0 4096 Feb 12 2002 etc
drwxr-sr-x 6 0 50 4096 Feb 19 15:24 pub
226-Options: -l
226 3 matches total
ftp&gt; <emphasis role="bold">passive</emphasis>
Passive mode off.
ftp&gt; <emphasis role="bold">ls</emphasis>
<emphasis>---&gt; PORT 192,168,1,3,142,58</emphasis>
200 PORT command successful
---&gt; LIST
150 Connecting to port 36410
drwxr-xr-x 5 0 0 4096 Nov 9 2002 archives
drwxr-xr-x 2 0 0 4096 Feb 12 2002 etc
drwxr-sr-x 6 0 50 4096 Feb 19 15:24 pub
226-Options: -l
226 3 matches total
ftp&gt;</programlisting>
<para>Things to notice:</para>
<orderedlist>
<listitem>
<para>The commands that I issued are <emphasis role="bold">strongly
emphasized</emphasis>.</para>
</listitem>
<listitem>
<para>Commands sent by the client to the server are preceded by
---&gt;</para>
</listitem>
<listitem>
<para>Command responses from the server over the control connection
are numbered.</para>
</listitem>
<listitem>
<para>FTP uses a comma as a separator between the bytes of the IP
address; and</para>
</listitem>
<listitem>
<para>When sending a port number, FTP sends the MSB then the LSB and
separates the two bytes by a comma. As shown in the PORT command, port
142,58 translates to 142*256+58 = 36410.</para>
</listitem>
</orderedlist>
</section>
<section>
<title>Linux FTP connection-tracking</title>
<para>Given the normal loc-&gt;net policy of ACCEPT, passive mode access
from local clients to remote servers will always work but active mode
requires the firewall to dynamically open a <quote>hole</quote> for the
server's connection back to the client. Similarly, if you are running an
FTP server in your local zone then active mode should always work but
passive mode requires the firewall to dynamically open a
<quote>hole</quote> for the client's second connection to the server. This
is the role of FTP connection-tracking support in the Linux kernel.</para>
<para>Where any form of NAT (SNAT, DNAT, Masquerading) on your firewall is
involved, the PORT commands and PASV responses may also need to be
modified by the firewall. This is the job of the FTP nat support kernel
function.</para>
<para>Including FTP connection-tracking and NAT support normally means
that the modules <quote>ip_conntrack_ftp</quote> and
<quote>ip_nat_ftp</quote> need to be loaded. Shorewall automatically loads
these <quote>helper</quote> modules from
/lib/modules/&lt;<emphasis>kernel-version</emphasis>&gt;/kernel/net/ipv4/netfilter/
and you can determine if they are loaded using the <quote>lsmod</quote>
command. The &lt;<emphasis>kernel-version</emphasis>&gt; may be obtained
by typing</para>
<programlisting><command>uname -r</command></programlisting>
<example>
<title></title>
<programlisting>[root@lists etc]# lsmod
Module Size Used by Not tainted
autofs 12148 0 (autoclean) (unused)
ipt_TOS 1560 12 (autoclean)
ipt_LOG 4120 5 (autoclean)
ipt_REDIRECT 1304 1 (autoclean)
ipt_REJECT 3736 4 (autoclean)
ipt_state 1048 13 (autoclean)
ip_nat_irc 3152 0 (unused)
<emphasis role="bold">ip_nat_ftp 3888 0 (unused)</emphasis>
ip_conntrack_irc 3984 1
<emphasis role="bold">ip_conntrack_ftp 5008 1</emphasis>
ipt_multiport 1144 2 (autoclean)
ipt_conntrack 1592 0 (autoclean)
iptable_filter 2316 1 (autoclean)
iptable_mangle 2680 1 (autoclean)
iptable_nat 20568 3 (autoclean) [ipt_REDIRECT ip_nat_irc ip_nat_ftp]
ip_conntrack 26088 5 (autoclean) [ipt_REDIRECT ipt_state ip_nat_irc
ip_nat_ftp ip_conntrack_irc ip_conntrack_ftp
ipt_conntrack iptable_nat]
ip_tables 14488 12 [ipt_TOS ipt_LOG ipt_REDIRECT ipt_REJECT ipt_state
ipt_multiport ipt_conntrack iptable_filter
iptable_mangle iptable_nat]
tulip 42464 0 (unused)
e100 50596 1
keybdev 2752 0 (unused)
mousedev 5236 0 (unused)
hid 20868 0 (unused)
input 5632 0 [keybdev mousedev hid]
usb-uhci 24684 0 (unused)
usbcore 73280 1 [hid usb-uhci]
ext3 64704 2
jbd 47860 2 [ext3]
[root@lists etc]#</programlisting>
</example>
<para>If you want Shorewall to load these modules from an alternate
directory, you need to set the MODULESDIR variable in
/etc/shorewall/shorewall.conf to point to that directory.</para>
</section>
<section>
<title>FTP on Non-standard Ports</title>
<para>The above discussion about commands and responses makes it clear
that the FTP connection-tracking and NAT helpers must scan the traffic on
the control connection looking for PASV and PORT commands as well as PASV
responses. If you run an FTP server on a nonstandard port or you need to
access such a server, you must therefore let the helpers know by
specifying the port in /etc/shorewall/modules entries for the helpers.
<caution>
<para>You must have modularized FTP connection tracking support in
order to use FTP on a non-standard port.</para>
</caution></para>
<example>
<title>if you run an FTP server that listens on port 49 or you need to
access a server on the internet that listens on that port then you would
have:</title>
<programlisting>loadmodule ip_conntrack_ftp ports=21,49
loadmodule ip_nat_ftp ports=21,49 # NOTE: This is not necessary with kernel 2.6.11 and later!</programlisting>
<para><note>
<para>you MUST include port 21 in the ports list or you may have
problems accessing regular FTP servers.</para>
</note></para>
<para>If there is a possibility that these modules might be loaded
before Shorewall starts, then you should include the port list in
/etc/modules.conf:</para>
<programlisting>options ip_conntrack_ftp ports=21,49
options ip_nat_ftp ports=21,49 # NOTE: This is not necessary with kernel 2.6.11 and later!</programlisting>
<para><important>
<para>Once you have made these changes to /etc/shorewall/modules
and/or /etc/modules.conf, you must either:</para>
<orderedlist>
<listitem>
<para>Unload the modules and restart shorewall:</para>
<programlisting><command>rmmod ip_nat_ftp; rmmod ip_conntrack_ftp; shorewall restart</command></programlisting>
</listitem>
<listitem>
<para>Reboot</para>
</listitem>
</orderedlist>
</important></para>
</example>
</section>
<section id="Rules">
<title>Rules</title>
<warning>
<para>If you run an FTP server behind your firewall and your server
offers a method of specifying the external IP address of your firewall,
DON'T USE THAT FEATURE OF YOUR SERVER. Using that option will defeat the
purpose of the ftp helper modules and can result in a server that
doesn't work.</para>
</warning>
<para>If the policy from the source zone to the destination zone is ACCEPT
and you don't need DNAT (see <ulink url="FAQ.htm#faq30">FAQ 30</ulink>)
then <emphasis role="bold">you need no rule</emphasis>.</para>
<para>Otherwise, for FTP you need exactly <emphasis
role="bold">one</emphasis> rule:</para>
<programlisting>#ACTION SOURCE DESTINATION PROTO PORT(S) SOURCE ORIGINAL
# PORT(S) DESTINATION
ACCEPT or &lt;<emphasis>source</emphasis>&gt; &lt;<emphasis>destination</emphasis>&gt; tcp 21 - &lt;external IP addr&gt; if
DNAT ACTION = DNAT</programlisting>
<para>You need an entry in the ORIGINAL DESTINATION column only if the
ACTION is DNAT, you have multiple external IP addresses and you want a
specific IP address to be forwarded to your server.</para>
<para>Note that you do <emphasis role="bold">NOT </emphasis>need a rule
with 20 (ftp-data) in the PORT(S) column. If you post your rules on the
mailing list and they show 20 in the PORT(S) column, I will know that you
haven't read this article and I will either ignore your post or tell you
to RTFM.</para>
<para>Shorewall includes an FTP macro that simplifies creation of FTP
rules. The macro source is in
<filename>/usr/share/shorewall/macro.FTP</filename>. Using the macro is
the preferred way to generate the rules described above. Here are a couple
of examples.</para>
<para><example>
<title>Server running behind a Masquerading Gateway</title>
<para>Suppose that you run an FTP server on 192.168.1.5 in your local
zone using the standard port (21). You need this rule:</para>
<programlisting>#ACTION SOURCE DESTINATION PROTO PORT(S) SOURCE ORIGINAL
# PORT(S) DESTINATION
FTP/DNAT net loc:192.168.1.5</programlisting>
</example><example>
<title>Allow your DMZ FTP access to the Internet</title>
<programlisting>#ACTION SOURCE DESTINATION PROTO PORT(S) SOURCE ORIGINAL
# PORT(S) DESTINATION
FTP/ACCEPT dmz net</programlisting>
</example></para>
<para>Note that the FTP connection tracking in the kernel cannot handle
cases where a PORT command (or PASV reply) is broken across two packets or
is misssing the ending &lt;cr&gt;/&lt;lf&gt;. When such cases occur, you
will see a console message similar to this one:</para>
<programlisting>Apr 28 23:55:09 gateway kernel: conntrack_ftp: partial PORT 715014972+1</programlisting>
<para>I see this problem occasionally with the FTP server in my DMZ. My
solution is to add the following rule:</para>
<programlisting>#ACTION SOURCE DESTINATION PROTO PORT(S) SOURCE ORIGINAL
# PORT(S) DESTINATION
ACCEPT:info dmz net tcp - 20</programlisting>
<para>The above rule accepts and logs all active mode connections from my
DMZ to the net.</para>
</section>
</article>