cancel
Showing results for 
Search instead for 
Did you mean: 

Why does FTPS loadbalancing need 3 VIPs?

davidfisher
Cirrus
Cirrus

Hey All,

 

I followed this guide to do FTPS SSL offloading - https://devcentral.f5.com/articles/ftps-offload-via-irules

 

The solution 1 did not work even after multiple tries but the solution 2 worked fine, however the article doesn't explain why it needs 3 VIPs in all.

 

I am quoting the working part here. And adding my config done in the comment below this post.

 

Solution 2: Offloading SSL for FTPS

This solution will handle both load balancing and offloading of SSL for FTPS. It will NOT support Active FTPS transfers -- only Passive FTPS transfers will work (This is because of the strange way active FTPS SSL negotiations work -- the server initiates a connection to the client but the client begins the SSL handshake). This solution could support the Clear Control Channel command but currently does not. This is really a pretty experimental solution and would need to be improved to make it more robust in a production environment. The second iRule has some code commented out to replace the IP the server sends for passive transfers, but it would be easier just to configure your server to hand out the VIP address.

 

x.x.x.x: external VIP address y.y.y.y: any internal IP address that is not in use

 

1) You must be running 9.4.x as we will be using the "virtual" command to send traffic to another Virtual Server.

 

2) A source address persistence profile is defined that matches across services and across virtuals. It is applied to inbound both virtual servers so that the passive transfer connections are sent to the same server that has the control connection from that client.

 

3) Define first virtual server (where the clients actually connect to) on VIP address x.x.x.x and port 21. This virtual server needs to have a CLIENTSSL profile associated with it with a valid SSL certificate for the server (the same way you'd do it if you were offloading SSL for HTTPS). This virtual server does not need a default pool. This virtual server also needs this iRule applied to it (with y.y.y.y replaced with the actual internal IP address):

 

when CLIENT_ACCEPTED { log local0. "client accepted" SSL::disable TCP::respond "220 My ftp server\r\n" TCP::collect } when CLIENT_DATA { log local0. "client data" TCP::respond "234 AUTH TLS Successful\r\n" TCP::payload replace 0 [TCP::payload length] "" virtual VS2FTP SSL::enable TCP::release log local0. "TCP Release Completed" }

3) Define a second standard virtual server on an internal address (where the first virtual server connects to) named "internal-y.y.y.y-999" with FTP servers (on port 21) as pool members. Apply the persistence profile. It needs the following iRule:

 

when CLIENT_ACCEPTED { TCP::collect } when CLIENT_DATA { if { [TCP::payload] contains "PBSZ" } { TCP::payload replace 0 [TCP::payload length] "" TCP::respond "200 PBSZ 0 successful\r\n" } elseif { [TCP::payload] contains "PROT P" } { TCP::respond "200 Protection set to Private\r\n" TCP::payload replace 0 [TCP::payload length] "" } elseif { [TCP::payload] contains "FEAT" } { TCP::payload replace 0 [TCP::payload length] "" TCP::respond "211-Features: MDTM REST STREAM SIZE AUTH TLS PBSZ PROT\r\n211 End\r\n" } TCP::release TCP::collect } when SERVER_CONNECTED { TCP::collect } when SERVER_DATA { if { [TCP::payload] contains "220 " } { TCP::payload replace 0 [TCP::payload length] "" } elseif { [TCP::payload] contains "Entering Passive Mode" } { You need to modify this section if your servers are not configured to hand out the VIP address for Passive transfers. regsub {10,10,71,1} [TCP::payload] "172,16,59,163" tmpstr TCP::payload replace 0 [TCP::payload length] $tmpstr } TCP::release TCP::collect }

4) The third virtual server catches inbound client passive transfer connections. It is defined on VIP address x.x.x.x and all ports. It must have the same CLIENTSSL profile as the first virtual server, the same pool as the first virtual server, and the same persistence profile as the first virtual server. It needs this iRule as well:

 

when CLIENT_ACCEPTED { SSL::disable TCP::collect 0 0 } when CLIENT_DATA { SSL::enable } when SERVER_CONNECTED { SSL::enable clientside }
2 REPLIES 2

davidfisher
Cirrus
Cirrus

My Working Config

 

POOLS USED:

 

root@(bigip1)(cfg-sync Disconnected)(Active)(/Common)(tmos) list ltm pool ftp-port21-only ltm pool ftp-port21-only { members { 10.1.20.100:ftp { address 10.1.20.100 session monitor-enabled state down } } monitor gateway_icmp }

VIRTUALS SERVERS

 

The initial VS 1 which is required in the config to offload the SSL and no pool

 

root@(bigip1)(cfg-sync Disconnected)(Active)(/Common)(tmos) list ltm virtual SSL-FTP ltm virtual SSL-FTP { destination 10.128.10.102:ftp ip-protocol tcp mask 255.255.255.255 profiles { ftp-ssl-profile { context clientside } ftp-tcp-profile { } } rules { ftp-ssl-irule } source 0.0.0.0/0 translate-address enabled translate-port enabled vs-index 15 }

The Second VS needed on a different unused IP

 

root@(bigip1)(cfg-sync Disconnected)(Active)(/Common)(tmos) list ltm virtual ftpvs2 ltm virtual ftpvs2 { destination 10.128.10.103:any ip-protocol tcp mask 255.255.255.255 pool ftp-port21-only profiles { tcp { } } rules { ftpvs2 } source 0.0.0.0/0 translate-address enabled translate-port disabled vs-index 17 }

The third VS with the pool again.

 

root@(bigip1)(cfg-sync Disconnected)(Active)(/Common)(tmos) list ltm virtual FTP-all-ports ltm virtual FTP-all-ports { destination 10.128.10.102:any ip-protocol tcp mask 255.255.255.255 pool ftp-port21-only profiles { ftp-ssl-profile { context clientside } tcp { } } rules { ftp-port-read ftpvs3 } source 0.0.0.0/0 translate-address enabled translate-port disabled } vs-index 16

Andy_McGrath
Cumulonimbus
Cumulonimbus

This solution is for Passive FTP only, your first VS is for the the incoming Command connection over SSL, this forwards on to the internal VS which looks to be dealing with the actual FTP Command connection without SSL.

 

As the iRule on the second VS reads the TCP Payload within the CLIENT_ACCEPTED event the traffic needs to in plaintext, decrypted, to allow it be do this. If you tried do do this in the initial VS with SSL the payload would be encrypted and you would not be able to read the contents to execute the iRule.

 

The final VS is for the Passive Data connection, which could be on any port as the connection is dynamic.

 

The connection flow looks a little like this

 

Initial Connection

 

Client || (SSL Connection 21) || virtual SSL-FTP || (none-SSL Connection 21) || virtual ftpvs2 || Backend FTP

Data Connection

 

Client || (SSL Connection Dynamic port) || virtual FTP-all-ports || Backend FTP

I think you could, with some complex iRules, do all this on a single Virtual Server however to keep the solution simple multiple Virtual Servers is often much better.