Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Answers

TCL error message with X-Forwarded-For iRule

We are using the X-Forwarded-For http header field on the BigIP LTM to server our webshop application with client IP addresses (to determinde country hawk and so on). Our web application can only work with exactly one IP address in this field. Due to the fact that more IPs are possible I've written a little iRule, where I check if the field already exists and in case, removes it and write it new. So far, so good ...

Now we are using a contend delivery network in front of one of our web clusters. They deliver the client IP address in a custom header field, called True-Client-IP. So I've modified my iRule to check a) if the X-Forwarded-For field exists as above b) check if we have a True-Client-IP field and if yes, change this to a X-Forwarded-For field that our application knows what to do.

I receive regularly the following error message: Operation not supported (line 3) invoked from within "HTTP::header remove X-Forwarded-For"

Can anyone explain me what this means and how I can get rid of this error logs? Of course I would also be happy for any suggestions on improvement (I'm a network guy, no programmer :-))

Thanks, Manuel

iRule:

      when HTTP_REQUEST {
          # Always need to remove any existing XFF headers.
          if {[HTTP::header exists X-Forwarded-For]}{
              HTTP::header remove X-Forwarded-For
          }
          # If the ‘True-Client-IP’ header exists use it, otherwise just use client address.
          if {[HTTP::header exists True-Client-IP]}{
             HTTP::header replace X-Forwarded-For [HTTP::header value True-Client-IP]
          } else {
              HTTP::header replace X-Forwarded-For [IP::client_addr]
          }
        }
0
Rate this Question

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Can you try a combined version?

when HTTP_REQUEST {
    # 'root domain redirect'
    if { [HTTP::host] eq "mydomain.com" } {
        HTTP::respond 301 Location http://www.mydomain.com[HTTP::uri]
    } elseif { [set redir [class lookup [string tolower [HTTP::uri]] equals REDIRECTS_301_SCO]] ne "" } {
        HTTP::respond 301 Location $redir
    } elseif { "[HTTP::host][HTTP::uri]" eq "asia.mydomain.com/taiwan" } {
        HTTP::redirect http://www.mydomain.com/something
    } elseif { "[HTTP::host][HTTP::uri]" eq "asia.mydomain.com/hongkong" } {
        HTTP::redirect http://www.mydomain.com/something
    } elseif { "[HTTP::host][HTTP::uri]" eq "asia.mydomain.com/china" } {
        HTTP::redirect http://www.mydomain.com/something
    } elseif  { [HTTP::host] contains "asia.mydomain.com" } {
        HTTP::redirect http://www.mydomain.com
    } else {
        # Always need to remove any existing XFF headers.
        if {[HTTP::header exists X-Forwarded-For]}{
            HTTP::header remove X-Forwarded-For
        }
        # If the ‘True-Client-IP’ header exists use it, otherwise just use client address.
        if {[HTTP::header exists True-Client-IP]}{
            HTTP::header replace X-Forwarded-For [HTTP::header value True-Client-IP]
        } else {
            HTTP::header replace X-Forwarded-For [IP::client_addr]
        }
    }
}

There were a few issues:

  • Tcl error from trying to issue a redirect and insert an HTTP header for the same request
  • [HTTP::request] returns all the HTTP headers of a request. I think you want the host header value and the URI so I used [HTTP::host][HTTP::uri] and removed the protocol from the strings you were checking
  • == should be used for numeric comparisons. Use eq for string comparisons.
  • You can save the output from class lookup instead of running two commands

Aaron

1
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

It could be that you're trying to evaluate/insert/replace headers in the same context as a redirect. It may make more sense to combine the iRule cohesively:

when HTTP_REQUEST {
    # 'root domain redirect'
    if { [HTTP::host] == "mydomain.com" } {
        HTTP::respond 301 Location http://www.mydomain.com[HTTP::uri]
    } elseif { [class match [string tolower [HTTP::uri]] equals REDIRECTS_301_SCO ] } {
        HTTP::respond 301 Location [class lookup [string tolower [HTTP::uri]] REDIRECTS_301_SCO ]
    } else {
        if { [HTTP::header exists True-Client-IP] } {
            HTTP::header replace X-Forwarded-For [HTTP::header True-Client-IP]
        } else {
            HTTP::header replace X-Forwarded-For [IP::client_addr]
        }
    }
}

What F5 version is this? I'm not 100% sure of the second iRule as the HTTP::request command, at least not on a v10 or v11 system, would return a value like "http://asia.mydomain.com/taiwan". Are you certain this iRule is actually working?

1
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

If I had to guess, it's because you're trying to perform replace and remove operations on the same header. Try this:

when HTTP_REQUEST {
    if { [HTTP::header exists True-Client-IP] } {
        HTTP::header replace X-Forwarded-For [HTTP::header True-Client-IP]
    } else {
        HTTP::header replace X-Forwarded-For [IP::client_addr]
    }
}
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Thanks for your help, Kevin. I've implemented this in our dev system and will post an update about the outcome.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

I've changed the rule today on the productive environment. Unfortunately only the error message changed slightly to:

Operation not supported (line 2) invoked from within "HTTP::header replace X-Forwarded-For [HTTP::header True-Client-IP]"

Do you have any more ideas?

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Is there another iRule enabled on the virtual server? Or custom HTTP profile options which would trigger TMM to send an HTTP redirect?

Can you post the other iRules and/or the tmsh list output for the custom HTTP profile?

Aaron

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

We are not using a custom http profile on this VS. Actually all our needs are customized with iRules. There are two iRules which triggers http redirects.

One for recdirecting a group of certain ("foreign") URIs (like facebook.domain.com to facebook.com/domain, e.g.)


when HTTP_REQUEST {
    # 'root domain redirect'
    if { [HTTP::host] == "mydomain.com" } then {
        HTTP::respond 301 Location http://www.mydomain.com[HTTP::uri]
     }
    elseif { [class match [string tolower [HTTP::uri]] equals REDIRECTS_301_SCO ] } then {
        HTTP::respond 301 Location [class lookup [string tolower [HTTP::uri]] REDIRECTS_301_SCO ]
    }
}

and the other one is quite old and presents some hardlined redirects:


when HTTP_REQUEST {
          if { [HTTP::request] == "http://asia.mydomain.com/taiwan" } {
	  HTTP::redirect http://www.mydomain.com/something
             }
          elseif { [HTTP::request] == "http://asia.mydomain.com/hongkong" } {
	  HTTP::redirect http://www.mydomain.com/something
             }
          elseif { [HTTP::request] == "http://asia.mydomain.com/china" } {
	  HTTP::redirect http://www.mydomain.com/something
             }
          elseif  { [HTTP::host] contains "asia.mydomain.com" } {
	  HTTP::redirect http://www.mydomain.com
	           }
}

Furthermore we have cookie persistence and a fallback host enabled with an iRule.

Does this help anything?

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

I understand your point and it seems to make a lot of sense to combine all the "HTTP_REQUEST" actions in one iRule.

I've tested it and it looks awesome so far ... and no "tcl errors" any more! Thanks a lot Hoolio and Kevin, you're upvoted :-)

