Premise The File Transfer Protocol is an old protocol, and like many of the older protocols it was developed in a time when security was not of such a paramount concern. One aspect of FTP that reflects this is the transmission of passwords, used to prove to the server that the client is who they say they are, "in the clear", unencrypted, visible to any packet sniffer. Protocols like SSH, and its scp program, are replacing FTP as a means to securely transfer files among hosts.
scp
However, many people still prefer to use their standard FTP clients. What would be easiest would be a way to allow such clients to function while transparently providing the encryption necessary for today's networks. Can this be done? Yes - after a fashion. This document aims to describe how to tunnel FTP over an SSH channel, providing for secure transmission of the user's password.
Client Configuration The trick to encrypting the password is to make use of ssh's local port forwarding capability. It works by creating a sort of proxy on the local host that listens to some high-numbered port. Any traffic sent to that port is encrypted, and forwarded to the configured remote address and port. (Note: the prior instructions' flaw was that the local port forwarding request was sent to localhost, rather than to the remote server, which effectively set up the encrypted channel between localhost and itself). Here's how to set up a local port forward:
$ ssh -Llocal-port:remote-addr:remote-port user@host
$ ssh -f -L3000:ftpserver:21 ftpserver 'exec sleep 10' && ftp localhost 3000
3000
Remember that only the control connection is encrypted, not the data connection: any data you transfer (e.g. directory listings, files uploaded or downloaded) are still sent "in the clear". Your password (and the other FTP commands sent by the client) is not.
Server Configuration The server side of the connection needs some configuration to make the ssh tunneling work as well. First, the client need a valid account on the remote host is necessary in order to support the ssh tunnel. A valid shell is not strictly necessary for these ssh tunnels, though; something like:
#!/bin/sh sleep 10
$ ssh -l test -f -L3000:ftpserver:21 ftpserver true && ftp localhost 3000
AllowForeignAddress
AllowForeignAddress on
proftpd
SECURITY VIOLATION: Passive connection from {host} rejected
Note that the use of the server host's DNS name, or its IP address, in the setting up of the ssh tunnel assumes that the routing of traffic to the host's own IP address will be short-circuited in the kernel and thus not actually be transmitted on the wire. On modern kernels this is a fair assumption, but may not always be the case. For the truly paranoid, use of localhost or 127.0.0.1 as the remote-addr parameter in the ssh tunnel command would cause traffic on host to be sent over its loopback address, and not over the network. However, this will prevent data transfers from working altogether. The author has a patch for scenarios like this; if interested, please contact him directly via email.
localhost
127.0.0.1