i've tried to create a script that will upload some file to a ftp server using lftp, but without any luck so far. If I used build in ftp command in debian I manage to succsessfully connected and put the file.
Here is the debug output from lftp command:
lftp xxx.xxx.xxx.xxxx -e "put -O /out/ some_file_name" -d
---- using user `user01' and password from ~/.netrc
---- Resolving host address...
---- 1 address found:xxx.xxx.xxx.xxxx
---- Connecting to xxx.xxx.xxx.xxxx (xxx.xxx.xxx.xxxx) port 21
<--- 220 (vsFTPd 2.0.7)
---> FEAT
<--- 211-Features:
<--- EPRT
<--- EPSV
<--- MDTM
<--- PASV
<--- REST STREAM
<--- SIZE
<--- TVFS
<--- UTF8
<--- 211 End
---> OPTS UTF8 ON
<--- 200 Always in UTF8 mode.
---> USER user01
<--- 331 Please specify the password.
---> PASS XXXX
<--- 230 Login successful.
---> PWD
<--- 257 "/"
---> TYPE I
<--- 200 Switching to Binary mode.
---> EPSV
<--- 550 Permission denied.
---- Switching passive mode off
---- Closing data socket
---- Closing control socket
As you can see I'm using stored user name and password from .netrc file. I have another script that connect to the same server but uploads files and rename them inside the remote ftp folder using lftp again. Can someone help and explain why I cannot put with lfpt but can do it using ftp.
after add set ftp:passive-mode true and set ftp:prefer-epsv false to /etc/lftp.conf the error is changed
<--- 230 Login successful.
---> PWD
<--- 257 "/"
---> TYPE I
<--- 200 Switching to Binary mode.
---> PASV
<--- 227 Entering Passive Mode (xxx.xxx.xxx.xxx,76,92)
---- Connecting data socket to (xxx.xxx.xxx.xxx) port 19548
---- Data connection established
---> ALLO 710
<--- 550 Permission denied.
---> STOR out/my_file_name
---> ABOR
put: Access failed: 550 Permission denied. (/out/my_file_name)
---- Closing aborted data socket
---- Closing control socket
Okay I've understand what ALLO means
The ALLO command may be sent to a server that requires the necessary space for an uploaded to be reserved before the transfer takes place
so after a quick search in ftp man page, I've found a command to shut it down. After adding set ftp:use-allo false and with epsv false everything is fine now. Thanks alot :)
lftp -e "set ftp:use-allo false; set ftp:passive-mode true; set ftp:prefer-epsv false; mirror -R {local dir} {remote dir}" -u {username},{password} {host}
Use this single command to sync your file from local to server without 550 permission error.
While 550 Permission denied. is a strange response to the EPSV command it means that the server or some middlebox in between does not understand the EPSV command (likely a middlebox since the response to FEAT shows EPSV as supported). If you use the builtin ftp command instead of lftp it will probably use the older PASV command (IPv4 only) instead of the newer EPSV command (IPv4+IPv6 capable).
According to the man page there is a setting ftp:prefer-epsv which should default to false. Maybe some configuration is setting this value to true so that lftp will use EPSV instead of PASV. Check your settings (set -a inside lftp) and if it is true (expected) set it to false and try again, in the hope that it will then use PASV instead of EPSV.
Related
I'm trying to log into an ftps site. I've tried giving the login creds at the command line (and putting set parameters in ~/.lftprc, then opening an lftp session and typing those parameters with lftp job control statements. Regardless, I keep hitting the same roadblock:
421 Sorry, cleartext sessions are not accepted on this server.
Please reconnect using SSL/TLS security mechanisms.
I got furthest with the following parameters, but keep getting the error above.
How do I get lftp to use SSL/TLS security mechanism from the command line?
The objective is to script the access to this ftps site using bash (programming without using expect).
lftp
lftp :~> set ssl-allow false
lftp :~> set passive-mode yes
lftp :~> open ftp.abc.com
lftp ftp.abc.com:~> login theuser
Password:
lftp theuser#ftp.abc.com:~> cd
`cd' at 0 [Delaying before reconnect: 26]
CTRL-C
lftp theuser#ftp.abc.com:~> debug
lftp theuser#ftp.abc.com:~> cd
---- Connecting to ftp.abc.com (XX.XXX.XX.XX) port 21
<--- 220-Welcome to the Yahoo! Web Hosting FTP server
<--- 220-Need help? Get all details at:
<--- 220-http://help.yahoo.com/help/us/webhosting/gftp/
<--- 220-
<--- 220-No anonymous logins accepted.
<--- 220-Yahoo!
<--- 220-Local time is now 15:30. Server port: 21.
<--- 220-This is a private system - No anonymous login
<--- 220 You will be disconnected after 5 minutes of inactivity.
---> FEAT
<--- 211-Extensions supported:
<--- EPRT
<--- IDLE
<--- MDTM
<--- SIZE
<--- MFMT
<--- REST STREAM
<--- MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
<--- MLSD
<--- XDBG
<--- AUTH TLS
<--- PBSZ
<--- PROT
<--- TVFS
<--- ESTA
<--- PASV
<--- EPSV
<--- SPSV
<--- ESTP
<--- 211 End.
---> OPTS MLST type;size;modify;UNIX.mode;UNIX.uid;UNIX.gid;
<--- 200 MLST OPTS type;size;sizd;modify;UNIX.mode;UNIX.uid;UNIX.gid;unique;
---> USER theuser
<--- 421 Sorry, cleartext sessions are not accepted on this server.
Please reconnect using SSL/TLS security mechanisms.
It seems like lftp is not configured correctly on many systems, which makes it unable to verify server certificates (producing Fatal error: Certificate verification: Not trusted).
The web (and answers in this post) is full of suggestions to fix this by disabling certificate verification or encryption altogether. This is unsecure as it allows man-in-the-middle attacks to pass unnoticed.
The better solution is to configure certificate verification correctly, which is easy, fortunately. To do so, add the following line to /etc/lftp.conf (or alternatively ~/.lftp/rc, or ~/.config/lftp/rc):
set ssl:ca-file "/etc/ssl/certs/ca-certificates.crt"
ca-certificates.crt is a file that contains all CA certificates of the system. The location used above is the one from Ubuntu and may vary on different systems. To generate or update the file, run update-ca-certificates:
sudo update-ca-certificates
If your system does not have this command, you can create one manually like this:
cat /etc/ssl/certs/*.pem | sudo tee /etc/ssl/certs/ca-certificates.crt > /dev/null
lftp :~> set ssl-allow false
You've explicitly set ssl-allow to false. But this must be true if lftp should attempt to use SSL.
You might also need to
set ssl:verify-certificate no
My answer provides access for a single user on your system rather than a system-wide certificate.
lftp uses Transport Layer Security (TLS). So it’s essential to first grab the certificate from the FTP server.
openssl s_client -connect <ftp-hostname>:21 -starttls ftp
I include the entire certificate chain in a new file called cert.crt in my local ~/.lftp folder. At the very least, you're looking to include all the text of the certificate itself: -----BEGIN CERTIFICATE----- <...> -----END CERTIFICATE-----.
I create a file called rc in the local ~/.lftp folder and add the lines
set ssl:ca-file “cert.crt”
set ssl:check-hostname no (this prevents Fatal error: Certificate verification: certificate common name doesn't match requested host name ‘<ftp-hostname>’ when running a command like ls remotely)
Setting ftp:ssl-allow true didn't work for me.
By typing set:
lftp :~> set
I noticed this:
set ftp:ssl-allow true
set ftp:ssl-allow/XXX.XXX.XXX.XXX no
with XXX.XXX.XXX.XXX being the server, I was logging into.
So the final set of commands I needed was:
lftp :~> set ftp:ssl-allow true
lftp :~> set ftp:ssl-allow/XXX.XXX.XXX.XXX true
lftp :~> set ssl:verify-certificate no
lftp version must be >= 4.6.3 (Debian user)
What worked for me step by step with lftp:
get certificate of host with openssl s_client -connect <ftp_hostname>:21 -starttls ftp, at the begining of result I got something like -----BEGIN CERTIFICATE-----
MIIEQzCCAyu.....XjMO
-----END CERTIFICATE-----
copy that -----BEGIN CERTIFICATE-----
MIIEQzCCAyu.....XjMO
-----END CERTIFICATE----- into /etc/ssl/certs/ca-certificates.crt
Into lftp configuration reference this certificate file adding to /etc/lftp.conf for systemwide set ssl:ca-file "/etc/ssl/certs/ca-certificates.crt"
and then do your sync or whatever with lftp, on my case it is lftp -u "${FTP_USER},${FTP_PWD}" ${FTP_HOST} -e "set net:timeout 10;mirror ${EXCLUDES} -R ${LOCAL_SOURCE_PATH} ${REMOTE_DEST_PATH} ; quit"
This worked for me for a FTPS server connection (with port 990, but not necessary to specify) using lftp
code:
lftp ftps://USER:PASSWORD#server.com -c "set ssl:verify-certificate false;"
then:
do stuff
more info at:
how-to-avoid-lftp-certificate-verification-error
I'm using lftp 4.8.4 on Ubuntu 20.4 with my own ftpd server code.
As the debug log below shows, in preparation for a transfer lftp sends ALLO but appears to ignore the negative response (452 "no space").
I've also tried a 552 "Exceeded storage allocation" response, which was also ignored.
Is there a more appropriate response? Am I misunderstanding the role of ALLO?
Any and all suggestions welcome! Thanks.
> put lfs.img -o lfs3
---- Connecting to ftpd (192.168.0.171) port 21
<--- 220 nil
---> FEAT
<--- 211-Extensions supported:
<--- SIZE
<--- REST STREAM
<--- PASV
<--- 211 END
---> USER anonymous
<--- 331 nil
---> PASS lftp#
<--- 230 nil
---> PWD
<--- 257 /
---> TYPE I
<--- 200 nil
---> PASV
<--- 227 Entering Passive Mode. 192,168,0,171,255,249
---- Connecting data socket to (192.168.0.171) port 65529
---- Data connection established
---> ALLO 72408
<--- 452 no space
---> STOR lfs3
<--- 500 open fail
---- Closing data socket
put: lfs.img: Fatal error: 500 open fail
lftp correctly handles a response of 552 ("Requested file action aborted. Exceeded storage allocation") to an ALLO command. lftp responds to the 552 response with a STOR command, immediately followed by an ABOR (ie. Abort) command.
From RFC 959 (para 4.1.3.): "This command [ALLO] shall be followed by a STORe or APPEnd command." So although the STOR command will not succeed, it would be incorrect to skip it and just send ABOR.
I made this script to download a folder in a remote FTP with implicit SSL:
open -d ftps://USER:"PASS"#ftp.xxx.tld:990
mirror --verbose --continue /remote/folder $HOME/destination/folder;
bye
It connects, the features are:
<--- 220-Microsoft FTP Service
<--- 220 FTP SOMECOMPANY
---> FEAT
<--- 211-Extended features supported:
<--- LANG EN*
<--- UTF8
<--- AUTH TLS;TLS-C;SSL;TLS-P;
<--- PBSZ
<--- PROT C;P;
<--- CCC
<--- HOST
<--- SIZE
<--- MDTM
<--- REST STREAM
<--- 211 END
But when the mirror command tries to do its thing, it gets:
<--- 257 "/" is current directory.
---> PBSZ 0
---- CWD path to be sent is `/remote/folder'
<--- 200 PBSZ command successful.
---> CWD remote
<--- 550 Access is denied.
mirror: Access failed: 550 Access is denied. (/remote/folder)
---> CWD folder
<--- 550 The system cannot find the file specified.
---> QUIT
When I manually connect with lftp I do have ls access for example but cannot change directory, same error, 550.
On FileZila it works perfectly, I do have access to the folder and can download files. I'm puzzled here. Already tried cryptic things such as using:
lftp -e "set ftp:use-allo false; set ftp:passive-mode true; set ftp:prefer-epsv false;...
to no avail. Any tips? Thanks!
You probably have to force TVFS here by using “set ftp:use-tvfs yes”. It enables Unix-like paths even if the server forgets to announce their support.
As the ftp server is hosted in a Windows envirionment, I had to use \ instead of / for defining paths.
The problem: I am trying to create a local mirror of a public FTP site. When I use lftp to do the job it creates a mirror without a problem, but when I try to update the mirror a few days later it becomes very slow due to getting stuck on several files.
Running lftp -d I can see that lftp makes several requests to RETR the file, but these requests result in several **** Timeout - reconnecting messages and after about 2-3 minutes I see
<--- 150 Opening BINARY mode data connection for {filename removed}.`
After this last command the file successfully downloads and lftp proceeds further.
From the manual I understand that BINARY is the default mode for lftp, but somehow it doesn't seem to work for the early requests. Can someone suggest how I can force lftp to always open BINARY mode data connection to download all files?
Here's a MWE:
``lftp -d -u anonymous,anonymous -c "open {url}; get {file}"``
And response from lftp -d:
---- Connecting to {url} ({IP}) port 21
<--- 220 (vsFTPd 3.0.3)
---> FEAT
<--- 211-Features:
<--- EPRT
<--- EPSV
<--- MDTM
<--- PASV
<--- REST STREAM
<--- SIZE
<--- TVFS
<--- 211 End
---> USER anonymous
<--- 331 Please specify the password.
---> PASS anonymous
<--- 230 Login successful.
---> TYPE I
<--- 200 Switching to Binary mode.
---> SIZE {file}
<--- 213 3321
---> MDTM {file}
--- 213 20160318190446
---> PASV
<--- 227 Entering Passive Mode ({IP}).
---- Connecting data socket to ({IP}) port 55380
---- Data connection established
---> RETR {file}
**** Timeout - reconnecting
---- Closing data socket
---- Closing control socket
lftp uses binary mode by default for all file transfers and ascii mode for directory listings. So the binary mode should not be a problem here.
Maybe you have a subtle connectivity problem, sometimes setting net:socket-maxseg to a lower value (e.g. 500) helps.
The ftp command for binary mode is bin so use that command before you get the file.
cd /direc/tory; bin; get file.xml
The problem is that I see
---> TYPE I
<--- 200 Switching to Binary mode.
in your output, so you're already in binary mode. I wonder if you have a different problem? I also see that you're using passive mode (PASV), and that's good because passive works around firewalls and NATs [1], so we need another reason why you see those timeouts.
Do you have any other clues, maybe from ping or netstat?
I am using LFTP to transfer files from a server, which unfortunately does not recognize the PORT command. I do not have control over the server (do not know in detail what server is) and I have to use the active mode.
This is the command line as:
lftp -e 'debug 10;set ftp:passive-mode off; set ftp:auto-passive-mode no; ls; bye;' -u user,password ftp://ftp.site.com
This is the debug output:
<--- 200 Using default language en_US
---> OPTS UTF8 ON
<--- 200 UTF8 set to on
---> OPTS MLST modify;perm;size;type;UNIX.group;UNIX.mode;UNIX.owner;
<--- 200 OPTS MLST modify;perm;size;type;UNIX.group;UNIX.mode;UNIX.owner;
---> USER xxxxx
<--- 331 Password required for xxxxx
---> PASS xxxxxx
<--- 230 User xxxxx logged in
---> PBSZ 0
<--- 200 PBSZ 0 successful
---> PROT P
<--- 200 Protection set to Private
---> PORT 172,16,133,11,146,168
<--- 500 Illegal PORT command
---> LIST
---> ABOR
---- Closing aborted data socket
---- Chiusura del socket di controllo
It seems that LFTP renounces to connect to data socket because the remote server does not support the PORT command. Is there a way to convince LFTP can still connect to port 20? By FTP manual obviously no problem.
The issue, I think, is not that the FTP server doesn't support the PORT command (it does), but rather, it doesn't like the IP address/port that your FTP client is sending in the PORT command.
PORT 172,16,133,11,146,168
...tells the server to connect to address 172.16.133.11, port 37544*. The interesting part here is the IP address: it's an RFC 1918 address (i.e. it's a private network address). That, in turn, suggests that your FTP client is in a LAN somewhere, and is connecting to an FTP server using a public IP address.
That remote FTP server cannot connect to a private network address; by definition, RFC 1918 address are not publicly routable.
Thus it very well could be that the FTP server is trying to make a connection to the address/port given in your PORT command, fails, thus that is why the FTP server fails the command, saying:
500 Illegal PORT command
To make a PORT command work with that FTP server, you would need to discover the public IP address that that server can connect to, to reach your client machine. Let's say that this address is 1.2.3.4. Then you would need to tell lftp to use that address in its PORT command, using the ftp:port-ipv4 option.
Chances are, though, that public IP address is the address of a NAT/router/firewall, and that that NAT/router/firewall will not allow connections, from the outside world to a high numbered port (e.g. 37544), to be routed to a machine within the LAN. This is one of the issues with active FTP data transfers, i.e. FTP data transfers which use the PORT (or EPRT) commands: they are not considered "firewall-friendly".
Hope this helps!
* - why 146,168 translates to port 37544?
According to FTP's RFC959 those parameters are:
(...) 16-bit TCP port address. This address information is broken into
8-bit fields and the value of each field is transmitted as a decimal
number (in character string representation).
146 dec = 10010010 bin = A
168 dec = 10101000 bin = B
A B
10010010 10101000 bin = 37544 dec