liximomo / vscode-sftp

Super fast sftp/ftp extension for VS Code
MIT License
1.5k stars 264 forks source link

KeepAlive flooding FTP? #430

Open opus-2 opened 5 years ago

opus-2 commented 5 years ago

Do you read the FAQ?

Describe the bug I've noticed my pure-ftpd server daemon (not sftp) getting flooded with small packets after a transfer is made. It seems to be some kind of keep-alive, but I'm getting several hundred packets per second.

After any transfer is done, in the output window, I see the extension starts sending a NOOP command every 8 seconds or so (which is good):

[debug] > NOOP [debug] < '200 Zzz...\r\n' [debug] > NOOP [debug] < '200 Zzz...\r\n'

BUT, at the same time, there are hundreds of 1-byte packets being sent to port 21. I'm the only client connected to my server and when I close vscode or reload window, this strange packet flow stops.

Here is one sample packet obtained with tcpdump on linux (they all look the same, 1 byte length - I get hundreds of these per second):

01:23:33.504593 IP (tos 0x0, ttl 128, id 13563, offset 0, flags [DF], proto TCP (6), length 41)
    (MY IP ADDRESS).55875 > (SERVER IP ADDRESS).ftp: Flags [.], cksum 0xc301 (correct), 
    seq 0:1, ack 1, win 252, length 1: FTP, length: 1
        0x0000:  4500 0029 34fb 4000 8006 b1c5 0a00 000b  E..)4.@.........
        0x0010:  0a00 0004 da43 0015 6269 d582 e89e dce3  .....C..bi......
        0x0020:  5010 00fc c301 0000 0000 0000 0000       P.............

IMPORTANT: I have tried another FTP client (WinSCP on windows) and the problem doesn't happen with that program.

To Reproduce Steps to reproduce the behavior:

  1. setup an FTP connection (not sftp) on sftp.json
  2. upload any file
  3. debug output starts logging NOOP every 8 seconds
  4. check your network switch for blinking lights or watch the traffic on port 21 like I did. There's a continuous stream of 1 byte tcp packets on port 21.

Expected behavior One NOOP every 8 seconds. Between those, sweet network silence.

Desktop (please complete the following information):

Extension Logs from Startup - required


