533 lines
26 KiB
HTML
533 lines
26 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>ProFTPD: AWS</title>
|
|
</head>
|
|
|
|
<body bgcolor=white>
|
|
|
|
<hr>
|
|
<center><h2><b>AWS and ProFTPD</b></h2></center>
|
|
<hr>
|
|
|
|
<p>
|
|
So you want to run ProFTPD on an AWS
|
|
<a href="https://aws.amazon.com/ec2/">EC2</a> instance? Due to FTP's nature as
|
|
a multi-connection protocol, it is not as straightforward to use FTP within AWS
|
|
EC2, but it <b>can be done</b>. Read on to find out how. <i>Note</i> that the
|
|
following documentation assumes that you know how to install and configure
|
|
ProFTPD already.
|
|
|
|
If you are only running individual FTP servers, then the sections on
|
|
<a href="#SGS">AWS security groups</a> and <a href="#Addresses">addresses</a>
|
|
are relevant. If you want to provide a "scalable" <em>pool/cluster</em> of
|
|
FTP servers, then the <a href="#ELBs">AWS Elastic Load Balancing</a> and
|
|
<a href="#Route53">AWS Route53</a> sections will also be of interest.
|
|
|
|
<p><a name="SGs">
|
|
<b>Security Groups</b><br>
|
|
Every EC2 instance belongs to one or more AWS <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html">Security Groups</a>
|
|
(often abbreviated as simply "SGs"). As the AWS documentation states, a
|
|
"security group" is a effectively a set of firewall rules controlling network
|
|
access to your EC2 instance. I tend to think of SGs more like NAT rules,
|
|
since the "firewall" is the EC2 network perimeter managed by Amazon, and
|
|
an SG dictates what holes to allow from the outside world into the EC2 internal
|
|
networks.
|
|
|
|
<p>
|
|
Clients wishing to make a connection to the <code>proftpd</code> running on
|
|
your EC2 instance, be it FTP, FTPS, SFTP, or SCP, will thus need to be allowed
|
|
to connect by one (or more) of your SGs. Assuming your <code>proftpd</code>
|
|
listens on the standard FTP control port (21), you would configure one of your
|
|
SGs to allow access to that port, from any IP address, using the AWS CLI like
|
|
so:
|
|
<pre>
|
|
$ aws ec2 authorize-security-group-ingress \
|
|
--group-id <em>sg-XXXX</em> \
|
|
--protocol tcp \
|
|
--port 21 \
|
|
--cidr 0.0.0.0/0
|
|
</pre>
|
|
<b>Note</b> that you do <b>not</b> need to allow access to port 20! Many,
|
|
many sites/howtos recommend opening port 20 in addition to port 21 for FTP
|
|
access, but it <i>simply not needed</i>. For <i>active</i> data transfers
|
|
(<i>i.e.</i> where the FTP server <i>actively</i> connects back to the
|
|
client machine for the data transfer), the <i>source</i> port will be port 20.
|
|
But <i>incoming</i> connections for FTP will <b>never</b> be to port 20.
|
|
|
|
<p>
|
|
If you are allowing SFTP/SCP connections, <i>e.g.</i> to your
|
|
<code>proftpd</code>, running the <a href="http://www.proftpd.org/docs/contrib/mod_sftp.html"><code>mod_sftp</code></a> module on the standard SSH port (22):
|
|
<pre>
|
|
$ aws ec2 authorize-security-group-ingress \
|
|
--group-id <em>sg-YYYY</em> \
|
|
--protocol tcp \
|
|
--port 22 \
|
|
--cidr 0.0.0.0/0
|
|
</pre>
|
|
<b>Note</b>: I recommend using different SGs for your FTP/FTPS rules and your
|
|
SFTP/SCP rules. FTP/FTPS rules are more complex, and it is more clear to
|
|
manage an SG named "FTP", with all of the related FTP rules, and separately
|
|
to have an SG named "SFTP", with the SFTP/SCP related rules.
|
|
|
|
<p>
|
|
If you are <em>only</em> allowing SFTP/SCP access, that should suffice for
|
|
the security group configuration for your instance. Allowing FTP/FTPS
|
|
connections requires more security group tweaks.
|
|
|
|
<p>
|
|
FTP uses multiple TCP connections: one for the control connection, and separate
|
|
<em>other</em> connections for data transfers (directory listings and file
|
|
uploads/downloads). The ports used for these data connections are dynamically
|
|
negotiated over the control connection; it is this dynamic nature of the
|
|
data connections which causes complexity with network access rules. This
|
|
site does a great job of describing these issues more in detail:
|
|
<pre>
|
|
<a href="http://slacksite.com/other/ftp.html">http://slacksite.com/other/ftp.html</a>
|
|
</pre>
|
|
Remember how I said that SGs are similar to NAT rules? This similarity is
|
|
one of the reasons why the ProFTPD <a href="http://www.proftpd.org/docs/howto/NAT.html">NAT</a> howto is relevant here as well.
|
|
|
|
<p>
|
|
We want to configure ProFTPD to use a known range of ports for its passive
|
|
data transfers, and then we want to configure our FTP SG to allow access to
|
|
that known port range. Thus we would use something like this in the
|
|
<code>proftpd.conf</code>:
|
|
<pre>
|
|
PassivePorts 60000 65535
|
|
</pre>
|
|
And then, to configure the SG to allow those ports:
|
|
<pre>
|
|
$ aws ec2 authorize-security-group-ingress \
|
|
--group-id <em>sg-XXXX</em> \
|
|
--protocol tcp \
|
|
--port 60000-65534 \
|
|
--cidr 0.0.0.0/0
|
|
</pre>
|
|
The SFTP/SCP protocols only use a single TCP connection, and thus they do not
|
|
require any other special configuration/access rules.
|
|
|
|
<p><a name="Addresses">
|
|
<b>Public <i>vs</i> Private Instance Addresses</b><br>
|
|
Every EC2 instance with have its own local/private IP address and DNS name,
|
|
automatically assigned by AWS. Instances <i>may</i> also be automatically
|
|
assigned <i>public</i> IP addresses/DNS names as well, depending on various
|
|
factors. The AWS docs on <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html">instance addressing</a> discuss those
|
|
factors in greater detail.
|
|
|
|
<p>
|
|
If your EC2 instance will be supporting FTP/FTPS sessions, then you will need
|
|
to determine whether your instance has a public address. If so, that address
|
|
needs to be configured using the <a href="http://www.proftpd.org/docs/modules/mod_core.html#MasqueradeAddress"><code>MasqueradeAddress</code></a> directive.
|
|
Why? When an FTP client negotiates a
|
|
<a href="http://slacksite.com/other/ftp.html">passive data transfer</a>,
|
|
ProFTPD tells that FTP client an address, and a port, to which to connect to
|
|
transfer the data. For EC2 instances with a public address, that public
|
|
address is what ProFTPD needs to convey to the FTP client, and the
|
|
<code>MasqueradeAddress</code> is the directive that does so.
|
|
|
|
<p>
|
|
So how can you tell what the public address of your EC2 instance is, if it
|
|
even has one? You can use the EC2 <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html">instance metadata</a>, via
|
|
<code>curl</code>, like so:
|
|
<pre>
|
|
$ curl http://169.254.169.254/latest/meta-data/public-hostname
|
|
</pre>
|
|
<b>If</b> your instance has a public address, the DNS name to use would be
|
|
returned. Otherwise, you might see something like this:
|
|
<pre>
|
|
$ curl http://169.254.169.254/latest/meta-data/public-hostname
|
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head>
|
|
<title>404 - Not Found</title>
|
|
</head>
|
|
<body>
|
|
<h1>404 - Not Found</h1>
|
|
</body>
|
|
</html>
|
|
</pre>
|
|
which indicates that your EC2 instances does <b>not</b> have a public address.
|
|
And if your instance does not <em>have</em> a public address, then you do
|
|
<em>not</em> need to use the <code>MasqueradeAddress</code> directive.
|
|
|
|
<p>
|
|
Here's one solution for handling this situation: obtain the public hostname
|
|
for your instance, store it in an environment variable, and then use that
|
|
environment variable in your <code>proftpd.conf</code>:
|
|
<pre>
|
|
$ export EC2_PUBLIC_HOSTNAME=`curl -f -s http://169.254.169.254/latest/meta-data/public-hostname`
|
|
</pre>
|
|
The <code>-f</code> option is necessary, in case the instance does not
|
|
<i>have</i> a public address. The <code>-s</code> option simply makes for
|
|
quieter shell scripts. Then, in your <code>proftpd.conf</code>, you might
|
|
use:
|
|
<pre>
|
|
MasqueradeAddress %{env:EC2_PUBLIC_HOSTNAME}
|
|
</pre>
|
|
If the instance does not have a public address, though, that environment
|
|
variable will be the empty string, and <code>proftpd</code> will fail to start
|
|
up because of that. Better would be to automatically handle the
|
|
"no public address" case, if we can. Assume you have a shell script for
|
|
starting <code>proftpd</code> which does something like this, using our
|
|
<code>EC2_PUBLIC_HOSTNAME</code> environment variable:
|
|
<pre>
|
|
PROFTPD_ARGS=""
|
|
|
|
# If we have a public hostname, then the string will not be
|
|
# zero length, and we define a property for ProFTPD's use.
|
|
if [ ! -z "$EC2_PUBLIC_HOSTNAME" ]; then
|
|
PROFTPD_ARGS="$PROFTPD_ARGS -DUSE_MASQ_ADDR"
|
|
fi
|
|
</pre>
|
|
Then, in your <code>proftpd.conf</code>, you use <i>both</i> that property
|
|
<i>and</i> the environment variable notation:
|
|
<pre>
|
|
<IfDefined USE_MASQ_ADDR>
|
|
MasqueradeAddress %{env:EC2_PUBLIC_HOSTNAME}
|
|
</IfDefined>
|
|
</pre>
|
|
|
|
<p>
|
|
Fortunately the EC2 instance addressing does not require any additional
|
|
changes/tweaks to the AWS Security Groups.
|
|
|
|
<p><a name="ELBs">
|
|
<b>Elastic Load Balancing</b><br>
|
|
Now that you have ProFTPD up and running on your EC2 instance, and you can
|
|
connect using FTP/FTPS and SFTP/SCP, and browse directories and upload and
|
|
download files, you are probably thinking about how to have more than one
|
|
instance for your FTP service. After all, you want redundancy for your FTP
|
|
servers just like you have for your HTTP servers, right? And for HTTP servers,
|
|
you would use an AWS <a href="http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elastic-load-balancing.html">Elastic Load Balancer</a>
|
|
(often called an "ELB"). Why not use the same technique for FTP? <i>Can</i>
|
|
you configure an ELB for FTP?
|
|
|
|
<p>
|
|
Yes, ELBs can be used for FTP. Like SGs, though, it's complicated by FTP's
|
|
use of multiple TCP connections; for SFTP/SCP, ELBs are simpler to configure.
|
|
|
|
<p>
|
|
The first thing to keep in mind is that ELBs only distribute (<i>i.e.</i>
|
|
"balance") connections in a <a href="http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/how-elb-works.html">round-robin fashion</a> among
|
|
the backend TCP servers; they do <b>not</b> distribute connections based on the
|
|
<em>load</em> of those backend servers. (The balancing algorithm is slightly
|
|
different for HTTP servers, but that does not apply to ProFTPD.) This means
|
|
that <em>any</em> user might connect to <em>any</em> of your ProFTPD instances;
|
|
this, in turn, means that users must be able to login on all instances,
|
|
<b>and</b> that the files for all users should be available on all instances.
|
|
These requirements lead to the requirements for centralized/shared
|
|
authentication data, and for shared filesystems. The centralized/shared
|
|
authentication data can be handled by using <i>e.g.</i> SQL databases,
|
|
LDAP directories, or even synchronized password files. For shared filesystems,
|
|
the popular approaches are:
|
|
<ul>
|
|
<li><a href="https://github.com/s3fs-fuse/s3fs-fuse">s3fs</a>
|
|
<li>NFS
|
|
<li>Samba
|
|
<li>Gluster
|
|
<li><a href="https://aws.amazon.com/efs/">AWS EFS</a>
|
|
</ul>
|
|
There are probably other solutions as well; the key is to have the users'
|
|
files available on any/every instance.
|
|
|
|
<p>
|
|
The next thing to keep in mind is whether you have an EC2 Classic account,
|
|
or whether you are using AWS <a href="https://aws.amazon.com/vpc/">VPC</a>.
|
|
Chances are that you are using a VPC. ELBs for an EC2 Classic account can
|
|
only be configured to listen on a <a href="http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-listener-config.html">restricted list</a>
|
|
of ports, <i>i.e.</i>:
|
|
<ul>
|
|
<li>25 (SMTP)
|
|
<li>80 (HTTP)
|
|
<li>443 (HTTPS)
|
|
<li>465 (SMTPS)
|
|
<li>587 (SMTP mail submission)
|
|
<li>1024-65535
|
|
</ul>
|
|
This means that if you have an EC2 Classic account <b>and</b> want to use
|
|
an ELB for your FTP/SFTP servers, you will need to run those servers on
|
|
non-standard ports, in the 1024-65535 range. ELBs within a VPC, on the
|
|
other hand, can listen on <b>any</b> port.
|
|
|
|
<p>
|
|
Let's assume that you are using a VPC, and thus you configure a TCP listener
|
|
on your ELB for port 21, which uses the instance port 21. And for SFTP/SCP,
|
|
it would be a TCP listener for port 22, using instance port 22. Obviously
|
|
you would not use HTTP or HTTPS listeners, but what about an SSL listener,
|
|
for FTPS? No. An SSL listener performs the SSL/TLS handshake <i>first</i>,
|
|
then forwards the plaintext messages to the backend instance. But FTPS is
|
|
a <a href="https://en.wikipedia.org/wiki/STARTTLS">"STARTTLS"</a> protocol,
|
|
which means the connection is <i>first</i> unencrypted, and then feature
|
|
negotiation happens on that connection, and <i>then</i> the SSL/TLS handshake
|
|
happens. ELBs do not support STARTTLS protocols, thus you cannot use them
|
|
for terminating SSL/TLS sessions for FTP servers.
|
|
|
|
<p>
|
|
Your ProFTPD configuration might use multiple different ports, for different
|
|
<code><VirtualHost></code>s. Your ELB would need a different TCP
|
|
listener for each of those separate ports. However, now that ProFTPD supports
|
|
the FTP <code>HOST</code> command (which allows for proper name-based virtual
|
|
hosts in FTP, just like HTTP 1.1 has via its <code>Host</code> header), you
|
|
<i>should</i> only need on TCP listener now.
|
|
|
|
<p>
|
|
An ELB wants to perform health checks on its backend instances, to know that
|
|
that instance is up, running, and available to handle connections. ELBs
|
|
can perform HTTP requests as healthchecks, or make TCP connections. ProFTPD
|
|
is not an HTTP server, so using TCP health checks is necessary. You would
|
|
configure the ELB to make TCP connections to ProFTPD port, <i>e.g.</i> port
|
|
21 for FTP/FTPS, and/or port 22 for SFTP/SCP.
|
|
|
|
<p>
|
|
What about the range of ports defined via <code>PassivePorts</code>, that
|
|
you had to allow in your SG? Does your ELB need TCP listeners for all of
|
|
those ports, too? No. To understand why, we need to examine in detail just
|
|
how passive data transfers work in FTP. An FTP client connects to your
|
|
FTP server, through the ELB, like this, for its control connection:
|
|
<pre>
|
|
client --- <i>ctrl</i> ---> ELB:21 --- <i>ctrl</i> ---> instance:21
|
|
</pre>
|
|
The client and server negotiate a passive data transfer; the FTP server
|
|
tells the client, over the control connection, an address and port to which
|
|
to connect. Now, let's assume that ProFTPD gives the address of the ELB,
|
|
and one of the <code>PassivePorts</code>; we'l use port 65000 for this example.
|
|
The FTP client connects to the address/port <em>on the ELB</em>, like this:
|
|
<pre>
|
|
client --- <i>data</i> ---> ELB:65000 --- <i>data</i> ---> instance:65000
|
|
</pre>
|
|
This would mean that the ELB <i>would</i> need TCP listeners for the
|
|
<code>PassivePorts</code>, <i>and</i> that <code>MasqueradeAddress</code> would
|
|
need to point to the ELB DNS name. So why did I say that the ELB did not
|
|
need those extra TCP listeners?
|
|
|
|
<p>
|
|
<b>If</b> your ELB will only ever have <b>just one backend instance</b>, then
|
|
the above configuration would work. Your EC2 instance might be in a VPC,
|
|
with no public address, and thus perhaps the <i>only</i> way to make your
|
|
FTP server there reachable <i>is</i> using an ELB. Where forcing passive
|
|
data connections through an ELB starts to fail is when there are <i>multiple
|
|
backend instances</i>. Consider the case where your ELB might have 3 instances:
|
|
<pre>
|
|
+--> instance1:21
|
|
ELB:21 --|--> instance2:21
|
|
+--> instance3:21
|
|
</pre>
|
|
An FTP client connects to the ELB, and the ELB selects instance #2:
|
|
<pre>
|
|
client --- <i>ctrl</i> ---> ELB:21 --- <i>ctrl</i> ---> instance2:21
|
|
</pre>
|
|
So far, so good. The client requests a passive data transfer; the FTP server
|
|
tells the client to connect to the ELB address, port 65000, <b>but</b> the
|
|
ELB sends that connection to instance <i>#3</i>, <b>not</b> instance #2:
|
|
<pre>
|
|
client --- <i>data</i> ---> ELB:65000 --- <i>data</i> ---> instance3:65000
|
|
</pre>
|
|
This can happen because the ELB does not understand FTP; it does not know
|
|
that the data connection is related, in any way, to any other connections. To
|
|
the ELB, all TCP connections are independent, and thus any connection will be
|
|
routed, round-robin, to any backend instance. There is no guarantee that the
|
|
data connections, going through the ELB, will connect to the proper backend
|
|
instance. If there is only <b>one backend instance</b>, though, everything
|
|
will work as expected.
|
|
|
|
<p>
|
|
In order to properly support multiple backend instances (which is one of the
|
|
goals/benefits of using an ELB in the first place) for FTP, then, the trick
|
|
is to <b>not</b> force data connections through the ELB. Instead, the
|
|
<code>MasqueradeAddress</code> directive points to each backend instance's
|
|
respective public hostname. With this configuration, the FTP client connects
|
|
to the ELB for its control connection, like usual:
|
|
<pre>
|
|
client --- <i>ctrl</i> ---> ELB:21 --- <i>ctrl</i> ---> instance2:21
|
|
</pre>
|
|
And for the data transfer, ProFTPD tells the client the instance public
|
|
hostname, and port 65000:
|
|
<pre>
|
|
client -------------- <i>data</i> -------------> instance2:65000
|
|
</pre>
|
|
Notice how, with this configuration, the TCP connection for the data transfer
|
|
bypasses the ELB completely. <i>This</i> is why you do not need to configure
|
|
any TCP listeners on the ELB for those <code>PassivePorts</code>, and why
|
|
you do <b>not</b> want <code>MasqueradeAddress</code> using the ELB DNS name;
|
|
you do not want passive data connections going through the ELB.
|
|
|
|
<p>
|
|
Now you have an ELB with multiple backend FTP servers. Success, right? Maybe.
|
|
There <i>are</i> some caveats. FTP clients might notice that they connect to
|
|
one name (the ELB DNS name), <i>but</i> for data transfers, they are being told
|
|
(by the FTP server) to connect to a <i>different</i> name; some FTP clients
|
|
might warn/complain about this mismatch. ProFTPD would definitely complain
|
|
about this mismatch, for it would see the control connection as originating
|
|
from the ELB, but the data connection originating from a different address,
|
|
and would refuse the data transfer. To allow data transfers to work, then,
|
|
you would need to add the following to your <code>proftpd.conf</code>:
|
|
<pre>
|
|
# Allow "site-to-site" transfers, since that is what FTP traffic with
|
|
# an ELB looks like.
|
|
AllowForeignAddress on
|
|
</pre>
|
|
which has its own <a href="http://www.proftpd.org/docs/howto/FXP.html">security implications</a>.
|
|
|
|
<p>
|
|
Next, there is the ELB <a href="http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/config-idle-timeout.html">idle timeout</a> setting to
|
|
adjust. The default is 60 seconds. During a data transfer, most FTP clients
|
|
will be handling the data connection, and the control connection is idle.
|
|
Thus if the data transfer lasts longer than 60 seconds, the ELB might terminate
|
|
the idle control connection, and the FTP session is lost. Unfortunately the
|
|
maximum allowed idle timeout for ELBs is 1 hour (3600 seconds); for <i>large</i>
|
|
(or slow) data transfers, even that timeout could be a problem. There are
|
|
ways of keeping the control connection from being idle for too long, using
|
|
<a href="http://www.proftpd.org/docs/howto/KeepAlives.html">keepalives</a>.
|
|
<b>Note</b> that this idle timeout is not really an issue for SFTP/SCP
|
|
sessions, as all data transfers for them use the same single TCP connection.
|
|
|
|
<p>
|
|
Last, using an ELB only for FTP control connections, and using direct
|
|
connections for the FTP data transfers only works if your backend EC2 instances
|
|
<i>have</i> public hostnames; for instances in a VPC, that may not be true.
|
|
So how can we use an ELB for multiple backend instances that only have private
|
|
addresses? Sadly, the answer is: you can't. For load balancing FTP sessions
|
|
among multiple backend EC2 instances with private addresses, you need an
|
|
FTP-aware proxy, such as ProFTPD with the <a href="https://github.com/Castaglia/proftpd-mod_proxy"><code>mod_proxy</code></a> module. This means running your
|
|
own instance for doing that load balancing, rather than having AWS manage it.
|
|
Of course, if the clients using your ELB for FTP services are <i>also</i>
|
|
within your VPC, then the lack of public hostnames for your EC2 instances
|
|
is not an issue, and using an ELB as described above will work.
|
|
|
|
<p><a name="Route53">
|
|
<b>DNS and AWS Route53</b><br>
|
|
Using an ELB for balancing connections across your pool of FTP servers is
|
|
rather complex. Are there alternatives? Yes: "DNS load balancing".
|
|
|
|
<p>
|
|
Instead of using an AWS ELB for balancing/distributing connections across
|
|
your pool of ProFTPD-running instances, you can use DNS tricks to implement
|
|
the same functionality. Note, however, these DNS tricks still assume that
|
|
your EC2 instances are publicly reachable, <i>i.e.</i> have public hostnames.
|
|
|
|
<p>
|
|
With DNS load balancing, the client resolves a DNS name to an IP address,
|
|
and connects to that IP address:
|
|
<pre>
|
|
client1 ----------------- <i>ctrl</i> ----------------> instance2:21
|
|
client1 ----------------- <i>data</i> ----------------> instance2:65000
|
|
</pre>
|
|
But the DNS server might be configured with <i>several</i> IP addresses for
|
|
the same DNS name; the client then chooses <i>one</i> IP address from the given
|
|
list (usually the first address), and connects to that. Some DNS servers will
|
|
<i>shuffle</i> the list of returned addresses for a name, so that clients will
|
|
choose different addresses, and thus distribute/balance their connections
|
|
across all of the addresses:
|
|
<pre>
|
|
client1 ----------------- <i>ctrl</i> ----------------> instance2:21
|
|
client1 ----------------- <i>data</i> ----------------> instance2:65000
|
|
|
|
client2 ----------------- <i>ctrl</i> ----------------> instance1:21
|
|
client2 ----------------- <i>data</i> ----------------> instance1:65000
|
|
|
|
client3 ----------------- <i>ctrl</i> ----------------> instance3:21
|
|
client3 ----------------- <i>data</i> ----------------> instance3:65000
|
|
</pre>
|
|
|
|
<p>
|
|
Within AWS, the <a href="https://aws.amazon.com/route53/">Route53</a> service
|
|
can be used as the DNS service for your domain names. AWS Route53 calls this round robin of addresses a <a href="http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-weighted">weighted</a> routing
|
|
policy, as each address associated with a name can be given a "weight",
|
|
affecting the probability that that address will be returned, by Route53,
|
|
when the DNS name is resolved to an IP address. Other routing policies are
|
|
supported, <i>e.g.</i> <a href="http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-latency">latency-based</a> routing
|
|
(so that the instance with the fastest response time is chosen), and
|
|
<a href="http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-geo">geolocation-based</a> routing (the instance address
|
|
chosen is based on the location of the resolving client).
|
|
|
|
<p>
|
|
If you are using AWS Route53, then you will need to configure health checks,
|
|
just as you would for an ELB. Route53 supports TCP health checks, which
|
|
you would point at your FTP/FTPS port (21) or SFTP/SCP port (22) on your
|
|
instances.
|
|
|
|
<p>
|
|
Since any/all clients could connect to any/all of the EC2 instances associated
|
|
with your DNS name, all of the users would need to be able to login on any
|
|
instance, and have their files/data available. Thus using a shared filesystem
|
|
for the files (such as <a href="https://github.com/s3fs-fuse/s3fs-fuse">s3fs</a>, NFS, Samba, gluster, <i>etc</i>) and a centralized/shared authentication
|
|
mechanism (<i>e.g.</i> SQL database, LDAP directory, <i>etc</i>) would be
|
|
needed.
|
|
|
|
<p><a name="FutureWork">
|
|
<b>Future Work</b><br>
|
|
In order to automate much of the above manual steps, work is progressing on
|
|
a <a href="https://github.com/Castaglia/proftpd-mod_aws/"><code>mod_aws</code></a> module for ProFTPD, which will eventually:
|
|
<ul>
|
|
<li>automatically set <code>PassivePorts</code> for FTP/FTPS vhost, if needed
|
|
<li>automatically set <code>MasqueradeAddress</code> if needed
|
|
<li>automatically adjust Security Group rules for FTP/FTPS, SFTP/SCP
|
|
</ul>
|
|
in addition to other interactions with AWS services.
|
|
|
|
<p><a name="FAQ">
|
|
<b>Frequently Asked Questions</b><br>
|
|
<p><a name="PerUserLoadBalancing">
|
|
<font color=red>Question</font>: I need to send particular users only to
|
|
a particular instance/set of instances. How do I configure AWS to do this?<br>
|
|
<font color=blue>Answer</font>: Short answer: you cannot. But it <b>can</b>
|
|
be done!
|
|
|
|
<p>
|
|
The AWS services like ELBs and Route53 understand TCP connections, and the
|
|
HTTP protocol, but they do not understand FTP. And understanding of the
|
|
protocol is necessary, so that you know how/when to expect the user name, and
|
|
how to redirect/proxy the backend connection. This is why you cannot use
|
|
<i>AWS</i> to do per-user balancing. However, you <i>can</i> use the
|
|
<a href="https://github.com/Castaglia/proftpd-mod_proxy"><code>mod_proxy</code></a> module for ProFTPD, which <i>is</i> protocol-aware, and thus can balance
|
|
FTP/FTPS connections in multiple ways, including per-user.
|
|
|
|
<p><a name="XForwardedFor">
|
|
<font color=red>Question</font>: I am using ELBs for my pool of ProFTPD
|
|
servers. I would like my logs to show the IP address of the connecting
|
|
clients, but all I get is the IP address of the ELB. Is there a way to get
|
|
the original IP address, an equivalent to the <code>X-Forwarded-For</code>
|
|
HTTP header?<br>
|
|
<font color=blue>Answer</font>: Yes, there is an equivalent mechanism
|
|
that is supported by ELBs for TCP listeners: the <a href="http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt">PROXY protocol</a>.
|
|
|
|
<p>
|
|
To enable use of the <code>PROXY</code> protocol by your ELB, see <a href="http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html">here</a>. You will <b>also</b> need to tell ProFTPD to expect
|
|
the <code>PROXY</code> protocol, which means using the <a href="https://github.com/Castaglia/proftpd-mod_proxy_protocol"><code>mod_proxy_protocol</code></a>
|
|
module.
|
|
|
|
<p>
|
|
The <code>PROXY</code> protocol, and the <code>mod_proxy_protocol</code> module,
|
|
work equally well for FTP/FTPS and SFTP/SCP sessions.
|
|
|
|
<p><a name="PerInstanceFirewall">
|
|
<font color=red>Question</font>: Should I run a firewall on my instance as well?<br>
|
|
<font color=blue>Answer</font>: It is considered a good network security
|
|
practice to do so, as it provides security in depth. <b>However</b>, care
|
|
must be taken with those firewall rules; they need to allow the same ports/
|
|
addresses as your SGs. (Also note that local/instance firewall rules CANNOT
|
|
be applied to the connecting client's IP address when connecting through ELB.)
|
|
|
|
<!--
|
|
iptables examples from SO
|
|
|
|
IPv6
|
|
VPC instance support, Route53, ELB
|
|
|
|
most common: transfers fail/can't connect/can't list directory/can't upload/download
|
|
-->
|
|
|
|
<p>
|
|
<hr>
|
|
<font size=2><b><i>
|
|
© Copyright 2017 The ProFTPD Project<br>
|
|
All Rights Reserved<br>
|
|
</i></b></font>
|
|
<hr>
|
|
|
|
</body>
|
|
</html>
|