domingo, 16 de agosto de 2015

FTP active mode in AWS

FTP is one of the oldest Internet protocols. Unfortunately, it was designed for environments where clients and servers interact with each other with a minimum of restriction. Therefore, FTP protocol doesn't work well in scenarios including NAT and/or Firewalls.

As you may know, AWS instances from OS perspective live in a network with private IPs. When an instance (EC2 classic or VPC) needs to communicate with another VPC, region or outside AWS network, some special devices handle the NAT translation between the private and the public IP. This AWS mechanism provides you maximum flexibility, allowing you to move a public IP from one instance to another easily, for example.

FTP protocol was designed without this concepts in mind. So, in complex network including NAT and/or Firewalls, the protocol doesn't work well. An example is FTP active mode. Imagine next scenario:
  • One instance (FTP client) in Frankfurt region
    • Private IP: 172.31.16.100
    • Public IP: 52.28.244.154
  • Another instance (FTP server) in Tokyo region
    • Private IP: 172.31.14.185
    • Public IP: 52.69.174.237
  • Security groups allow any traffic between both instances
 If we try to communicate using a standard FTP client such as ncftp with active mode, you will experience next issue:
  1. FTP client will be able to connect
  2. FTP client will be able to authenticate
  3. FTP client will fail when trying to list files



The issue is well covered in next public documentation from ncftp team. Please, take a look on previous information (specially the 'Why PORT Poses Problems for Routing Devices' section).

Inside the instance, FTP client can only see private IPs. So, when the client try to connect with the remote FTP server, it will send private IP information. If we perform a packet capture in FTP server side during previous test, we will see how the FTP protocol information inside the packet includes 'PORT' request using the private IP of the FTP client instead of the public IP (check the packet highlighted in blue):


Because of this, FTP data connection from server will fail (basically: FTP server won't be able to find a route back to source instance).

To work around this, I recommend you:
  1. Use FTP passive mode instead of active. The passive mode works better under NAT/Firewalls. Most of the FTP services include parameters to specify the public IP address to handle this kind of scenarios.
  2. Use another method to send files. FTP is an old protocol and has many limitations about functionality and security. Probably, move to a modern transfer protocol (like SSH) could be a good alternative.
  3. Use a FTP client with options to specify public IP. FileZilla ftp client has a specific parameter to specify the public IP when using active mode.
  4. Patch FTP to specify Public IP instead of Private IP. With this method, both instances will be able to establish and complete the communication. 
If for whatever reason you need to use FTP active mode in AWS and the 3rd option is not possible, I suggest you to patch the FTP client to workaround the issue. For example, you can obtain the public IP of an instance from metadata information. 

I created a patch for the latest stable version of ncftp client to replace the private IP in 'PORT' request with the public IP (if available through metadata) when the FTP Server (destination) is not a private IP. The result: the FTP server is able to establish the FTP data connection and complete the request, even in active mode. Example output of the same test with the customized FTP client:



Please, note in the previous tcpdump output the highlighted packet in blue how the 'PORT' directive includes the public IP of the instance instead of the private IP.

If you want to use this customized ftp client, you can download the patched source-code version from the next link.

Also, if you want to patch from the vanilla version, download the latest stable version (v3.2.5) of ncftp from here and patch next files:

 The customized ncftp client requires development curl libraries (libcurl-devel package, in Amazon Linux) in order to compile correctly.

Finally, here you can see patch details:

configure

libncftp/ftp.c

11 comentarios:

Unknown dijo...

I tried to compile your patched version and, during the make command, I got this:

Linking ncftp: [ERROR]
gcc -D_REENTRANT -lcurl -Wno-format-y2k -DLINUX=43000 -DLINUX_GLIBC=39000 -Dn
cftp -DO_S="linux-x86_64-glibc2.19" -DBINDIR="/usr/local/bin" -DSYSCONFDIR="/
usr/local/etc" -DHAVE_CONFIG_H -DLINUX=43000 -DLINUX_GLIBC=39000 -I/tmp/ncftp
-3.2.5-aws -I../libncftp -I../Strn -I../sio -I/tmp/ncftp-3.2.5-aws -I/tmp/ncf
tp-3.2.5-aws/libncftp -I/tmp/ncftp-3.2.5-aws/sio -I/tmp/ncftp-3.2.5-aws/Strn
cmds.o cmdlist.o ls.o main.o version.o shell.o util.o readln.o progress.o boo
kmark.o pref.o preffw.o trace.o spool.o spoolutil.o log.o gl_getline.o -o ../
bin/ncftp -L../libncftp -L../Strn -L../sio -L/tmp/ncftp-3.2.5-aws/libncftp -L
/tmp/ncftp-3.2.5-aws/sio -L/tmp/ncftp-3.2.5-aws/Strn -lncftp -lStrn -lsio
../libncftp/libncftp.a(ftp.o): In function `FTPSendPort':
ftp.c:(.text+0x15e7): undefined reference to `curl_global_init'
ftp.c:(.text+0x15ec): undefined reference to `curl_easy_init'
ftp.c:(.text+0x161e): undefined reference to `curl_easy_setopt'
ftp.c:(.text+0x1649): undefined reference to `curl_easy_setopt'
ftp.c:(.text+0x1674): undefined reference to `curl_easy_setopt'
ftp.c:(.text+0x16a1): undefined reference to `curl_easy_setopt'
ftp.c:(.text+0x16cc): undefined reference to `curl_easy_setopt'
ftp.c:(.text+0x16db): undefined reference to `curl_easy_perform'
ftp.c:(.text+0x194e): undefined reference to `curl_easy_cleanup'
ftp.c:(.text+0x1962): undefined reference to `curl_global_cleanup'
collect2: error: ld returned 1 exit status
make[1]: *** [../bin/ncftp] Error 1

I've read this can be solved by putting the -lcurl at the end but I did not get that to work.

TIA,
Dan

Unknown dijo...

To add to the above...

I tried the 2nd option (patch the vanilla version) and get the same results.

I installed the curl lib with

sudo apt-get install libcurl4-gnutls-dev

I am on ubuntu VERSION="14.04.3 LTS, Trusty Tahr"
uname: Linux 3.13.0-44-generic #73-Ubuntu SMP Tue Dec 16 00:22:43 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

any ideas?

Thanks,
Dan

Unknown dijo...

I was able to get the make to work. I had to edit all the Makefiles by removing the -lcurl option from the CFLAGS statement:

changed:

CFLAGS=-D_REENTRANT -lcurl -Wno-format-y2k

to:

CFLAGS=-D_REENTRANT -Wno-format-y2k

and then changed the SOCKS_LIBS statement from:

SOCKS_LIBS=

to:

SOCKS_LIBS=-lcurl

This moved the -lcurl option to where it needed to be in the gcc command line.

ALSO, there was no mention of the fact that the curl library had to be installed beforehand. Be sure you've done this first:

sudo apt-get install libcurl4-gnutls-dev

or you will get this error when you run configure:

checking whether the C compiler (gcc -lcurl ) works... no
configure: error: installation or configuration problem: C compiler cannot create executables.

HTH,
Dan

Javier Sianes dijo...

Hi Dan,
I created the patch and test under Amazon Linux. I didn't test under Ubuntu. Thank you for sharing with us!

sindhu dijo...

Really, these quotes are the holistic approach towards mindfulness. In fact, all of your posts are. Proudly saying I’m getting fruitfulness out of it what you write and share. Thank you so much to both of you.

SMO Services Chennai

Suseela dijo...



What an awesome post, I just read it from start to end. Learned something new after a long time.


SAP SD training in Chennai

Shalini dijo...

Very nice post here thanks for it .I always like and such a super contents of these
post.Excellent and very cool idea and great content of different kinds of the valuable
information's. seo company in chennai

Unknown dijo...

I cant wait to check out some of these blogs! I’ve really wanted to start learning more about cars and auto repairs lately and I think this will help a lot. I think it can save my family some money if we knew how to do some repairs at home.! Thanks again for all the options.

home spa services in mumbai

Unknown dijo...

Great post I am actually getting ready to across this information,your post are very good to read and it is useful, good work you are doing well.
Hadoop Training in Chennai

Kaashvi mohan dijo...

Usually I do not read post on blogs, but I would like to say that this write-up very forced me to try and do it! Your writing style has been surprised me. Great work admin..Keep update more blog..
Online 3d printing
3D printing in Coimbatore
3D printing service in Coimbatore
3D printing in Chennai

Unknown dijo...

I'm wondering if there is a aws configuration that allow to rute this connection or some configuration that do this, any thought