FTP with Explicit SSL (FTPES)

Contributed by: Jeremy

Description

The F5 is capable of load balancing FTP, but by default will not properly balance FTP with Explicit SSL while offloading SSL on the control channel.
This iRule does not inject SSL or TLS into the stream, but looks for requests and responses from the Client and Server to determine when SSL or TLS should be enabled. I have successfully implemented this, but I cannot make any guarantees to its functionality.
The advantage of this method is the F5 can still translate the Active/Passive information appropriately using the FTP profile and allow the data connection between client and server to be secure and direct. If the data connection is proxied, it can affect transfer speed.

Requirements

In most cases, the Client SSL profile on the F5 would need to have the same Cert and Key as the FTP servers to be trusted by the client for the data connection. Also, some FTP servers may need to be configured to allow a new SSL Session for the data connection.
The FTP Virtual server would need the FTP profile and both ClientSSL and ServerSSL profiles.

WARNING

If the server is not configured to force re-use of the TLS session originally negotiated with the Client (the F5 in this case), this does introduce a security risk in that for a passive transfer, anyone could connect to upload or download a file if the passive port could somehow be determined and the attacker could MitM the traffic. It may be possible to mitigate this risk using SSL Proxy though I have not tested.

iRule Source

when CLIENT_ACCEPTED {
    SSL::disable
    set CLIENT 1
}
when CLIENT_DATA {
    set CLIENT 0
    # determine if we need to enable TCP Collect server side
    if {[string match {AUTH TLS*} [TCP::payload]]} {
        serverside {TCP::collect}
    } elseif {[string match {AUTH SSL*} [TCP::payload]]} {
        serverside {TCP::collect}
    }
    TCP::release
}
when SERVER_DATA {
    # TCP collect was enabled server side
    # determine if the server can do FTPES
    if {[string match {234*} [TCP::payload]]} {
        # Server can do FTPES, enable response notify for enabling SSL
        TCP::notify response
    }
    TCP::release
}
when SERVER_CONNECTED {
    SSL::disable
    if {$CLIENT} { clientside {TCP::collect} }
}
when CLIENTSSL_HANDSHAKE {
    # if there is a successful handshake client side, enable SSL server side
    serverside {SSL::enable}
}
when USER_RESPONSE {
    # triggered when TCP::notify response is enabled
    SSL::enable
}

The BIG-IP API Reference documentation contains community-contributed content. F5 does not monitor or control community code contributions. We make no guarantees or warranties regarding the available code, and it may contain errors, defects, bugs, inaccuracies, or security vulnerabilities. Your access to and use of any code available in the BIG-IP API reference guides is solely at your own risk.