question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Client.prepareTransfer() only tries first (IPV6) strategy then fails on system ETIMEDOUT error

See original GitHub issue

Description I am trying to list files from a server with an IPV4 address. With the ‘list()’ operation, the code eventually enters Client.prepareTransfer() which in turn tries to connect with two strategies: IPV6 then IPV4. However I’m getting an ETIMEDOUT error when attempting the IPV6 connection (not suprising), but then the code re-throws this error rather than trying the next strategy (IPV4). You see this here:

ftp.log("Trying to find optimal transfer strategy...");
for (const strategy of strategies) {
	try {
		const res = await strategy(ftp);
		ftp.log("Optimal transfer strategy found.");
		this.prepareTransfer = strategy; // eslint-disable-line require-atomic-updates
		return res;
	}
	catch (err) {
		// Receiving an FTPError means that the last transfer strategy failed and we should
		// try the next one. Any other exception should stop the evaluation of strategies because
		// something else went wrong.
		if (!(err instanceof FtpContext_1.FTPError)) {
			throw err;
		}
	}
}

Could this catch be an empty block or explicitly test for ETIMEOUT?

Example code

// -- main ----------------------------

const main = async function()
{
	const client = new ftp.Client(CONFIG.get('ftp.timeout'));
	client.ftp.verbose = true;

	await client.access(
	{
		host: CONFIG.get('ftp.host'),
		user: CONFIG.get('ftp.user'),
		password: CONFIG.get('ftp.password'),
		secure: false
	});

	console.log(await client.cd('/VDOT Sites'));
	console.log(await client.list());

	if (!client.closed)
	{
		await client.close();
	}
};

main().catch((err) =>
{
	let msg = err.message;
	if (err.details !== undefined) msg += ' : ' + err.details;
	console.log(msg);
	process.exit(1);
});

Console output

Login security: No encryption
> USER ****
< 331 Password required for ****
> PASS ###
< 230 Logged on
> TYPE I
< 200 Type set to I
> STRU F
< 200 Using file structure 'File'
> OPTS UTF8 ON
< 202 UTF8 mode is always enabled. No need to send this command.
> OPTS MLST type;size;modify;unique;unix.mode;unix.owner;unix.group;unix.ownername;unix.groupname;
< 200 MLST OPTS type;size;modify;
> CWD /VDOT Sites
< 250 CWD successful. "/VDOT Sites" is current directory.
{
  code: 250,
  message: '250 CWD successful. "/VDOT Sites" is current directory.'
}
Trying to find optimal transfer strategy...
> EPSV
< 229 Entering Extended Passive Mode (|||10034|)
Can't open data connection in passive mode: connect ETIMEDOUT ***.170.37.65:10034

Which version of Node.js are you using? Node v12.16.1 with basic-ftp v4.5.3

Additional context If I only attempt the IPV4 strategy (enterPassiveModeIPv4) by modifying the Client constructor, everything then works.

Aside: Also can you swap the order of the strategies (i.e. IPV4 before IPV6) as that would be faster as I suspect many more connections are attempted on IPV4?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

8reactions
patrickjuchlicommented, Feb 26, 2020

Ah, I see the reason now. Very interesting!

Your data connection points to a different IP than the control connection. FTP uses two different socket connections, one for general commands and another one for transferring data (upload, download, directory listing). Usually these point to the same IP but the original FTP protocol also considered the use-case we see here: That the data connection is pointing to another machine. Is this the case here? Can you share more of your context?

This has been used very rarely though. Which is why the EPSV command, the more modern variant of PASV, which is used to establish such a data connection, doesn’t allow it anymore. That’s why only PASV works in your case.

You don’t have to overwrite the library for this. Use the following lines to force your client to use, well, PASV. Turns out the name of enterPassiveModeIPv4 is not so great considering what I’ve just explained. It should be enterPassiveModePASV.

const ftp = require("basic-ftp")

client.prepareTransfer = ftp.enterPassiveModeIPv4
0reactions
tiagotmrcommented, Feb 23, 2022

hello how do i change the

const ftp = require(“basic-ftp”)

client.prepareTransfer = ftp.enterPassiveModeIPv4

on: push: branches: - master

name: 🚀 Deploy website on push jobs: web-deploy: name: 🎉 Deploy runs-on: ubuntu-latest steps: - name: 🚚 Get latest code uses: actions/checkout@v2

- name: 📂 Sync files
  uses: SamKirkland/FTP-Deploy-Action@4.1.0
  with:
    server: ${{ secrets.ftp_host }}
    username: ${{ secrets.ftp_username }}
    password: ${{ secrets.ftp_password }}
    local-dir:  ./app/
    server-dir: public_html/teste/app/
Read more comments on GitHub >

github_iconTop Results From Across the Web

FileZilla etimedout error : Causes and Fixes - Bobcares
FileZilla etimedout error normally happens when user configures FTP client incorrectly or due to server firewall restrictions.
Read more >
ETIMEDOUT Error while installing Node packages on Windows
First, run npm config list and check whether you are behind a proxy. If so, try running
Read more >
https://scm.linefinity.com/common/linux-stable/com...
This results in failure to initialize the adapter with an error reported in the system log (something like "CTLX[1] error: state(Request failed)").
Read more >
Although I connected before, I can't connect now and I get the ...
I get “Connect ETIMEDOUT” error while connecting to database on server via mongodb compass and even though I made any changes.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found