[debug] register command "Cancel All Transfer" from "./commandCancelAllTransfer.ts"
[debug] register command "Config" from "./commandConfig.ts"
[debug] register command "List Active Folder" from "./commandListActiveFolder.ts"
[debug] register command "Open Ssh Connection" from "./commandOpenSshConnection.ts"
[debug] register command "Set Profile" from "./commandSetProfile.ts"
[debug] register command "Toggle Output Panel" from "./commandToggleOutputPanel.ts"
[debug] register command "Upload Changed Files" from "./commandUploadChangedFiles.ts"
[debug] register command "Delete Remote" from "./fileCommandDeleteRemote.ts"
[debug] register command "Diff" from "./fileCommandDiff.ts"
[debug] register command "Diff Active File" from "./fileCommandDiffActiveFile.ts"
[debug] register command "Download" from "./fileCommandDownload.ts"
[debug] register command "Download Active File" from "./fileCommandDownloadActiveFile.ts"
[debug] register command "Download Active Folder" from "./fileCommandDownloadActiveFolder.ts"
[debug] register command "Download File" from "./fileCommandDownloadFile.ts"
[debug] register command "Download Folder" from "./fileCommandDownloadFolder.ts"
[debug] register command "Download Force" from "./fileCommandDownloadForce.ts"
[debug] register command "Download Project" from "./fileCommandDownloadProject.ts"
[debug] register command "Edit In Local" from "./fileCommandEditInLocal.ts"
[debug] register command "List" from "./fileCommandList.ts"
[debug] register command "List All" from "./fileCommandListAll.ts"
[debug] register command "Reveal In Explorer" from "./fileCommandRevealInExplorer.ts"
[debug] register command "Reveal In Remote Explorer" from "./fileCommandRevealInRemoteExplorer.ts"
[debug] register command "Sync Both Directions" from "./fileCommandSyncBothDirections.ts"
[debug] register command "Sync Local To Remote" from "./fileCommandSyncLocalToRemote.ts"
[debug] register command "Sync Remote To Local" from "./fileCommandSyncRemoteToLocal.ts"
[debug] register command "Upload" from "./fileCommandUpload.ts"
[debug] register command "Upload Active File" from "./fileCommandUploadActiveFile.ts"
[debug] register command "Upload Active Folder" from "./fileCommandUploadActiveFolder.ts"
[debug] register command "Upload File" from "./fileCommandUploadFile.ts"
[debug] register command "Upload Folder" from "./fileCommandUploadFolder.ts"
[debug] register command "Upload Force" from "./fileCommandUploadForce.ts"
[debug] register command "Upload Project" from "./fileCommandUploadProject.ts"
[info] config at s:\(project directory) {"remotePath":"./","uploadOnSave":true,"downloadOnOpen":false,"ignore":[".git/",".hg/","**/.DS_Store"],"concurrency":4,"connectTimeout":10000,"interactiveAuth":false,"secure":false,"passive":true,"remoteTimeOffsetInHours":0,"port":22,"profiles":{"server2":{"host":"(ip address)","port":21,"protocol":"ftp","remotePath":"/web","username":"dev","password":"(removed)"},"server1":{"host":"(ip adress)","port":22,"protocol":"sftp","remotePath":"(removed)","username":"(removed)","password":"(removed)","agent":null,"privateKeyPath":null,"passphrase":null}},"defaultProfile":"server2","syncMode":"update","watcher":{"files":"**","autoUpload":true,"autoDelete":true}}
[info] Using profile: server2
[info] [file-save] s:\(path)\Factory.php
[info] Using profile: server2
[trace] handle upload file for s:\(path)\Factory.php
[info] Using profile: server2
[debug] < '220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\r\n220-You are user number 1 of 50 allowed.\r\n220-Local time is now 01:50. Server port: 21.\r\n220-This is a private system - No anonymous login\r\n220-IPv6 connections are also welcome on this server.\r\n220 You will be disconnected after 30 minutes of inactivity.\r\n'
[debug] > USER dev
[debug] < '331 User dev OK. Password required\r\n'
[debug] > PASS ******
[info] [watcher-update] s:\(path)\Factory.php
[info] Using profile: server2
[trace] handle upload for s:\(path)\Factory.php
[info] Using profile: server2
[debug] < '230 OK. Current restricted directory is /\r\n'
[debug] > FEAT
[debug] < '211-Extensions supported:\r\n EPRT\r\n IDLE\r\n MDTM\r\n SIZE\r\n MFMT\r\n REST STREAM\r\n MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;\r\n MLSD\r\n AUTH TLS\r\n PBSZ\r\n PROT\r\n UTF8\r\n ESTA\r\n PASV\r\n EPSV\r\n SPSV\r\n ESTP\r\n211 End.\r\n'
[debug] > TYPE I
[debug] < '200 TYPE is now 8-bit binary\r\n'
[debug] > PASV
[debug] < '227 Entering Passive Mode ((address),210,233)\r\n'
[debug] > PASV
[debug] < '227 Entering Passive Mode ((address),59,107)\r\n'
[debug] > LIST /(remotepath)
[debug] < '150 Accepted data connection\r\n'
[debug] < '226-Options: -a -l \r\n226 6 matches total\r\n'
[debug] > PASV
[debug] < '227 Entering Passive Mode ((address),157,208)\r\n'
[debug] > LIST /(remotepath)
[debug] < '150 Accepted data connection\r\n'
[debug] < '226-Options: -a -l \r\n226 6 matches total\r\n'
[debug] > PASV
[debug] < '227 Entering Passive Mode ((address),246,139)\r\n'
[debug] > STOR /(path)/Factory.php
[debug] < '150 Accepted data connection\r\n'
[debug] < '226-File successfully transferred\r\n226 0.002 seconds (measured here), 4.51 Mbytes per second\r\n'
[debug] > PASV
[debug] < '227 Entering Passive Mode ((address),213,102)\r\n'
[debug] > STOR /(path)/Factory.php
[debug] < '150 Accepted data connection\r\n'
[debug] < '226-File successfully transferred\r\n226 0.003 seconds (measured here), 4.36 Mbytes per second\r\n'
[debug] > MFMT 20181216035044 /(path)/Factory.php
[debug] < '213 UTIME OK\r\n'
[debug] > MFMT 20181216035044 /(path)/Factory.php
[info] local -> remote s:\(path)\Factory.php
[debug] < '213 UTIME OK\r\n'
[info] local -> remote s:\(path)\Factory.php
[debug] > NOOP
[debug] < '200 Zzz...\r\n'
[debug] > NOOP
[debug] < '200 Zzz...\r\n'

