Forum Discussion
karmacoma_49245
Nimbostratus
Jul 10, 2008iRule disconnects the client when switch from one server to another
Hi guys
We are newbies when writing iRules and I'm afraid we need some help. Our iRule is supposed to assign a different LDAP server depending on a subscriber id.
Let's say we have two OpenLDAP DBs and we have to route the traffic to one or the other. If we receive a search for DB1 the iRule routes it properly and the transaction is finished.
If then we receive a new message for DB2 the iRule sends it to the DB2. Note we have set the OpenLDAP so there is no need for a bind to be sent before a search for example is sent.
The problem we are having is that when a new search for DB2 is coming into the F5 while the F5 has still not closed the previous LDAP dialogue towards the DB1, we get a TCP reset towards both sides of the F5 leading into disconnection of the client and affecting performance.
We think we may need to buffer the messages until the previous dialogue is finished so that no message is lost and no reset is sent however we don't know hot to do so, any ideas???
Another possible solution could be to reject the incoming messages while a previous message is processed but we have try with no success.
Here is our iRule
rule ldapProxy {
when RULE_INIT {
Define default ldap server and port
set ::ldapPool Internal_Pool
set ::ldapPort 389
Turn on debugging
set ::debug 1
Define a lookup table for debugging
array set ::msg_types {
0 "bind request"
1 "bind response"
2 "unbind request"
3 "search request"
4 "search response"
6 "modify request"
7 "modify response"
8 "add request"
9 "add response"
10 "delete request"
11 "delete response"
12 "modifydn request"
13 "modifydn response"
14 "compare request"
15 "compare response"
16 "abandon request"
23 "extended request"
24 "extended response"
}
}
when CLIENT_ACCEPTED {
TCP::collect
}
when CLIENT_DATA {
Grab the current payload collected
set payload [TCP::payload]
set SUBSID [findstr $payload "MSISDN=" 7 6 ]
if {$SUBSID>=491700 and $SUBSID < 491706 } {
set NODE "172.80.121.30"
} elseif {$SUBSID>= 491723 and $SUBSID < 491724 } {
set NODE "172.80.121.31"
} else {
}
Pull the first 2 bytes.
binary scan $payload H2c ber_t ber_len
The first byte is the tag signifying an LDAP message,
Always is hex 30, if that is not so reject
if { $ber_t ne "30" } {
reject
return
}
The second byte is one of two values:
a) The length of the packet minus the above
defining byte and the length byte
OR
b) an octet describing how many subsequent bytes
hold the packet length
In either case the message type (what we are after)
follows the message id field which too can be a variable
number of bytes.
set len_bytes 0
if { [expr [expr ($ber_len + 0x100) % 0x100] & 128] > 0 } {
set len_bytes [expr [expr ($ber_len + 0x100) % 0x100] & 127]
}
How many bytes is the message id
binary scan $payload x[expr 3 + $len_bytes]c msgid_bytes
The message type is then 4 bytes + number length bytes + number of
message id bytes offset.
binary scan $payload x[expr 4 + $len_bytes + $msgid_bytes]c msgtype
msgtype - BER encoded value, bits 1-5 are the actual
type, 6 is the data type, 7-8 are the data class
Here we only care about the lower 5 bits
set msgtype [expr $msgtype & 31]
if {$::debug and
[catch {
log local0. "message type is: $::msg_types($msgtype) $msgtype"
}
]
} {
log local0. "Bad message type: $msgtype"
reject
}
Each connection should start with a bind request
if { $msgtype == 0 } {
if {$::debug} {log local0. "Bind Request with: $::ldapPool"}
pool $::ldapPool
} elseif {[string compare [LB::server addr] $NODE] -- 0}{
if {$::debug} {log local0. "Sending to node : $NODE"}
LB::detach
node $NODE $::ldapPort
}
TCP::release
TCP::collect
}
}
thanks a lot in advance!
- karmacoma_49245
Nimbostratus
Hi nmenant - Nicolas_Menant
Employee
Hi, - karmacoma_49245
Nimbostratus
Hi nmenant - Nicolas_Menant
Employee
Hi, - karmacoma_49245
Nimbostratus
Hi nmenant! - karmacoma_49245
Nimbostratus
Hi nmenant!Ldap ClientVIPF5Server1Server2 ============================= LDap Search -----------------> TCP(SYN) -----------> TCP(ACK) <--------------- TCP(FIN/ACK) ---------------------------> TCP(SYN/ACK) <----------- TCP(ACK) ------------> Ldap Search ------------> TCP(FIN(ACK) <--------------------------- TCP(ACK) -----------------------------> TCP(ACK) <---------------------------- ::::::::::::::::::::::::::: ::::::::::::::::::::::::::::
Ldap ClientVIPF5Server1Server2 ============================= LDap Search -----------------> TCP(SYN) -----------------------------> TCP(ACK) <--------------- TCP(FIN/ACK) ---------> LDap Search -----------------> ****** TCP(ACK) <--------------- TCP(RST/ACK) <--------------- TCP(SYN/ACK) <--------------------------- TCP(RST) --------------------------> TCP(FIN/ACK) <------------ TCP(ACK) ------------->
- karmacoma_49245
Nimbostratus
hey guys
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects