[Dovecot] F5 SLB iRule - POP3 TLS Offload & Add Realm
Hey Guys,
I figured someone might have use of this at some point. I've created an iRule for our F5 Load Balancer which performs the following tasks:
- Appends STLS to the POP3 Capability list (it does this blindly, so expects the backend POP3 server to not return this)
- Watches for the STLS command and initiates SSL negotiation with the client (leaves the connection to the backend POP3 server unencrypted)
- Watches for the USER command (login attempt) and appends a realm if the user hasn't supplied one
- Stops watching once a successful login occurs
It's designed to be attached to port 110 and port 995 at the same time, and will disable SSL if the user is connecting to port 110 until the STLS command is issued.
This is a first pass, so there's probably room for improvement, but it does seem to work. This will require LTM v10 (at least), as the SSL::collect command didn't exist prior to that version.
Here's the rule:
when CLIENT_ACCEPTED { if { [TCP::local_port clientside] == "110" } { # Disable SSL if we're on port 110 (as we're doing TLS Offload) set secure 0 SSL::disable } else { set secure 1 } set realm "mydomain.com" set debug 0 set loggedin 0 }
when SERVER_CONNECTED { TCP::collect }
when CLIENTSSL_HANDSHAKE { SSL::collect set secure 1 }
when CLIENTSSL_DATA { if { $debug } { log local0. "CLIENT DATA: [SSL::payload]" }
set lcpayload [string tolower [SSL::payload]]
if { $lcpayload starts_with "user" } { scan [SSL::payload] {%s%s} command user set pos [string first $user [SSL::payload] 0] SSL::payload replace $pos [string length $user] "$user@$realm" if { $debug } { log local0. [SSL::payload] } }
SSL::release if { $loggedin == 0 } { SSL::collect } }
when CLIENT_DATA { if { $debug } { log local0. "CLIENT DATA: [TCP::payload]" } set lcpayload [string tolower [TCP::payload]] if { $lcpayload starts_with "stls" } { TCP::respond "+OK Begin TLS negotiation\r\n" TCP::payload replace 0 [TCP::payload length] "" TCP::release SSL::enable return } elseif { $lcpayload starts_with "user" } { scan [TCP::payload] {%s%s} command user set pos [string first $user [TCP::payload] 0] TCP::payload replace $pos [string length $user] "$user@$realm" if { $debug } { log local0. [TCP::payload] } } TCP::release if { $loggedin == 0 } { TCP::collect } }
when SERVER_DATA { if { $debug } { log local0. "SERVER DATA: [TCP::payload]" }
set lcpayload [string tolower [TCP::payload]] if { $lcpayload starts_with "+ok logged in" } { TCP::release set loggedin 1 event disable if { $debug } { log local0. "POP3 Login Successful" } return } elseif { $lcpayload contains "capa" } { TCP::payload replace [expr [TCP::payload length] - 3] 0 "STLS\r\n"
}
if { $secure == 1 && $loggedin == 0 } { clientside { SSL::collect } } elseif { $secure == 0 && $loggedin == 0 } { clientside { TCP::collect } } TCP::release if { $loggedin == 0 } { TCP::collect } }
participants (1)
-
Lee Standen