How to prevent TCP connection timeout when FTP'ing large file?

I am not able to FTP (retrieve) a large file from the Internet to my Linux VM. It times out after a while.

The actual error is "Could not read reply from control connection -- timed out." This error occurs after a few minutes, after a good chunk of the file has already been transferred.

The setup is:

FTP Client:  ncftpget running in Linux on VMWare Player 3.0
FTP Server:  somebody else's machine out on the Internet, configuration unknown
Guest OS:    Ubuntu 8.10 Linux 32-bit, with vmxnet and vmware tools installed.
Host OS:     Vista 64-bit
Network:     Linux VM connects to the Internet via Bridged NIC (also tried NAT)
FTP Mode:    PASV
I did find some forum postings mentioning a 2-minute timeout somewhere. But exactly where and how to fix it was not clear. Some troubleshooting steps already tried:
  • I have switched from VMWare Player 3.0 to VirtualBox 3.0.x, but no luck.
  • I also changed from NAT to Bridged virtual NICs, but no luck

UPDATE Netstat on the Linux VM and the equivalent admin page on the DIR-655 router both show the connection is alive and well (tcp 'ESTABLISHED' status). Vista doesn't see the connection at all, which I guess is normal if connection state is managed only within the VM.

Here's the output from netsh interface tcp show global on Vista, in case it's useful:

C:\Users\alex>netsh interface tcp show global
Querying active state...

TCP Global Parameters
----------------------------------------------
Receive-Side Scaling State          : enabled
Chimney Offload State               : disabled
Receive Window Auto-Tuning Level    : highlyrestricted
Add-On Congestion Control Provider  : none
ECN Capability                      : disabled
RFC 1323 Timestamps                 : disabled
** The above autotuninglevel setting is the result of Windows Scaling heuristics
overriding any local/policy configuration.

Solution 1:

For troubleshooting purposes, try downloading the same file via wget or curl. I suspect that PEra is correct, NOOP commands will prevent this, and possibly wget or curl would send them.

Solution 2:

If you are going through NAT, chances are the NAT timers are disconnecting you. I see this from hotel rooms where I ssh into a machine and fail to do something for some time (as short as 5 minutes sometimes!)

# echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time
# echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
# echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes

Try those. This will cause a keepalive to be sent on all TCP streams once every minute regardless of activity on the socket.

Note that the ftp client may not actually USE keepalives. It is something that the application must request. If that fails, perhaps installing another FTP client would work better. The NetBSD FTP client (lukemftp) may be available, and is the best command-line FTP client I've seen to date.

It's also possible the remote end is closing the connection due to inactivity. If it is, it has a rather broken idea of reality. If these TCP keepalive hacks above don't fix it, either the client will have to send some command periodically (NOOP, etc) or the administrators of the FTP server will have to change their end.