Forum Discussion

rahtoll_74678's avatar
rahtoll_74678
Icon for Nimbostratus rankNimbostratus
Sep 08, 2012

Check for String in TCP Payload from a specific position

 

Hi Guys,

 

 

I’m new here, as well as with F5 systems. Though basic load balancing is okay, I have this requirement where I believe iRules would be of big help. From the TCP payload, I need to base my load balancing from a specific 6-byte information in a specific position.

 

Here’s a sample payload, I need to search (underlined) info, to know (in string) if this is 000001 and decide load balancing from there. In some cases, the data here can be random characters, null, or zeros like the one below.

 

 

0000 00 15 17 48 5d fc 00 50 56 9f 0f 2b 08 00 45 00 ...H]..P V..+..E.

 

0010 01 2a 5b 1e 40 00 80 06 c2 b1 0a 08 06 12 d0 e0 .*[.@... ........

 

0020 fb 03 27 61 12 ae bd 85 05 bb 3f e8 5a 37 50 18 ..'a.... ..?.Z7P.

 

0030 fa 36 f3 f8 00 00 01 00 31 34 31 30 30 30 30 30 .6...... 14100000

 

0040 30 30 30 30 30 30 31 38 38 38 38 38 38 30 30 35 00000018 88888005

 

0050 30 30 30 30 30 30 30 37 30 32 30 31 30 30 30 37 00000007 02010007

 

0060 20 20 37 30 32 36 36 36 36 37 37 30 31 30 30 30 702666 67701000

 

0070 30 30 30 31 39 34 23 10 02 30 01 01 02 00 00 02 000194. .0......

 

0080 08 03 06 15 49 00 00 00 00 02 09 20 12 08 03 14 ....I... ... ....

 

0090 21 42 03 05 09 07 02 01 00 07 88 00 01 54 71 00 !B...... .....Tq.

 

00a0 97 f4 c0 dd 58 15 30 30 30 30 30 31 38 38 38 38 ....X.00 00018888

 

00b0 38 38 30 30 35 36 36 36 36 37 37 30 31 20 20 20 88005666 67701

 

00c0 20 20 20 20 20 01 01 07 56 00 00 00 00 07 80 02 ... V.......

 

00d0 04 00 00 00 78 02 32 30 30 37 37 31 31 43 45 30 ....x.20 07711CE0

 

00e0 37 33 32 30 30 44 37 31 36 32 30 31 32 30 38 30 73200D71 62012080

 

00f0 33 31 34 32 31 34 32 04 00 00 01 28 17 00 15 30 3142142. ...(...0

 

0100 30 30 30 35 33 38 38 38 38 38 38 30 30 35 36 36 00053888 88800566

 

0110 36 36 37 37 30 39 20 20 20 20 20 20 20 20 00 00 667709 ..

 

0120 00 43 48 46 33 2e 34 39 30 30 30 30 02 07 02 00 .CHF3.49 0000....

 

0130 00 00 00 00 00 02 07 56 .......V

 

 

We’ve did the basic iRule below but obviously does not work on all transactions:

 

when CLIENT_ACCEPTED {

 

 

TCP::collect 15

 

}

 

when CLIENT_DATA {

 

if { [TCP::payload 15] contains "000001" } {

 

pool Pool1

 

} else {

 

pool Pool2

 

}

 

TCP::release

 

}

 

 

Any help would be appreciated and thanks in advance.

 

8 Replies

  • Hamish's avatar
    Hamish
    Icon for Cirrocumulus rankCirrocumulus
    If you have a look at the FIX iRule from codeshare (I think Nathan did it didn't he?) it does pretty much what you want (Albeit for FIX traffic). That's at

     

     

    https://devcentral.f5.com/wiki/iRules.FixSelectPoolBasedOnSenderCompID.ashx

     

     

    There's also the LDAP Stats Measuring iRule at

     

     

    https://devcentral.f5.com/wiki/iRules.LDAP_Stats_Measuring.ashx

     

     

    H

     

  • Thank you for your response. I'm not sure if the link you provided would be related or would be the closest answer as what i just want to do is to read the 6 bytes on this specific position and try to confirm if it is the match i'm looking for. Like for example, from the TCP payload, i would skip 5 bytes which would be random characters, and start reading only for the next 6 bytes after this? Thanks again.

     

     

     

     

    Lez
  • Hi rahtoll,

     

     

    You could try adjusting your TCP::collect to collect 6 bytes after skipping the first 5 bytes and then do a literal compare.

     

     

    TCP::collect

     

     

    TCP::collect 6 5
  • That's a novel idea Michael, but I think it would have an unintended consequence of passing some of the data through on the serverside before parsing the full request payload.

    Here's a sample for using binary scan I tried in a quick test. Maybe something like this will work for you?

    
    when RULE_INIT {
     Encode the raw bytes in base64 to test
    set bytes_b64 "ABUXSF38AFBWnw8rCABFAAEqWx5AAIAGwrEKCAYS0OD7AydhEq69hQW7P+haN1AY+jbz+AAAAQAxNDEwMDAwMDAwMDAwMDE4ODg4ODgwMDU="
    log local0. "\$bytes_b64: $bytes_b64"
    
    set bytes_raw [b64decode $bytes_b64]
    log local0. "\$bytes_raw: $bytes_raw"
    
     Skip 59 bytes into the payload and save the next 6 bytes to $match
    binary scan $bytes_raw x59a6 match
    log local0. "\$match: $match"
    }
    

    < RULE_INIT >: $match: 000000

    I'll reply with a more specific example in a minute.

    Aaron
  • Here's what I'm thinking could work for your scenario:

    
    when CLIENT_ACCEPTED {
     Collect at least 65 bytes if the bytes to parse are 59-65
    TCP::collect 65
    }
    when CLIENT_DATA {
    
     use pool2 by default
    pool Pool2
    
     Start reading at the 59th byte and save 6 characters to $match
    if {[binary scan $bytes_raw x59a6 match] == 1}{
    log local0. "Matched $match"
    if { $match eq "000001" } {
    pool Pool1
    }
    }
    TCP::release
    }
    

    Aaron
  • Hi Michael / Aaron,

     

     

     

    Thanks for your help. I will simulate this up and provide update.

     

     

     

    Lez
  •  

    That's a novel idea Michael, but I think it would have an unintended consequence of passing some of the data through on the serverside before parsing the full request payload.

     

     

     

    Thanks for pointing that out Hoolio. I wouldn't have thought that if you did a TCP::collect offset that it would send through any data that you skipped to the server.

     

     

    I does make sense though.

     

     

    Thanks!
  • Just for update, I have modified the iRule to the one below and so far our simulation tests ended up to be positive and met the desired results! The payload actually starts at x56, so i just attempted this irule initially:

     

     

    when CLIENT_ACCEPTED {

     

    TCP::collect 65

     

    }

     

     

    when CLIENT_DATA {

     

     

    use pool2 by default

     

    pool test_pool2

     

     

    set mero [TCP::payload 15]

     

    Start reading at the 5th byte and save 6 characters to $match

     

    if {[binary scan $mero x5a6 match] == 1}{

     

    log local0. "Matched $match"

     

    if { $match eq "000001" } {

     

    pool test_pool1

     

    }

     

    }

     

    TCP::release

     

    }

     

     

     

    It may require adjustment but hopefully no :) Again thanks for the support!

     

     

     

    Lez