problem starts here.

opus-2 commented 5 years ago

UPDATE: Doing further investigation, I have tried:

The results were exactly the same: the extension enters this "keep alive" mode by sending NOOP instructions every few seconds, but at the same time, sends hundreds of one-byte packets per second to the server, on port 21. So it's not the server, or the server software or the config file. That leaves me to think it's a bug in the extension.

Full log:

[debug] register command "Cancel All Transfer" from "./commandCancelAllTransfer.ts"
[debug] register command "Config" from "./commandConfig.ts"
[debug] register command "List Active Folder" from "./commandListActiveFolder.ts"
[debug] register command "Open Ssh Connection" from "./commandOpenSshConnection.ts"
[debug] register command "Set Profile" from "./commandSetProfile.ts"
[debug] register command "Toggle Output Panel" from "./commandToggleOutputPanel.ts"
[debug] register command "Upload Changed Files" from "./commandUploadChangedFiles.ts"
[debug] register command "Delete Remote" from "./fileCommandDeleteRemote.ts"
[debug] register command "Diff" from "./fileCommandDiff.ts"
[debug] register command "Diff Active File" from "./fileCommandDiffActiveFile.ts"
[debug] register command "Download" from "./fileCommandDownload.ts"
[debug] register command "Download Active File" from "./fileCommandDownloadActiveFile.ts"
[debug] register command "Download Active Folder" from "./fileCommandDownloadActiveFolder.ts"
[debug] register command "Download File" from "./fileCommandDownloadFile.ts"
[debug] register command "Download Folder" from "./fileCommandDownloadFolder.ts"
[debug] register command "Download Force" from "./fileCommandDownloadForce.ts"
[debug] register command "Download Project" from "./fileCommandDownloadProject.ts"
[debug] register command "Edit In Local" from "./fileCommandEditInLocal.ts"
[debug] register command "List" from "./fileCommandList.ts"
[debug] register command "List All" from "./fileCommandListAll.ts"
[debug] register command "Reveal In Explorer" from "./fileCommandRevealInExplorer.ts"
[debug] register command "Reveal In Remote Explorer" from "./fileCommandRevealInRemoteExplorer.ts"
[debug] register command "Sync Both Directions" from "./fileCommandSyncBothDirections.ts"
[debug] register command "Sync Local To Remote" from "./fileCommandSyncLocalToRemote.ts"
[debug] register command "Sync Remote To Local" from "./fileCommandSyncRemoteToLocal.ts"
[debug] register command "Upload" from "./fileCommandUpload.ts"
[debug] register command "Upload Active File" from "./fileCommandUploadActiveFile.ts"
[debug] register command "Upload Active Folder" from "./fileCommandUploadActiveFolder.ts"
[debug] register command "Upload File" from "./fileCommandUploadFile.ts"
[debug] register command "Upload Folder" from "./fileCommandUploadFolder.ts"
[debug] register command "Upload Force" from "./fileCommandUploadForce.ts"
[debug] register command "Upload Project" from "./fileCommandUploadProject.ts"
[info] config at s:\(project path) {"remotePath":"(path)","uploadOnSave":false,"downloadOnOpen":false,"ignore":[],"concurrency":1,"protocol":"ftp","connectTimeout":10000,"interactiveAuth":false,"secure":false,"passive":false,"remoteTimeOffsetInHours":0,"port":21,"host":"10.0.0.3","username":"******","password":"******"}
[trace] run command 'Upload File'
[trace] handle upload file for s:\(path)\local.ini
[debug] < '220 ProFTPD 1.3.4a Server (dio) [10.0.0.3]\r\n'
[debug] > USER fabio
[debug] < '331 Password required for fabio\r\n'
[debug] > PASS ******
[debug] < '230 User fabio logged in\r\n'
[debug] > FEAT
[debug] < '211-Features:\r\n MDTM\r\n MFMT\r\n TVFS\r\n MFF modify;UNIX.group;UNIX.mode;\r\n MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.mode*;UNIX.owner*;\r\n REST STREAM\r\n SIZE\r\n211 End\r\n'
[debug] > TYPE I
[debug] < '200 Type set to I\r\n'
[debug] > PASV
[debug] < '227 Entering Passive Mode (10,0,0,3,156,187).\r\n'
[debug] > LIST /(path)
[debug] < '150 Opening BINARY mode data connection for file list\r\n'
[debug] < '226 Transfer complete\r\n'
[debug] > PASV
[debug] < '227 Entering Passive Mode (10,0,0,3,156,204).\r\n'
[debug] > STOR /(path)/local.ini
[debug] < '150 Opening BINARY mode data connection for /(path)/local.ini\r\n'
[debug] < '226 Transfer complete\r\n'
[debug] > MFMT 20181216224449 /(path)/local.ini
[debug] < '213 Modify=20181216224449; /(path)/local.ini\r\n'
[info] local -> remote s:\(path)\local.ini
[debug] > NOOP
[debug] > NOOP
[debug] > NOOP
[debug] > NOOP
[debug] > NOOP
opus-2 commented 5 years ago

