LFTP FTPS and Certificate Verification

Plain old FTP offers no encryption of any kind, even the username and password are sent plain text. As a result an extension to FTP named FTPS (not to be confused with the totally unrelated SFTP), provides encryption for the username and password and optionally the data channel.

It does this by using Transport Layer Security or TLS the same used to secure websites. As with websites you setup public and private keys and use certificates to verify trust with the host you are connecting.

Now my server host offers off-site backup using FTP or FTPS, unfortunate they don't use an properly trusted certificate, they use a self-signed certificate.

Self signed certificates are not bad, they still provide encryption but they do not offer any trust, ie verification of who you are talking to.

As a result when connecting to an FTP server using TLS with a self-signed certificate you will receive a message that the connection is not trusted. In lftp you get the message:

Fatal error: Certificate verification: Not trusted

and then the connection is closed.

To bypass this message you can create a file named rc in ~/.lftp and add the line:

set ssl:verify-certificate no

this has the effect of disabling certificate verification. HOWEVER, this now means that no checking is performed so you have no idea who you are connecting to, you could be connecting to a hostile intermediary out to steal passwords!

There has to be a better way

Well a much safer option is to add the self signed public key into our local certificate store. This way we can verify that we are connecting to the expected server and not a hostile third party. To do this we first must download the public key from the server, for this we use openssl, run the following command

openssl s_client -showcerts -connect example.com:21 -starttls ftp

replace example.com with the host name of your ftp server and change the port number if different.

This will return a bunch of information, the bit we are interested in is under Certificate chain section. Copy the certificate which is the text which starts -----BEGIN CERTIFICATE----- and ends -----END CERTIFICATE----- and paste into a new file under  ~/.lftp eg. mycert.crt so you now have a file that reads:

-----BEGIN CERTIFICATE-----

<lots of characters...>

-----END CERTIFICATE-----

Now create or edit a file named rc in the ~/.lftp file and add the line

set ssl:ca-file "mycert.crt"

You should now be able to connect with no Certificate validation error.

If you now get a message which reads: Certificate verification: certificate common name doesn't match requested host name this is because the Common Name or hostname specified in the certificate does not match the hostname you have connected to. To bypass this check you need to add the following additional line to the rc file:

set ssl:check-hostname no

In Summary

While this is not a perfect solution it is far more desirable than blindly connecting to a random server. Because if we are suddenly presented with a different certificate it is a sign that someone maybe tampering with your connection. Then again it maybe a legitimate certificate update, remember the certificate will expire eventually and will need to be updated.