Forum Discussion

Arkashik_6155's avatar
Arkashik_6155
Icon for Nimbostratus rankNimbostratus
Jan 04, 2013

iRule to log POP3/IMAP user

Hello everyone,

 

Since i'm new with iRules, could you please advice me how to log username/user's email address from POP3 and IMAP sessions.

 

The goal is to move users to go through POP3/IMAP over SSL, however, prior to do so, we would like to identify users who still use un-encrypted connections and reduce impact for the production.

 

I already created custom log facility for that pourpose, but i couldn't find how to parse username from traffic.

 

Many thanks!

 

 

P.S. Just in case - sorry for my bad english ;)

 

  • Hey. I believe for IMAP login packet data would look like this;

    
    login username password
    

  • So an iRule to log that might look like this. This is a bit simple and I'm sure it could be improved and you could pull the username string out, I just don't have that level of skill;

    
    when CLIENT_ACCEPTED {
     TCP::collect 300
     }
    
    when CLIENT_DATA {
     if { [TCP::payload 300] contains "login" } {
      log local0. "[TCP::payload 300]"
      TCP::release
     }
    
  • I think it would be simpler to look in the server software side for a solution to this, or is that just not possible for you?
  • OK, here's an improvement using findstr to pull out just the username and restricting data collection to port 143 connections;

    
    when CLIENT_ACCEPTED {
     if {[TCP::local_port] == 143 } {
      Collect 300 bytes of data if client is using unencrypted IMAP
      TCP::collect 300
     }
    }
    
    when CLIENT_DATA {
     if {[TCP::local_port] == 143 } {
     Only do the following if client is using unencrypted IMAP and presumably data has been collected
      if { [TCP::payload 300] contains "login" } {
       Look for text 'login', skip forward 1 character and match up to the next space
       set imapusername [findstr [TCP::payload 300] "login" "1" " "]
       log local0. "Unecrypted IMAP connection established by $imapusername"
       Release and flush collected data
       TCP::release
       Stop processing the iRule for this event here
       return
      }
     }
    }
    
  • Posted By What Lies Beneath on 01/04/2013 05:44 AM

    OK, here's an improvement using findstr to pull out just the username and restricting data collection to port 143 connections;

     when CLIENT_ACCEPTED { if {[TCP::local_port] == 143 } { Collect 300 bytes of data if client is using unencrypted IMAP TCP::collect 300 } } when CLIENT_DATA { if {[TCP::local_port] == 143 } { Only do the following if client is using unencrypted IMAP and presumably data has been collected if { [TCP::payload 300] contains "login" } { Look for text 'login', skip forward 1 character and match up to the next space set imapusername [findstr [TCP::payload 300] "login" "1" " "] log local0. "Unecrypted IMAP connection established by $imapusername" Release and flush collected data TCP::release Stop processing the iRule for this event here return } } } 

    Thanks a lot, will give a try with this one.

    Posted By Mohamed Lrhazi on 01/04/2013 05:43 AM

    I think it would be simpler to look in the server software side for a solution to this, or is that just not possible for you?

    Hello Mohamed, this solution is also under review.

  • OK, and now with POP3;

    
    when CLIENT_ACCEPTED {
     if { ([TCP::local_port] == 143) or ([TCP::local_port] == 110) } {
      Collect 300 bytes of data if client is using unencrypted IMAP or POP3
      TCP::collect 300
     }
    }
    when CLIENT_DATA {
     if { [TCP::local_port] == 143 } {
     Only do the following if client is using unencrypted IMAP and presumably data has been collected
      if { [TCP::payload 300] contains "login" } {
       Look for text 'login', skip forward 1 character and match up to the next space
       set imapusername [findstr [TCP::payload 300] "login" "1" " "]
       log local0. "Unecrypted IMAP connection established by $imapusername"
       Release and flush collected data
       TCP::release
       Stop processing the iRule for this event here
       return
      }
     }
     elseif { [TCP::local_port] == 110 } {
     Only do the following if client is using unencrypted POP3 and presumably data has been collected
      if { [TCP::payload 300] contains "USER" } {
       Look for text 'USER', skip forward 1 character and match up to the end of the line
       set pop3username [findstr [TCP::payload 300] "USER" "1"]
       log local0. "Unecrypted POP3 connection established by $pop3username"
       Release and flush collected data
       TCP::release
       Stop processing the iRule for this event here
       return
      }
     }
    }
    
  • this is just another example.

    pop3

    root@(B3900-R72-S16)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm virtual bar110
    ltm virtual bar110 {
        destination any:110
        ip-protocol tcp
        mask any
        pool gw
        profiles {
            tcp { }
        }
        rules {
            myrule110
        }
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        translate-address disabled
        translate-port disabled
        vlans-disabled
    }
    root@(B3900-R72-S16)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm rule myrule110
    ltm rule myrule110 {
        when CLIENT_ACCEPTED {
      TCP::collect 0 0
    }
    when CLIENT_DATA {
      if { [TCP::payload] contains "USER" } {
        scan [TCP::payload] {USER%s} username
        log local0. $username
        TCP::release
        return
      }
      TCP::release
      TCP::collect
    }
    }
    
    [root@B3900-R72-S16:Active:Standalone] config  tail -f /var/log/ltm
    Jan  5 02:56:05 B3900-R72-S16 info tmm[11078]: Rule /Common/myrule110 : garfield@something.com
    Jan  5 02:56:09 B3900-R72-S16 info tmm1[11078]: Rule /Common/myrule110 : odie@something.com
    
  • imap

    root@(B3900-R72-S16)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm virtual bar143
    ltm virtual bar143 {
        destination any:143
        ip-protocol tcp
        mask any
        pool gw
        profiles {
            tcp { }
        }
        rules {
            myrule143
        }
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        translate-address disabled
        translate-port disabled
        vlans-disabled
    }
    root@(B3900-R72-S16)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm rule myrule143
    ltm rule myrule143 {
        when CLIENT_ACCEPTED {
      TCP::collect 0 0
    }
    when CLIENT_DATA {
      if { [TCP::payload] contains "LOGIN" } {
        scan [TCP::payload] {%*s LOGIN %s} username
        log local0. "username $username"
        TCP::release
        return
      }
      TCP::release
      TCP::collect
    }
    }
    
    [root@B3900-R72-S16:Active:Standalone] config  tail -f /var/log/ltm
    Jan  5 03:16:22 B3900-R72-S16 info tmm3[11078]: Rule /Common/myrule143 : username "garfield@something.com"
    Jan  5 03:16:22 B3900-R72-S16 info tmm2[11078]: Rule /Common/myrule143 : username "garfield@something.com"
    Jan  5 03:16:22 B3900-R72-S16 info tmm1[11078]: Rule /Common/myrule143 : username "odie@something.com"
    Jan  5 03:16:22 B3900-R72-S16 info tmm[11078]: Rule /Common/myrule143 : username "odie@something.com"
    
  • Hello guys,

     

     

    Thanks for your replies and sorry for delay, had to switch to some more urgent tasks. I've tested iRules and they works fine for mee on 10.2.4 version. I'm using now nitass's iRules, works perfect =)

     

     

    Thanks a lot!