Forum Discussion

dubdub's avatar
dubdub
Icon for Nimbostratus rankNimbostratus
Nov 06, 2012

A strange case for catching an exception

Environment: 11.1.0 HF2 custom EHF build

I have an iRule associated with a virtual server that's protected by an APM policy. This VS usually has north of 12,000 concurrent users, and is extremely critical in addition to being insanely busy. I've started seeing the following errors in my syslog recently that I expect are due to a new/misconfigured client:

Nov 6 04:31:07 tmm err tmm[8637]: 01220001:3: TCL error: /Common/myiRule - Illegal argument (line 46) invoked from within "HTTP::username"

The only place in my iRule that I invoke HTTP::username is where I set it to a variable for use later. I'm guessing that line 46 is within the username function itself, not in my iRule.

So what I want to do is try to find out who this misconfigured client might be. Whoever they are, their connection is being terminated if I understand the TCL processing of the exception correctly; and here's the weird part - I don't necessarily want to let them through successfully yet. I just want to find out more about their device. And I don't want to log all clients, as I will rapidly run out of resources if I try that.

If I change the following line in my iRule:

set myUser [HTTP::username]

to

if { [catch {set myUser [HTTP::username] } ] } {
  set myAgent [HTTP::header "User-Agent"]
  log local0. "Invalid username from [IP::remote_addr] using $myAgent"
}

how can I let the connection still terminate so I am not changing the current behavior? I know that catch will always complete execution without raising an error. I can't let the iRule continue processing as if the username is valid. I think adding just a return statement inside the catch would somehow keep the policy continuing - is the best approach to add a drop or reject statement there instead?

Thanks,

Jen

8 Replies

  • Lucas_Thompson_'s avatar
    Lucas_Thompson_
    Historic F5 Account
    Your proposal of using catch is the right way to do it.

     

    Since HTTP::username reads the Authorization header, you'll probably want to dump that too in your log statement, and if it's a GET or POST too for good measure.

     

     

    eg:

     

    log local0. "Invalid username from [IP::remote_addr] using $myAgent , authorization: [HTTP::header authorization] method: [HTTP::method]"

     

     

    Adding that extra stuff will give you a little better clue about what exactly is going on. It may give enough information to reproduce whatever the trouble is. I wonder if maybe it's doing that if the authorization header is malformed? maybe it's not good base64, or maybe it's missing?

     

     

    Maybe another interesting thing to do, if you find that the authorization header is present but isn't working, is to do it manually instead of using HTTP::username, like in this example:

     

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

     

    One thing to note about that is that if a base64 decode is called against invalid data, it will also throw a runtime exception so you'd have to use the same sort of catch technique to avoid those.

     

  • Hi Jen,

     

     

    Which event are you running this code in? [HTTP::username] should return a null string if the username isn't present in an HTTP request. I don't think it *should* return a runtime error. Do you have any hints as to what type of client request triggers this runtime error?

     

     

    In addition to using catch to handle the error, can you open a case with F5 Support to let them know about the runtime TCL error?

     

     

    As for your specific question, yes you can use reject to close the TCP connection with a reset:

     

     

    
    if { [catch {set myUser [HTTP::username] } ] } {
      log local0. "Invalid username from [IP::remote_addr] using [HTTP::header User-Agent]"
      reject
    }
    

     

     

    Thanks,

     

    Aaron
  • dubdub's avatar
    dubdub
    Icon for Nimbostratus rankNimbostratus
    Hi Aaron,

     

     

    I'm running this in HTTP_REQUEST... I will be using lthompson's suggestion of including the authorization header and the HTTP method in the logged information, it's a fantastic idea and should help pinpoint where the runtime error is coming from. I will post what I find out as soon as I get the info. Unfortunately, despite the enormous number of connections, I've only seen about a dozen occurrences of the error over the past few days, so whatever client it is - they're not trying too terribly hard ;)

     

     

    Thanks for the catch too on the unneeded user agent variable. I'll take that out, it's unnecessary.

     

     

    Thanks,

     

    Jen
  • dubdub's avatar
    dubdub
    Icon for Nimbostratus rankNimbostratus
    Finally caught one! This is the log message:

     

     

    Nov 11 11:02:35 tmm3 info tmm3[8640]: Rule /Common/myiRule : Invalid username from x.x.x.x using Apple-iPhone3C1/902.176, authorization: Basic (null) method: OPTIONS

     

     

    So, an iPhone 4 running iOS5.1. Thoughts on how else I can track down more details on this one?

     

     

    Thanks,

     

    Jen

     

     

  • This seems to be related to cross domain requests perhaps: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/

     

     

    I suspect you are blocking the OPTIONS method?
  • Can you try logging the [HTTP::request] value to get the full HTTP request headers. If it's over 1k bytes, you might want to log it remotely using HSL as logging locally via syslog-ng is limited to ~1k bytes.

     

     

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

     

     

    As Steve said, it might be that you're dropping these requests with this or another iRule. That might trigger this runtime error.

     

     

    Aaron

     

     

  • dubdub's avatar
    dubdub
    Icon for Nimbostratus rankNimbostratus
    Hi Steve,

     

     

    I confirmed we are not blocking the OPTIONS method, and it looks like the actual header value is coming over as "(null)", so I have opened a case for the runtime TCL error in that situation, since an invalid base-64 encoded string shouldn't trip up the function like that.

     

     

    And hi Aaron :)

     

     

    Sure, I can add that. I do use HSL from this unit on other iRules, so I can just default to that for the catch. There isn't another iRule on this VS, so this should be the only one dropping the connection. We got a flurry of the errors this weekend, but since late yesterday they have dropped off, so I'm not sure when the next one will show up. I feel like I'm fishing in the ocean with a minnow!

     

     

    Thanks,

     

    Jen
  • dubdub's avatar
    dubdub
    Icon for Nimbostratus rankNimbostratus
    Just to close this thread out... suffice it to say that the minnow didn't catch anything. The errors have disappeared over the past six weeks and I haven't seen them for a while.

     

     

    Result of the support case: since Apple isn't adhering to the specification in this situation, no changes to the HTTP::username function will be made. I will just need to add a catch around the function invocation to make sure my rule flows the way I want it to, even when an invalid base64-encoded string is sent through.

     

     

    Thanks,

     

    Jen