Forum Discussion

Chad_Roberts_21's avatar
Chad_Roberts_21
Icon for Nimbostratus rankNimbostratus
Jul 16, 2007

Log IMAP user name

Any ideas on how I might go about writing an iRule which would log the user name given each time a user authenticates? I need to log the source IP and the username for correlating connections later. Obviously the IP is the easy part.

 

 

I've got only a small idea where to start. We use IMAP-SSL, but I've used tcpdump with ssldump to find the following text string I'd like to match on somehow:

 

 

hkvs LOGIN "[username]" "[password]"

 

 

Any ideas on how I could search for the text "LOGIN" and then log whatever comes in between, say, the next to spaces? Sorry for being so vague. I'm kinda at a loss here.
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    If you are decrypting traffic @ LTM, you should be able to collect and examine the TCP data using the "TCP::collect" command. (Click here)

     

     

    HTH

     

    /deb
  • I would like to do something similar. The problem is, when terminating IMAP-SSL at the BigIP, TCP::collect get's the encrypted traffic. Is there a way to do something similar to a TCP::collect that collects the decrypted payload instead?

     

     

    E.
  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    When you say you're "terminating" the IMAP-SSL connection at the LTM, do you mean actually terminating the SSL at the LTM? If you've got a clientSSL profile set up to actually decrypt the SSL at the LTM, which is what Deb was referring to, then TCP::collect should be able to capture plain-text data just fine.

     

     

    Colin
  • Thanks Colin, but for whatever reason, that doesn't appear to be happening. I am, indeed, terminating the SSL at the LTM with a plain-text connection to the server pool. I'm using a very basic iRule:

     

     

    when CLIENT_ACCEPTED {

     

    TCP::collect

     

    }

     

     

    when CLIENT_DATA {

     

    set data [TCP::payload]

     

     

    if { $data contains "LOGIN" } {

     

    log local0. "User LOGIN <$data>"

     

    }

     

     

    debug

     

    log local0. "Payload: <$data>"

     

     

    TCP::release

     

    TCP::collect

     

    }

     

     

    And all that gets logged are lines like this:

     

     

    Jul 18 12:26:42 tmm tmm[1301]: Rule IMAP_User_Logging : Payload: Ú.ñ"ÊÈ»\¡¸OW÷ÛÇlé×Öuýc«îóDgyþ®QªËúmD üê;éoÁcò^E\Iuw>

     

     

    If I change CLIENT to SERVER in this case, I do log the server responses, but then again, they're not encrypted to start begin with.

     

     

    I must be missing something.

     

     

    E.

     

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    I'd try moving your collect to the CLIENTSSL_HANDSHAKE event, instead of CLIENT_ACCEPTED, to ensure that the collection of data actually occurs after the handshake has been completed.

     

     

    Other than that, your rule looks good.

     

     

    Let me know the results once you've given this a shot.

     

     

    Thanks,

     

    Colin
  • Yes, I had tried using CLIENTSSL_HANDSHAKE before and it didn't seem to make a difference.
  • bl0ndie_127134's avatar
    bl0ndie_127134
    Historic F5 Account
    TCP runs below SSL. You will need to use the stream filter to do the replacement.
  • Thanks bl0ndie.

     

     

    Deathbywedgie, I combined snippetd from iRule sample "LogHttpTcpUdpToSyslogng" with the STREAM commands and came up with this:

     

     

    ---

     

    when CLIENT_ACCEPTED {

     

    STREAM::enable

     

    STREAM::expression @LOGIN\ .*@

     

    }

     

     

    when STREAM_MATCHED {

     

    set match [getfield [STREAM::match] " " 2]

     

    set client "[IP::client_addr]:[TCP::client_port]"

     

    set vip [IP::local_addr]:[TCP::local_port]

     

    set node "[IP::server_addr]:[TCP::server_port]"

     

     

    log local0.info "$match $client $vip $node"

     

     

    STREAM::disable

     

    }

     

    ---

     

     

    Eric.
  • bl0ndie_127134's avatar
    bl0ndie_127134
    Historic F5 Account
    Since your expression is static, I would suggest that you configure the expression in the stream profile. Regexp compilation is a tad bit expensive to be doing it per connection (which is what happens in STREAM::expression). Otherwise it looks like you are on the right track.