Setting Up a Reverse FTP Proxy Server

Problem: You have a server (let's call it the firewall) with a public IP. Users will connect to this public IP using FTP clients. However your actual FTP server is not located on the firewall, but located somewhere else -- behind a DMZ, or through a VPN, or just another "less visible" public IP on the internet. You need the Firewall to act as a reverse-proxy and relay the protocol from your firewall to your actual ftp server.

Doing this at the network level (e.g. with iptables) with the FTP protocol is messy as it supports connections being opened in both directions (esp when in non-passive mode), especially if your actual ftp server has its own connection to the internet (not through the firewall). Instead I found an "old-school" application level proxy software from back in 2002. You can read about it here: http://www.linuxjournal.com/magazine/configuring-and-using-ftp-proxy.

Note that your "actual" ftp server need not actually be on an internal network; it can be somewhere reachable via VPN or even elsewhere on the internet itself. Essentially, it can be used any time you want to have an FTP server "appear" at one place but actually reside somewhere else.


Configuration

These steps were performed on the CentOS-6 "firewall" box:

ServerType standalone
User nobody
Group nobody
LogDestination daemon
# LogLevel INF
# DBG is useful for
# troubleshooting
PidFile /var/run/ftp-proxy.pid
# ServerRoot /var/ftp-proxy/rundir
AllowMagicUser no
AllowTransProxy yes
DestinationAddress 192.168.141.60
ValidCommands USER, PASS, PWD, CWD, CDUP, \
PORT, PASV, RETR, TYPE, REST, \
ABOR, LIST, NLST, STAT, QUIT
  • Change "DestinationAddress" to the address of your actual FTP server
  • Append the following to /etc/rc.d/rc.local:
    • /usr/local/bin/ftp-proxy -d
  • Start the ftp-proxy manually the first time by running the command above.
  • Now test ftp to your firewall server.
  • You also get a detailed log of every thing that passes through the proxy in your /var/log/messages, etc:
Apr 7 23:22:24 vps1 ftp-child[4472]: USER-INF connect from 113.210.130.114
Apr 7 23:22:35 vps1 ftp-child[4472]: USER-INF 'USER aws1' from 113.210.130.114
Apr 7 23:22:35 vps1 ftp-child[4472]: USER-INF reading data for 'aws1' from cfg-file
Apr 7 23:22:38 vps1 ftp-child[4472]: USER-INF 'PASS XXXX' from 113.210.130.114
Apr 7 23:22:38 vps1 ftp-child[4472]: USER-INF 'PASS XXXX' from 113.210.130.114
Apr 7 23:22:38 vps1 ftp-child[4472]: USER-WRN 'SYST' from 113.210.130.114 not allowed
Apr 7 23:22:47 vps1 ftp-child[4472]: USER-INF 'PORT 113.210.130.114:7551' from 113.210.130.114
Apr 7 23:22:47 vps1 ftp-child[4472]: USER-INF 'LIST' from 113.210.130.114
Apr 7 23:22:47 vps1 ftp-child[4472]: TECH-INF 'PORT 192.168.141.1:40335' for 113.210.130.114
Apr 7 23:22:47 vps1 ftp-child[4472]: TECH-INF 'LIST' sent for 113.210.130.114
Apr 7 23:22:48 vps1 ftp-child[4472]: USER-INF Transfer for 113.210.130.114 completed: LIST '' read 144938/1 byte/sec
Apr 7 23:22:52 vps1 ftp-child[4472]: USER-INF 'CWD incoming' from 113.210.130.114
Apr 7 23:22:54 vps1 ftp-child[4472]: USER-INF 'PORT 113.210.130.114:4948' from 113.210.130.114
Apr 7 23:22:54 vps1 ftp-child[4472]: USER-INF 'LIST' from 113.210.130.114
Apr 7 23:22:54 vps1 ftp-child[4472]: TECH-INF 'PORT 192.168.141.1:57099' for 113.210.130.114
Apr 7 23:22:54 vps1 ftp-child[4472]: TECH-INF 'LIST' sent for 113.210.130.114
Apr 7 23:22:54 vps1 ftp-child[4472]: USER-INF Transfer for 113.210.130.114 completed: LIST '' read 0/1 byte/sec

shahada AT abubakar.net