Kevin, unfortunately I cannot confirm that this rule was yet working at all. In our investigation we found out, that the same redirects we're applied on the web servers themselves. I've removed the rule, but the redirects are still working ... sorry to bother you.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Just upgraded from 10.2.0 to 11.4.1. I am using the exact syntax in deb's post from long ago, and I'm receiving a very similar tcl error. Anyone have any ideas?

original post

when HTTP_REQUEST {
  if {[HTTP::header exists X-Forwarded-For]}{
    HTTP::header replace X-Forwarded-For "[HTTP::header X-Forwarded-For], [IP::client_addr]"
  } else {  
    HTTP::header insert X-Forwarded-For [IP::client_addr]
  }
}

tcl error in my logs:

Apr 17 14:59:01 bigip2 err tmm[14652]: 01220001:3: TCL error: /Production/rule_remove_and_insert_XFF_header  - Operation not supported (line 1)     invoked from within "HTTP::header insert X-Forwarded-For [IP::client_addr]"

Thanks in advance for any help anyone can provide. I'm not finding anything else related.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Apr 17 14:59:01 bigip2 err tmm[14652]: 01220001:3: TCL error: /Production/rule_remove_and_insert_XFF_header - Operation not supported (line 1) invoked from within "HTTP::header insert X-Forwarded-For [IP::client_addr]"

do you have redirection logic in the configuration (e.g. HTTP::redirect, local traffic policy, etc)? is there a chance that traffic also hits the redirection?

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

In my case the issue was risen because we had more iRules, all starting with "when HTTP_REQUEST" (redirects and header field manipulation). Maybe your problem will be solved too, if you use a combined iRule

0