Forum Discussion

Matt_Jannusch's avatar
Matt_Jannusch
Icon for Nimbostratus rankNimbostratus
Feb 20, 2008

http_process_state_parse_header

I've written an iRule that sets up persistence on a virtual server for both .NET SessionID cookies as well as embedded HTML form post arguments, and the iRule is working great as users are going through the sites. There is a "logout" button on the site, and when a user clicks on it, it closes out the sessions and links the user back to the homepage of the site.

 

 

When someone clicks "logout", with the iRule in place they get a TCP reset packet from the LTM, and the LTM logs the following error message:

 

 

http_process_state_parse_header - Invalid state transition to ST_HTTP_XFER_HEADERS Server side: vip=vs_www.xxxxxxx.com profile=http pool=pool_www.xxxxxxx.com

 

 

I can't find any information as to what this error actually means, or what I might do to prevent it from occuring in the first place.

 

 

Any ideas?

5 Replies

  • iRule to take POST arguments named "SESSION" and use the numeric value as a universal persistence key

     

    iRule designed by Matt Jannusch of FishNet Security

     

    when RULE_INIT {

     

    set ::debug 1

     

    set ::term "\""

     

    log local0. "persist_SESSION_postarg iRule initialized."

     

    }

     

    when HTTP_REQUEST {

     

    See if we've got an incoming ASPSESSIONID cookie, if so - try to find a persistence record to match.

     

    set ::postMethod 0

     

    set cli [IP::remote_addr]:[TCP::remote_port]

     

    set SessionID ""

     

    set SessionID [findstr [HTTP::cookie names] "ASPSESSIONID" 12 8]

     

    if {$::debug}{log local0. "Client: $cli Request SessionID: >$SessionID<"}

     

    if { $SessionID != "" } { persist uie $SessionID 6000 }

     

    Determine if the incoming request is a form POST - if it is, flag it for later when we are watching server responses.

     

    POSTs need to be scanned for our SESSION argument value for persistence, and the server replies must be

     

    watched for them embedded in the form as well.

     

    if {[HTTP::method] equals "POST" } {

     

    If it is a POST, grab all the packet data of the response, it could be multiple packets

     

    set ::postMethod 1

     

    if { [HTTP::header exists "Content-Length"] } {

     

    set content_length [HTTP::header "Content-Length"]

     

    } else {

     

    set content_length 1000000000

     

    }

     

    if { $content_length > 0 } {

     

    if {$::debug}{log local0. "POST method detected, collecting $content_length bytes" }

     

    HTTP::collect $content_length

     

    }

     

    else {

     

    pool pool_www.xxxxxxx.com

     

    }

     

    }

     

    }

     

    when HTTP_REQUEST_DATA {

     

    We have the whole request, now parse it to look for the SESSION postarg's value, if it exists.

     

    if {$::debug}{log local0. "POST Data: [HTTP::payload]"}

     

    set namevals [split [HTTP::payload] "&"]

     

    for {set i 0}{$i < [llength $namevals]} {incr i} {

     

    set params [split [lindex $namevals $i] "="]

     

    if {$::debug}{log local0. " [lindex $params 0] : [lindex $params 1]"}

     

    if {[lindex $params 0] equals "SESSION"} {

     

    Found it! Persist on the value of SESSION

     

    if {$::debug}{log local0. "Param length is [string length [lindex $params 1]]"}

     

    First response from login .dll is a blank SESSION arg, don't try to persist on that!

     

    if { [string length [lindex $params 1]] > 12 } {

     

    persist uie [lindex $params 1]

     

    }

     

    }

     

    }

     

    }

     

    when HTTP_RESPONSE {

     

    set cli [IP::remote_addr]:[TCP::remote_port]

     

    set SessionID [findstr [HTTP::cookie names] "ASPSESSIONID" 12 8]

     

    if {$::debug}{log local0. "Client: $cli Response SessionID: >$SessionID<"}

     

    if { $SessionID != "" }{ persist add uie $SessionID 6000 }

     

    if {$::postMethod} {

     

    First entry on application is a POST request with a blank SESSION argument (no value).

     

    if {$::debug}{log local0. "POST response from server, collecting [HTTP::header Content-Length] bytes."}

     

    if { [HTTP::header exists "Content-Length"] } {

     

    set content_length [HTTP::header "Content-Length"]

     

    } else {

     

    set content_length 1000000000

     

    }

     

    if { $content_length > 0 } {

     

    if {$::debug}{log local0. "Response to post, collecting $content_length bytes" }

     

    HTTP::collect $content_length

     

    }

     

    HTTP::collect $content_length

     

    }

     

    }

     

    when HTTP_RESPONSE_DATA {

     

    Locate all SESSION postargs in the HTML response - there could be multiples, in the case of the course list

     

    page where each course has a unique SESSION id set for some reason. Create a persistence record for each.

     

    set session_indices [regexp -all -inline -indices {"SESSION" VALUE="[0-9]*"} [HTTP::payload]]

     

    foreach session_idx $session_indices {

     

    set session_start [lindex $session_idx 0]

     

    set session_end [lindex $session_idx 1]

     

    set session_len [expr {$session_end - $session_start +1}]

     

    set session_string [string range [HTTP::payload] $session_start $session_end]

     

    set session_id [findstr $session_string "VALUE=" 7 $::term]

     

    persist add uie $session_id 6000

     

    if {$::debug}{log local0. "Session ID in server reply: $session_id"}

     

    }

     

    }

     

    when LB_FAILED {

     

    pool pool_www.xxxxxxx.com

     

    LB::reselect

     

    if {$::debug}{log local0. "Selected server [LB::server] did not respond. Reselected from pool."}

     

    }
  • Hi,

     

     

    First i would recommend you to remove the ::for your variable ::postMethod because what you need only to do is to have this variable reachable from any event IN THIS connection only. That's what is happening with local variables. You don't need to set it as a global variables in your case

     

     

    Moreover by defining it as a global variables it means ALL YOUR CONNECTION in this VS share the same variable, so you must have issues with it right now$

     

     

    to help you, can you turn debug to 1 and show us the output when you click on the logout button ?

     

     

    Thanks
  • Sorry for the delay, I was out on another assignment and didn't get around to putting together the log data. Here it is...

     

     

    Normal iRule responses:

     

     

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : POST method detected, collecting 173 bytes

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : POST Data: SESSION=0040871497437490&SECTION=2&NAME=xxxxxx92&GROUP=XXX111&ACCESS=1234567891234&EXPIRES=20%3A02%3A2008%3A16%3A33+96729668-137702865182&CHECK=1234567891234&FINISH=

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : SESSION : 0040871497437490

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : Param length is 16

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : SECTION : 2

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : NAME : xxxxxx92

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : GROUP : XXX111

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : ACCESS : 1234567891234

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : EXPIRES : 20%3A02%3A2008%3A16%3A33+96729668-137702865182

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : CHECK : 1234567891234

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : FINISH :

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : Client: 10.200.204.125:80 Response SessionID: ><

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : POST response from server, collecting bytes.

     

    Feb 20 04:21:20 tmm tmm[1614]: Rule iRule_ComboTest : Response to post, collecting 1000000000 bytes

     

    Feb 20 04:21:21 tmm tmm[1614]: Rule iRule_ComboTest : Session ID in server reply: 0040871497437490

     

     

     

    Error when "logging out" of application:

     

     

    Feb 20 04:22:01 tmm tmm[1614]: 011f0008:3: http_process_state_parse_header - Invalid state transition to ST_HTTP_XFER_HEADERS (Server side: vip=vs_www.xxxxxx.com profile=http pool=pool_www.xxxxxx.com)

     

    Feb 20 04:22:06 tmm tmm[1614]: Rule iRule_ComboTest : Client: 66.55.53.22:16337 Request SessionID: >ASQADQBA<

     

    Feb 20 04:22:06 tmm tmm[1614]: Rule iRule_ComboTest : Client: 10.200.204.150:80 Response SessionID: ><

     

    Feb 20 04:22:07 tmm tmm[1614]: Rule iRule_ComboTest : Client: 66.55.53.22:16337 Request SessionID: >ASQADQBA<

     

    Feb 20 04:22:07 tmm tmm[1614]: Rule iRule_ComboTest : Client: 10.200.204.150:80 Response SessionID: ><

     

    Feb 20 04:22:07 tmm tmm[1614]: Rule iRule_ComboTest : Client: 170.223.116.94:2768 Request SessionID: >ASQADQBA<

     

    Feb 20 04:22:07 tmm tmm[1614]: Rule iRule_ComboTest : Client: 170.223.116.94:2776 Request SessionID: >ASQADQBA<

     

     

  • Do you have some kind of capability to trace the request you send when you do a logout ?

     

     

    I'd like to see if it's a POST request, and the content.

     

     

    Moreover did you remove the :: in front of the variable PostMethod? it must be a local variable not a global one.