UPDATE 2 - (FIXED?) The problem seems to be in the mscdex / node-ftp dependency, file connection.js, line 109 (github link):

socket.setKeepAlive(true);

If I set socket.setKeepAlive(false); instead of true (effectively disabling its keep-alive feature), not only the packet flood stops completely, but also sftp's NOOP instruction keeps being sent correctly and working properly!

That module also seems to be abandoned for about 3 years and someone else reported a similar bug about it, with the variable noopreq being redefined at line 151 (var noopreq=... ), causing similar trouble.

I'm not sure it's the definitive solution, but it worked for me. Would you please give it a try and maybe patch it?

liximomo commented 5 years ago

@opus-2 I will do it once I have enough time.

agiannis commented 4 years ago

It happens many times (every 5 or 6 uploads), making the plugin difficult to use. Is there any workaround for this?

sametpalitci commented 4 years ago

@agiannis @opus-2 did you solve it?

opus-2 commented 4 years ago

I ended up not needing the extension anymore, but my fix was as mentioned earlier:

The problem seems to be in the mscdex / node-ftp dependency, file connection.js, line 109 (github link):

socket.setKeepAlive(true);

If I set socket.setKeepAlive(false); instead of true (effectively disabling its keep-alive feature), not only the packet flood stops completely, but also sftp's NOOP instruction keeps being sent correctly and working properly!

Steps: 1) In vscode, press F1 and select "Extensions: Open Extensions Folder". 2) Navigate to: liximomo.sftp-1.12.9/dist/extension.js 3) Look for o.setKeepAlive(!0) and remove the exclamation mark, like this: o.setKeepAlive(0). There is only one occurence of this string at this extension's current version (1.12.9). 4) Save and close the file, restart vscode.

It should work. If you upgrade the extension, you'll have to do this again, while the bug is not fixed.

MikeWillis commented 1 year ago

@opus-2 I know this is an old thread, I just found out my office IP address was banned from connecting to a few of the sites I manage due to an overflow of SSH connection requests - I think the bug you found here is the culprit.

I was about to dig around in the liximomo SFTP extension settings, but VSCode informed me that this extension is deprecated and replaced by Natizyskunk's fork

However the fork has the same dependency (and same version number), so I imagine the problem persists - I'll use the fix you found

opus-2 commented 1 year ago

Hey Mike, I don't think you have the same problem I had, because it only happened to me on FTP, not SFTP or anything related to SSH. Normal, old-fashioned FTP won't do any SSH requests (as you mentioned an "overflow of SSH connection requests"). I do wish you luck, though.

Edit: could it be simply because the extension is opening a new connection everytime you save a file? Also, check with your ISP if you're behind a NAT. That would mean dozens of users sharing the same output IP address, so it could be someone else's fault. If one of them tries a brute-force password scan, the IP gets banned and you go down with them. Another possibility is the remote host is banning a whole block of IPs because of one or two abusers. Try connecting with a VPN, tor-network or even your cell phone's data connection (not wifi) to see if the problem goes away.

MikeWillis commented 1 year ago

Thanks for the info! Yea I was just using SFTP (SSH), not regular FTP - but maybe SFTP has the same (or similar) issue with this extension?

We have a dedicated IP address, and the site host let me know that they were getting flooded with 400+ SSH connection login failures across the several domains I connect to that are hosted with them. The attempts would come in bursts of 10+. I tend to have multiple VSCode windows open, each connected to one of these domains.

I'll have to do some checking to see if it's still happening.. They whitelisted our office IP, but the problem could still be there. Ugh!

JohnEPierce commented 1 year ago

This same problem recently arose for me using Natizyskunk's extension for regular ftp. The fix by opus-2 still seems to be successful.