Forum Discussion

kpiti_52215's avatar
kpiti_52215
Icon for Nimbostratus rankNimbostratus
Jan 11, 2013

What does "no peer connection established TCP::collect" mean

I have an irule doing some checks on SMTP and I get a lot of:

 

CLIENT_DATA> - no peer connection established TCP::collect needs an established peer connection! (line 124) invoked from within "TCP::collect "invalid peer expression (line 1) invoked from within "serverside { TCP::collect }"

 

 

errors in the log. The irule seems to be working, the traffic is pretty busy and these errors make up to quite a lot of events in the log. As I understand is that this could mean the client session either disconnected half way the session or that LTM is somehow loosing the sessions. I'd like to know if this is a client problem I don't care about or a LTM problem.

 

Couldnt find any useful docs on this, does anybody know anything about this?

 

 

Cheers

 

Jure

 

6 Replies

  • Could you post your iRule code please, so we can understand the context and logic of the rule?
  • As I understand is that this could mean the client session either disconnected half way the session or that LTM is somehow loosing the sessions. I'd like to know if this is a client problem I don't care about or a LTM problem.

    doesn't it mean server-side connection is not existing because it is triggered on serverside { TCP::collect } command?

     

  • Well, it's not a trivial rule, what it does is that it extracts RCPT TO fields and checks them via en external sideband connection and if the user doesn't exist it fakes the server response and doesn't pass it to the server. We are using it for the intermediate time of migration of mail systems and the incoming mail is already going trough the new system, which doesn't know which users are valid and which not. And some other fixups (like deleting STARTLS from options)..

    The error lines show the error at

    TCP::respond $static::DiePerm

    but in less than 1% of cases, so it doesn't seem as an error as such (I think)..

    Here goes:

    
    when RULE_INIT {
        set static::debugSCRT 0
        set static::ConnTimeout 1000
        set static::ConnIdle 30 
        set static::VServer "LdapCheck"
        set static::DieTemp "450 Temporary unavailable\r\n"
        set static::DiePerm "550 Mailbox unavailable\r\n"
        set static::STLS "250-STARTTLS\r\n"
        set static::RCPTBAD "550 Invalid recipient: "
        set static::EOT "\r\n"
        set static::HSLpool "mail.syslog"
        set static::collectBuffer 40000
    }
    when CLIENT_ACCEPTED {
        set host [IP::client_addr]
        if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>" }
        set hsl [HSL::open -proto UDP -pool $static::HSLpool]
        set dataon 0
        set ischecked 0
    }
    when CLIENT_DATA {
         all the commands
        set cmds [split [TCP::payload] $static::EOT];
        if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>: List>$cmds<" }
    
         skip DATA section
        if { [expr {$dataon==1}] }{
    serverside { TCP::collect }
    TCP::release
        }
         this we process
        if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>: Tpay>[TCP::payload]<" }
        
         catch HELO section, reset ischecked
        if { ([lsearch $cmds "HELO*"] > -1) ||
     ([lsearch $cmds "EHLO*"] > -1) ||
     ([lsearch $cmds "RSET*"] > -1) } {
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>: resetting params" }
    set ischecked 0
    set dataon 0
        }
        
         catch STARTLS section
        if { [lsearch $cmds "STARTTLS*"] > -1 } { 
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>: block STARTLS" }
    TCP::respond "502 TLS not supported\r\n"
    TCP::payload replace 0 [TCP::payload length] ""
    TCP::release
    serverside { TCP::collect }
        }
        
        foreach cdata [lsearch -inline -glob -all $cmds "RCPT *"] {
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>: RCPT TO...>$cdata<" }
    
     extract email
    set email [split [lindex [lsearch -inline -glob [split $cdata <>] *@*] 0] @]
    set fullmail [join $email @]
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>em: >$email<>$fullmail<" }
    
    if { [llength $email] } {  got the email, check the email
         get domain
        set domain [lindex $email 1]
        if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>dom: >$domain<" }
        
         check if it is in backupMX list
        if { [class match $domain equals MailPassDomains] }{
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>:WL pass trough $fullmail" }
     pass directly
    set ischecked 1
        } else {
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>: sideband check email" }
     check in LDAP, open a connection
    set conn [connect -timeout $static::ConnTimeout -idle $static::ConnIdle -status conn_status $static::VServer]
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>: connGet: <$conn> connStatus: <$conn_status>" }
    
     connection ok?
    if {$conn eq ""}{  
        if { $static::debugSCRT >= 0 }{ log local0.debug "C<$host>: failed opening sideband connection" }
         it failed, die temp
        TCP::respond $static::DieTemp
        TCP::close
    }
     conn ok, send&recieve
    set send_info [send -timeout $static::ConnTimeout -status send_status $conn "$fullmail$static::EOT"]
    set recv_data [recv -status recv_status -timeout $static::ConnTimeout $conn]
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>sband-rcv: <$recv_data>" }
    
    if { [string length $recv_data] } {
         make actions, response 0-user ok,1-no user,2-err
        switch -glob $recv_data {
    0* {
         allow trough
        if { $static::debugSCRT > 0 }{ log local0.debug "C<$host>: OK >$fullmail<" }
        HSL::send $hsl "<134> LDAPCHECK: <$host>: OK >$fullmail<"
        set ischecked 1
    }
    1* {
         drop permanently
        if { $static::debugSCRT > 0 }{ log local0.debug "C<$host>: DROP >$fullmail<" }
        HSL::send $hsl "<134> LDAPCHECK: <$host>: BAD >$fullmail<"
    
        TCP::respond "$static::RCPTBAD <$fullmail>\r\n"
        TCP::payload replace 0 [TCP::payload length] ""
        TCP::release
        serverside { TCP::collect }
    
    }
    2* {
         drop temporary
        if { $static::debugSCRT > 0 }{ log local0.debug "C<$host>: TEMP FAIL >$fullmail<" }
        HSL::send $hsl "<134> LDAPCHECK: <$host>: TEMP FAIL >$fullmail<"
        TCP::respond $static::DieTemp
        TCP::close
    }
        }
    } else {
         drop temporary
        if { $static::debugSCRT > 0 }{ log local0.debug "C<$host>: TEMP FAIL/NO CONN" }
        HSL::send $hsl "<134> LDAPCHECK: <$host>: TEMP FAIL/NO CONN"
        TCP::respond $static::DieTemp
        TCP::close
    }
        }
    } else {  wrong email format
         drop perm
        if { $static::debugSCRT > 0 }{ log local0.debug "C<$host>: DROP/BAD EMAIL FORMAT" }
        HSL::send $hsl "<134> LDAPCHECK: <$host>: DROP/BAD EMAIL FORMAT" 
        TCP::respond $static::DiePerm
        TCP::close
    } 
     end check the email
        } 
        
         catch DATA section
        if { [lsearch $cmds "DATA*"] > -1 } { 
     don't buffer DATA
    if { $static::debugSCRT > 1 }{ log local0.debug "C<$host>: DATA, skip processing" }
    if { [expr {$ischecked != 1}] }{
         this one got trough checking somehow
        if { $static::debugSCRT > 0 }{ log local0.debug "C<$host>: DROP/NOT PROPERLY CHECKED" }
        HSL::send $hsl "<134> LDAPCHECK: <$host>: DROP/NOT PROPERLY CHECKED"
        TCP::respond $static::DieTemp
        TCP::close
    }
    set dataon 1
        }
    
         nothing else to do
        serverside { TCP::collect }
        TCP::release
        TCP::collect    
    }
    when SERVER_CONNECTED {
        TCP::collect
    }
    when SERVER_DATA {
        if { $static::debugSCRT > 1 }{ log local0.debug "S<$host>: [TCP::payload]" }
    
         check end of DATA
        if { [expr {$dataon==1}] && 
     ([string toupper [TCP::payload]] starts_with 250) }{
    if { $static::debugSCRT > 1 }{ log local0.debug "S<$host>: end of DATA" }
    set dataon 0
        }
         remove STARTTLS from response
        if { [string toupper [TCP::payload]] contains "STARTTLS" } {
    if { $static::debugSCRT > 1 }{ log local0.debug "S<$host>: hiding TLS" }
    TCP::payload replace [string first $static::STLS [TCP::payload]] [string length $static::STLS] ""
        }
        TCP::release
        clientside { TCP::collect }
    }
    
  • I think I figured this one out myself. This VS has 2 iRules attached, the other one being MSM, a f5 product that does RBL checking and when it decides the user is from an untrusted IP it drops it. As both of them start TCP::collect and in some cases MSM drops the connection and this other iRule finds out there is no more session present and logs the above error. Hope this will be useful to somebody as there is very little reference to the above error around..
  • Thanks. Presumably you could check for the existence of the connection first to avoid the error, or perhaps set something in the other iRule to check for later, or disable later events.
  • Hmm, any idea on how one would do that? Using session table lookup or is there a session_exists pragma I could use? One way of having that working as I see it is merging the 2 iRules into a single one which even shouldn't be too difficult as MSM does its stuff in CLIENT_ACCEPTED which the other one doesn't use much, but the problem being that this one will only be in place for the next couple of months and I'm not sure if we could have some problems with F5 support in case some problems arise with the MSM..

     

     

    Jure