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
- FTP client will be able to connect
- FTP client will be able to authenticate
- 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:
- 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.
- 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.
- 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.
- Patch FTP to specify Public IP instead of Private IP. With this method, both instances will be able to establish and complete the communication.
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:
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
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
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
Hi Dan,
I created the patch and test under Amazon Linux. I didn't test under Ubuntu. Thank you for sharing with us!
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
What an awesome post, I just read it from start to end. Learned something new after a long time.
SAP SD training in Chennai
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
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
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
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
I'm wondering if there is a aws configuration that allow to rute this connection or some configuration that do this, any thought
Publicar un comentario