Forum Discussion

davelutz's avatar
davelutz
Icon for Nimbostratus rankNimbostratus
Nov 23, 2020

Send node FQDN as http header instead of virtual server FQDN

I have a situation were I need my virtual server to listen for test.example.com but when the F5 talks to the nodes it communicates with them as node1.example.com or node2.example.com.

 

So for user -> F5 as test.example.com then F5 -> nodes as node1/2.example.com

 

I assume I need to use a header rewrite but I am unsure how to do that when each node would have its own name.

Any help would be greatly appreciated.

7 Replies

  • If all you want to do is replace the HTTP Host header on the server-side request, you should be able do this with an iRule but not using BIG-IP configuration data alone.

    On the LB_SELECTED event, you can ask the system to return information about the pool member the server-side connection will target, including the name of the pool the member is in, along with the member's IP address and port. Unfortunately, it looks like the FQDN of the underlying node is not accessible from an iRule. However, if you can map an IP address to its associated FQDN, perhaps using a datagroup, then you can have the iRule grab the IP address of the selected member and then use it to obtain the FQDN. For example, here is a small datagroup I set up mapping three node IP addresses to their respective FQDN:

    ltm data-group internal node_addr_to_fqdn_mapping {
        records {
            172.16.20.1/32 {
                data wwa.f5trn.com
            }
            172.16.20.2/32 {
                data wwb.f5trn.com
            }
            172.16.20.3/32 {
                data wwc.f5trn.com
            }
        }
        type ip
    }

    And here is the iRule I used to replace the HTTP Host header:

    when LB_SELECTED {
        log local0. "HTTP Host header changed from [HTTP::host] to [class match -value [LB::server addr] equals node_addr_to_fqdn_mapping]"
        # Replace the HTTP host header with the node's FQDN as found in datagroup
        HTTP::header replace host [class match -value [LB::server addr] equals node_addr_to_fqdn_mapping]
    }

    I tested this on v14.1 using a small web application that we use in our customer-facing training environment, and it produced the following log messages. (I would remove the log command for use in production.)

    Nov 23 11:24:25 bigip4 info tmm1[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwa.f5trn.com
    Nov 23 15:29:34 bigip4 info tmm1[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwb.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwb.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwc.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwa.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm1[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwc.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm1[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwa.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm1[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwb.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwb.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwc.f5trn.com
    Nov 23 15:29:35 bigip4 info tmm1[9878]: Rule /Common/change_http_header <LB_SELECTED>: HTTP Host header changed from virt.f5trn.com to wwc.f5trn.com
    ...

    You get the idea...

    Although it's not the most elegant solution, it works, even if the connection is persisting rather than actually being load balanced.

  • So this is basically simple - as you say, you just rewrite the Host header. The question is how the BIG-IP knows what to rewrite it to. If it were me, i'd use a simple switch statement as a start and work out from there how to improve it. Ultimately i'd probably create an iApp so I had a nice GUI, but that's just me!

    when LB_SELECTED {
      switch -exact -- [LB::server name] {
        "server1" { HTTP::host "www.example1.com" }
        "server2" { HTTP::host "www.example2.com" }
      }
    }

    You'll also want to include some logging to start with, and error handling

    • crodriguez's avatar
      crodriguez
      Ret. Employee

      Nice! You beat me to the punch as I got distracted while preparing my response below. Note that [LB::server name] does not return the actual pool member or node name but rather a 3-element list containing the configuration name of the pool, the selected member's IP address, and service port. For example:

       

      /Common/fqdn_pool 172.16.20.1 80

      • PeteWhite's avatar
        PeteWhite
        Icon for Employee rankEmployee
        Your solution is more graceful, as with all things F5 you can do it in multiple ways. The only thing you should consider is if there is no match. Good point about LB::server
  • Thank you both for the replies, I will test them out in the morning and report back.

    I appreciate the quick responses,

  • Thank you for all your help, your solution did exactly what I needed.