I have a machine A. From it, I can SSH to machine B. Machine B can FTP to machine C. I want to download files from C, onto A. I do not have access from A to C directly.

                 Port 20 and 21
┌───┐     ┌───┐  FTP Control    ┌─────────────────┐
│   │ SSH │   ├────────────────►│                 │
│ A ├────►│ B │                 │ C - with files  │
│   │     │   ├────────────────►│     I want      │
└───┘     └───┘  FTP data       │                 │
                 Random ports   └─────────────────┘

I know there's a million questions on this site about SFTP. As far as I can tell, this is not the same as SFTP. With SFTP it seems the SSH server must be the same server that has the files to be downloaded, which is not the problem here. Is this correct? Or is there any way to do this with a simple SFTP command and some additional arguments?

Are there any easy ways to do this? The files are large, and the disk and memory on B is tiny, so if possible I'd like to stream the data straight through. (Compared to doing a two-step FTP download onto the disk of B.)

In general SSH can tunnel anything. But apparently FTP uses more than just port 20 and 21. It uses a whole bunch of random and unpredictable ports, new ones for each file operation. The possible range of such FTP ports is so large that with one client I tried, I wasn't able to just port-forward the whole range with SSH. (Note that I'm trying passive FTP, where all network connections are initiated from client the server. As opposed to active FTP where C would initiate a connection back to B, which isn't possible because of a NAT between them.)

I've tried to write a script in python hacking together the FTP standard library and a 3rd-party SSH tunnel library. It's a pretty convoluted and janky solution, that results in me openning up a new port for every new file, but never closing it. Also a recent upgrade to one library broke some dependencies so now the script doesn't work with the latest version of these libraries. I'm tempted to re-write the solution with the underlying Paramiko library. But I fear that's a deep rabbit-hole. This stuff is really fiddly. (Let me know if you need to see my attempt. I'm trying to omit it to avoid the X/Y problem.)

Is there a simpler way to do this tunneling?

I would prefer a solution with Python, but at this point I'm desperate enough to use any tool.

  • How about you install a reverse-ftp-proxy server on machine B? Machine B proxies machine C's ftp-server. Machine A uses ftp over SSH at machine B. This should easily work, you definitive don't have to "hack together" anything.
    – paladin
    May 10, 2022 at 6:54

2 Answers 2


The "conventional" solution for that is to use an FTP client that has SOCKS 5 support and rather than forwarding specific ports over ssh, configure dynamic port forwarding (the ssh client will act as SOCKS 5 server)

Then on host A:

ssh -D localhost:10108 user@host-B 

And configure your FTP client to use a SOCKS5 proxy on that port, for example in WinSCP https://winscp.net/eng/docs/ui_login_proxy or edit the ncftp configuration file $HOME/.ncftp/firewall or use

curl --socks5-hostname localhost:10108 ftp://host-c/path/to/file
  • When I look online to learn about SOCKS proxies, some sites (1, 2) say that the traffic from A to B is unencrypted. Can you confirm that if I'm doing SOCKS over SSH, then the traffic from A to B is encrypted (and of course from B to C is it unencrypted). May 11, 2022 at 1:05
  • All traffic in the tunnel will be encrypted.
    – Rob
    May 11, 2022 at 4:49
  • 1
    The traffic between your ftp client and the socks proxy is not encrypted, which is the main security concern with using a remote socks server (running somewhere on the internet or in a corporate network) But with ssh dynamic port forwarding the socks server is running on the same host, not somewhere in your corporate network or the internet.
    – Rob
    May 11, 2022 at 4:58

You can use SSH as a SOCKS proxy. The SSH client on A will work as a SOCKS5 server, tunneling all connection requests to B. You'll need a SOCKSified FTP client on A.

How you activate the SOCKS proxy functionality depends on the SSH client in use on A. Look for "dynamic port forwarding" in the documentation. For the standard OpenSSH client, specify the option -D 1080 to have it listen on the standard SOCKS5 port. For PuTTY, go to Connection - SSH - Tunnels in the configuration dialog and add a forwarded port with destination "Dynamic".

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .