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
would suffice. This would prevent the FTP users from logging in, yet give them enough time to establish a port forwarded ssh connection. With this sort of quasi-shell (although, strictly speaking, there are better, more restrictive shells than this example, as it could be escaped from), one can ssh over any command:
ssh -l test -f -L3000:ftpserver:21 ftpserver true && ftp localhost 3000
You'll also need to use the AllowForeignAddress configuration directive to your configuration file:
AllowForeignAddress on
or proftpd will reject the passive transfer connections and log:
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 is presently developing a patch for scenarios like this; if interested, please contact him directly via email.