Forum Discussion

Eblakely_225577's avatar
Eblakely_225577
Icon for Nimbostratus rankNimbostratus
Nov 28, 2016

Use of getfield in iRule

Hi all,

 

I'm using iRules to implement some rate limiting based on a custom HTTP header our users insert into each request.

 

The relevant bits in the iRule are as follows: if { [HTTP::header exists Authorization] } { set limiter [getfield [HTTP::header Authorization] " " 2 ] set methodCount [table key -count -subtable [IP::client_addr]:$limiter]

 

The header looks like this:

 

Authorization: ID biglongstring-usedforauthtoken

 

The iRule works if the user sends the Token biglongstring-usedforauthtoken with one white space between the two fields. However, it breaks if there are two or more white spaces. Our spec says to use one whitespace, but you can never be sure with users/

 

Is there a better way to scan and split that header such that I get only the token back and use it ? I've tried a few things, to no avail and am almost at wits end....

 

Thanks for any advice.

 

3 Replies

  • Hi Eblakely,

    you may use one of the commands below to extract your Authorization data.

    Example 1: Serach the position of the first

    whitespace
    character, then skip directly after the found position and take the remaining string.

    set limiter [findstr [HTTP::header value Authorization] " " 1 end]
    

    Example 2: Same as Example 1 but with additional removal of any additional

    whitespaces
    .

    set limiter [join [findstr [HTTP::header value Authorization] " " 1 end] ""]
    

    Cheers, Kai

  • And one more problem .... for which I am just stumped:

    The full iRule I have is thus:

    when RULE_INIT { set static::maxRate 10 set static::timeout 1 } when HTTP_REQUEST { if { ([HTTP::uri] starts_with "/v3") } { log local0. "You are here: step 1"

        if { [HTTP::header exists Authorization] } {
        log local0. "You are here: step 2"
        set limiter [join [findstr [HTTP::header value Authorization] " " 1 end] ""]
            log local0. "You are here: step 3 =>  got auth token => $limiter"
            set methodCount [table key -count -subtable [IP::client_addr]:$limiter]
            log local0. "You are here: step 4 => Count = $methodCount /  $limiter"
    
    } else {
            set limiter "[TCP::client_port]"
            log local0. "You are here: Step 5:  Limiter Set to: [TCP::client_port] for [IP::client_addr]"
            set methodCount [table key -count -subtable [IP::client_addr]:$limiter] 
            log local0. "You are here: step 6 => Count = $methodCount /  $limiter"
        }
    
            if { $methodCount < $static::maxRate } {
                incr methodCount 1
                log local0. "You are here: step 7 Adding entry for [IP::client_addr]"
                table incr -notouch  -subtable [IP::client_addr]:$limiter [clock clicks] "1" indef $static::timeout
       } else {
                log local0. "[IP::client_addr] with limiter $limiter blocked"
                HTTP::respond 429 content "Request blocked - Requests per second exceeded." Access-Control-Allow-Origin "*"
                return
    
        }
    }
    

    }

    I get the following error in the logs and I for the life of me cannot figure out what is wrong:

    - wrong args: should be "table incr -notouch -subtable 172.20.0.84:{f027f673812eb228d7b86a86601fc166-6f0a04ed3ef4722012ab8245f538abe8} 1480534505883002 1 indef 1 (extra args supplied)" while executing "table incr -notouch -subtable [IP::client_addr]:$limiter [clock clicks] "1" indef $static::timeout"

    Help. Anyone !!! Please.

    The goal of this irule is to rate limit on the IP::authtoken. If that fails then filter on the IP:remote_port

    A client is allowed 120 HTTP requests per second. If I remove the "1" indef $static::timeout portion of the table incr command then it "works" , sort of. It will hit 120 connections and drop everything after the 120th connection, as it is not properly expiring the connection table.

    The [clock clicks] "1" indef $static::timeout works in another irule so I am not sure what is wrong here.

    I'd appreciate any help or assistance.

    Thank you.

    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP

      Hi Eblakely,

      To resolve your problem, you can simply change

      [table incr ...]
      to
      [table set ...]
      .

      This change will cause your iRule to create a unique

      -subtable
      key based on the current
      [clock]
      with the value 1. This change does not have any impact on the
      [table key -count -subtable]
      command, since this command will just care about unique keys in a given
      -subtable
      and don't care about the key values.

      Note: The difference of

      [table incr]
      and
      [table set]
      in your case is, that
      [table set]
      supports additional parameters to handle timeouts and lifetimes.

      Cheers, Kai