[Dovecot] F5 SLB iRule - POP3 TLS Offload & Add Realm
Lee Standen
lee at standen.id.au
Wed Apr 11 06:54:35 EEST 2012
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
}
}
More information about the dovecot
mailing list