FTP集成开发总结-之SSL
博客分类: NetWork
应用服务器
基于FTP/SSL的开发,推荐使用Indy组件。ICS 也开始全面支持SSL(v5 v6 v7),也免费开源,
也是候选方案,以前我用ics v5的ssl的相关支持还要收费呢。 Indy的优势在于开发组人马众多、
版本更新快,对于不同FTP server 返回的LIST格式的支持比较全面。
Indy10开始全面支持SSL,对于FTP/SSL的应用,以客户端为例:只需要新加一个
TIdSSLIOHandlerSocketBase 组件,再将TIdFTP组件的 IOHandler指向它,
设置IdFTP组件的 UseTLS、 DataPortProtection 即可。
UseTLS 属性决定了客户端连接服务器的模式:
utNoTLSSupport- 根本不使用TLS
utUseImplicitTLS- 隐式TLS(implicitTLS) 。通常这种模式下,客户端连接到990端口,建立TLS会话,
整个会话都是加密的。但是IETF 已经废弃了对ImplicitTLS的支持,所以一般情况下这种设置只是用来
连接那些还不支持explicitTLS的ftp服务器。
utUseRequireTLS- 强制显式TLS。这种模式下,客户端像普通ftp会话一样,以非加密方式连接到
21端口,ftp服务器给你一个hello信息,然后你发出一个特殊TLS命令(AUTH TLS, AUTH SSL,
AUTH TLS-P 或 AUTH TLS-C)开始建立TLS会话,其后再进行ftp USER PASS 认证过程,整个会话
保持加密状态持续到结束或你发出一个重初始化命令(REIN)。 如果TLS会话建立不成功,后面的
ftp会话就自动断开了,无法继续。
utUseExplicitTLS-显式TLS(explicitTLS)。这种模式类似上面的 utUseRequireTLS,只是如果TLS会话
建立不成功,仍然可以继续传统的非加密FTP会话。 这种模式可以保证最大的兼容性。
所谓隐式TLS/显式TLS,区别主要在是否独立开监听端口上。
隐式TLS的实现,都是要求服务器单独listen一个特殊端口,客户端连接后直接建立SSL会话,然后
再进行应用协议的command,整个过程都是加密的;而显式TLS的实现,是在原应用协议的基础上
改进,增加了TLS认证的command,并且server不占用单独的端口。
以FTP/SSL为例:
隐式TLS-服务器在990端口监听,客户端建立TCP连接,然后建立SSL连接,然后进行
USER PASS的ftp 认证。 其间是没有 AUTH TLS这种特殊command的。
显式TLS-服务器仍然在21端口监听,客户端正常发起tcp连接、服务器返回hello、客户端发
起AUTH TLS-至此建立了TLS认证,以后才是加密状态。如果服务器设置了必须使用TLS,
则当server hello后,客户端试图不建立SSL连接而直接进行USER PASS的ftp认证,服务器会
踢掉客户端。
简而言之:
隐式TLS-干脆利落,服务器listen一个单独端口,上来就直接SSL加密,然后才建立应用层会话。
显式TLS-保持最大的兼容性,还是混在原来的端口,只是应用层会话一旦建立,就用特殊的命令
来建立SSL会话。
另:
1. 按Indy的官方说法, Indy8、9 无法支持ftp on SSL的应用,因为老版本缺乏支持ftp on ssl 某些
关键特性:比如提供了PORT PASV的加密&不加密数据传输通道及开始explicit TLS会话的命令。
(原话是这样的:In Indy 8.0 and Indy 9.0, you can not do this. The File Transfer Protocol requires
some extensions that those Indy versions do not support them. The extensions provide encrypted
or clear PORT and PASV data channels plus provide a command for starting negotiation with explicit TLS. )
2. SSL加密的ftp连接,最好只使用 PASV模式。 因为客户端的NAT无法识别加密后的客户端发出的
PORT 命令中的ip地址,它就无法翻译成NAT内的地址
SSL 需要两个动态库:libeay32.dll,ssleay32.dll
参考代码:
procedure TForm1.btn1Click(Sender: TObject);
var
SSL: TIdSSLIOHandlerSocketOpenSSL;
FTP: TIdFTP;
i: Integer;
begin
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
FTP := TIdFTP.Create(nil);
FTP.IOHandler := SSL;
FTP.UseTLS := utUseRequireTLS;
FTP.Passive := False;
FTP.Host := '192.168.9.203';
FTP.Username := 'FTPUsername';
FTP.Password := 'FTPPassword';
i := 1;
try
while i < 5 do // 在 XE2 版则无需循环尝试连接 D2007 则需要
begin
try
FTP.Connect;
if FTP.Connected then Break;
except
end;
i := i + 1;
end;
FTP.ChangeDir('/Image');
FTP.List;
mmo1.Lines.Text := FTP.ListResult.Text;
finally
FTP.Free;
SSL.Free;
end;
end;
转载于:https://my.oschina.net/u/582827/blog/1625358