Forum Discussion

Dan_Deming_1935's avatar
Dan_Deming_1935
Icon for Nimbostratus rankNimbostratus
Aug 18, 2006

How do I insert LB's IP with an irule?

We have 2 F5 Big IP units set up in front of 3 web servers running Apache 1.3. We're using the Type: Standard, Protocol: TCP and HTTP Profile: HTTP settings.

In our Apache logs, we want to include the IP address of the client, the IP of the server and the IP of the F5 unit. I was able to set up this irule to get the first 2:


when HTTP_REQUEST {
  HTTP::header insert "Remote-Addr" [IP::remote_addr]
  HTTP::header insert "Local-Addr" [IP::local_addr]
  }

Adding IP::client_addr gives the same value as local_addr, and trying to use IP::server_addr actually breaks the web page: a Page cannot be displayed error is shown. I know I can hardcode in different values in the irule:


HTTP::header insert "LB" LB1

However, since we want to sync both LBs and have the exact same config on both machines, this isn't feasible. I spoke with customer support who said they knew of no unique identifier I could use, and no way to get the LB's IP. Is there any way to get this information and put it in a header? Can you use envirnonment variables in a header, so I can print the $hostname to the header?

Any help would be greatly appreciated. Thanks.

10 Replies

  • Which IP of the BIG-IP are you looking at inserting? The Management port, the IP of the virtual, or the internal gateway address that is used to connect to your backend servers?

    The values of IP::client_addr, IP::local_addr, IP::remote_addr, and IP::server_addr have different values depending on the event they are accessed in.

    In the HTTP_REQUEST event, there is no server side connection so think of this as the first half of the connection where the client is connecting to the virtual. In this context the values are the following

    IP::client_addr - The address of the connecting client

    IP::local_addr - The address of the virtual the client is connecting to

    IP::remote_addr - The address of the connecting client (same as client_addr)

    IP::server_addr - Not valid as there is no serverside connection.

    If you want the server address of the pool member you are connecting to, you can access this in the HTTP_REQUEST_SEND event. This is raised after a serverside connection has been established and before the request is sent. In this event, the values are:

    IP::client_addr - The address of the connecting client

    IP::local_addr - The address of the connecting client (same as client_addr)

    IP::remote_addr - The address of the pool member

    IP::server_addr - The address of the pool member

    So, this rule should do what you want

    when HTTP_REQUEST {
      set bigip_addr [IP::local_addr]
    }
    when HTTP_REQUEST_SEND {
      clientside {
        HTTP::header insert "Client-Addr" [IP::client_addr]
        HTTP::header insert "BIGIP-Addr" $bigip_addr
        HTTP::header insert "Node-Addr" [IP::remote_addr]
      }
    }

    I don't believe you have access to the virtual address in the HTTP_REQUEST_SEND event so you'll have to store it in a variable from the HTTP_REQUEST event.

    Also, you'll need to enclose the HTTP::header commands in a clientside context within the HTTP_REQUEST_SEND event which might not be obvious.

    Hopefully this will give you enough to get you going.

    -Joe
  • Nice trick with clientside. I was getting a context error when trying to insert a header in the HTTP_REQUEST_SEND event.

     

     

    Why is it necessary to specify the clientside context for a header insert in the HTTP_REQUEST_SEND event? I believe this event is in the serverside context, but shouldn't you still be able to insert a header? Or can you only insert a header in the serverside context on HTTP_RESPONSE?

     

     

    Thanks,

     

    Aaron
  • It has to do with which context owns the data and in the case of http requests, it's the clientside context. The HTTP_REQUEST_SEND event lives in the serverside context so any commands you issue with be processed there without the clientside override.

     

     

    I'll have to check about the HTTP_RESPONSE...

     

     

    -Joe
  • I still can't get the Big IP's IP address to be passed on.

     

     

    I can get 3 of the 4 IP's involved: client's IP, Server Internal IP and Server External IP, but no matter what I try, I can't for the life of me get the Big IP's IP.

     

     

    The only time I've ever managed to get it was when we were using the Performance profile, which we found gave an inaccuarate value for REMOTE_ADDR. But in the normal HTTP setting nothing I try will let me see this value. Here's the variation on Joe's code which I've tried, which returns the same 3 IPs but not the one I need:

     

     

    
    when HTTP_REQUEST {
      set bigip_addr1 [IP::local_addr]
      set bigip_addr2 [IP::remote_addr]
      set bigip_addr3 [IP::client_addr]
    }
    when HTTP_REQUEST_SEND {
      set serverip_addr1 [IP::server_addr]
      set remoteip_addr2 [IP::remote_addr]
      set clientip_addr3 [IP::client_addr]
      clientside {
        HTTP::header insert "Client-Addr" [IP::client_addr]
        HTTP::header insert "Server-Addr" [IP::server_addr]
        HTTP::header insert "Node-Addr" [IP::remote_addr]
        HTTP::header insert "Local-Addr" [IP::local_addr]
        HTTP::header insert "BIGIP-Server-Addr" $serverip_addr1
        HTTP::header insert "BIGIP-Remote-Addr" $remoteip_addr2
        HTTP::header insert "BIGIP-client-Addr" $clientip_addr3
        HTTP::header insert "BIGIP1" $bigip_addr1
        HTTP::header insert "BIGIP2" $bigip_addr2
        HTTP::header insert "BIGIP3" $bigip_addr3
      }
    }

     

     

    Any other suggestions?
  • I think if you use [IP::local_addr] in the HTTP_REQUEST_SEND event it should get you the SNAT or source IP the BIG-IP will use to source the traffic to the node.

     

     

    It should be the same between both units though...

     

     

    Aaron
  • To clarify...

    HTTP_REQUEST_SEND is in the server side context as it's when the BIG-IP is sending the request to the server. So if you use [IP::local_addr] in HTTP_REQUEST_SEND it should give you the source IP the BIG-IP will use.

    In the last example you posted, you're using [IP::local_addr], but specifying the clientside context. So that should equate to the VIP address (the address local to the VIP on the clientside connection).

    So you should be able to use this:

    
    ...
    when HTTP_REQUEST_SEND {
       set bigip_source_to_node [IP::local_addr]
    ...
       clientside {
          HTTP::header insert "Source_to_node" $bigip_source_to_node
    ...
       }
    }
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Unfortunately, we don't have a mechanism for accessing the BIGIP's mgmt IP address nor any of the Self IP's.

     

     

    Your best bet would probably be to use an external class/data group. The class would reference a file on the BIGIP that could contain the BIGIP's IP address and then you could reference that in the rule.

     

     

    Here's the steps I would do:

     

    a) create an external class called bigip_address and have it reference the file /config/bigip_address.txt.

     

    b) create a script that grep's out the bigip's mgmt address from bigip_base.conf or from 'ifconfig eth0' and writes it to /config/bigip_address.txt

     

    c) Use $::bigip_address to get this value in your rule.

     

     

    The only trick is to make sure the script gets run if the configuration is changed (which I would assume should not really happen that often).

     

     

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Hoolio: I'm assuming snat must not be enabled, and that's why IP::local_addr is reflecting the client's IP address in HTTP_REQUEST_SEND...
  • unRuleY,

     

     

    Thanks for your reply. All I really care about is being able to log which Load Balancer a request went through, so I'm fine with using 'LB1' / 'LB2' instead of the actual IP addresses. I made 2 text files with these names on each of my Big IPS. Now how do I reference the contents of these files?

     

     

    The admin panel rejects the following code as invalid. I'm obviously not setting the class correctly and I'm not sure if this will even pull in the contents of the file.

     

     

    
    class whichlb {
       "/config/whichlb.txt"
    }
    when HTTP_REQUEST {
      HTTP::header insert "Remote-Addr" [IP::remote_addr]
      HTTP::header insert "Local-Addr" [IP::local_addr]
      HTTP::header insert "LB" $::whichlb
      }

     

     

    Please let me know what I should do to get at the contents of this file. Thanks again for your help.

     

     

    -Dan
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    I'm assuming your not defining the class in the iRule...

    When you create the Datagroup from the GUI, you will want to define it's type as "(External File)". The screen will then update to allow you to specify the path/filename and then select the File Contents type (I assume you'd want string).

    Your bigip.conf will then contain a definition like so:

    class whichlb {
       type string
       filename "/config/whichlb.txt"
    }

    The file is then automatically read into the class variable $::whichlb. HTH!