pyftpdlib supports tls connections but lacks SNI support.
SNI is TLS extension which allows client to indicate server name to which it wants to connect. Then server can provide ssl certificate for that hostname. Such feature enables support for ftp virtual hosting over TLS, even on single IP.
The implementation should allow dynamic loading of certificates to allow millions of certificates to be used (which is not something unexpected with letsencrypt being available).
So for example on connection, when SNI hostname is known, specific method is called which has to return certificate, key, etc. And that method gets implemented by pyftpdlib user to for example do open('/etc/something/%s.pem' % sanitized_hostname).read() or load cert from sql database etc.
If client doesn't provide SNI extension the hostname could be set to None and our method could load some default certificate.
So get_servername() checks hostname and calls some used implemented load_certs(servername) which needs to return tuple with (certfile, keyfile[optional]).
Uhmm... this looks like a desirable nice feature... but it also requires time which I don't have right now. If you're brave enough feel free to submit a PR (or at least a draft).
pyftpdlib supports tls connections but lacks SNI support.
SNI is TLS extension which allows client to indicate server name to which it wants to connect. Then server can provide ssl certificate for that hostname. Such feature enables support for ftp virtual hosting over TLS, even on single IP.
Relevant RFC: https://tools.ietf.org/html/rfc6066
pyopenssl supports SNI using get_servername(): https://pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Connection.get_servername
ftp servers with SNI support: proftpd 1.3.6+ - http://www.proftpd.org/docs/contrib/mod_tls.html
Few ftp clients that support SNI: lftp - https://lftp.yar.ru/ filezilla - https://filezilla-project.org/
The implementation should allow dynamic loading of certificates to allow millions of certificates to be used (which is not something unexpected with letsencrypt being available).
So for example on connection, when SNI hostname is known, specific method is called which has to return certificate, key, etc. And that method gets implemented by pyftpdlib user to for example do open('/etc/something/%s.pem' % sanitized_hostname).read() or load cert from sql database etc. If client doesn't provide SNI extension the hostname could be set to None and our method could load some default certificate.
So get_servername() checks hostname and calls some used implemented load_certs(servername) which needs to return tuple with (certfile, keyfile[optional]).