Forum Discussion

mikey_webb's avatar
Dec 14, 2020

Custom response header to identify pool member - help

i would like to insert a response header for diags to identify which server handled the request

I have the below as a start

  1. when HTTP_RESPONSE {
  2.  
  3. HTTP::header insert SERVER_INFO "[IP::server_addr]:[TCP::server_port]"
  4. }

i need to have a map for the IPs to identify the server ie ip1 = server1, ip2=server2 - i know need class and datagroup but unsure how to do and how the above needs to change.

as always any help greatly appreciated

2 Replies

  • If I am interpreting your question correctly, I believe you are trying to insert an HTTP Server header into the response to the client based on matching the server's IP address and port to a datagroup entry that contains the associated server information. (In other words, you are not trying to send the server's actual IP address and service port.) If that is correct, then your solution is pretty straightforward.

     

    First, you will need a datagroup with the mappings. You can use a string datagroup type. For example:

    ltm data-group internal IP_Port_Server_Info_Mappings {
        records {
            172.16.20.1:80 {
                data "Server1 Info"
            }
            172.16.20.2:80 {
                data "Server2 Info"
            }
            172.16.20.3:80 {
                data "Server3 Info"
            }
        }
        type string
    }

    I used an internal datagroup in the example above, but you could just as easily use an external datagroup. (If you need help configuring an external datagroup, please check out this article: K73862425: Creating external data groups)

     

    You can use an iRule or Local Traffic Policy on the virtual server to do the header insertion. For the iRule, you could use something like this:

    ltm rule Insert_HTTP_Server_Header {
        when HTTP_RESPONSE {
            HTTP::header insert Server [ class match -value "[IP::server_addr]:[TCP::server_port]" equals IP_Port_Server_Info_Mappings ]
        }
    }

    Note the HTTP::header insert will insert the Server header regardless of whether a Server header is already present in the response from the server.

     

    If using a Local Traffic Policy:

    ltm policy Insert_HTTP_Server_Header {
        last-modified 2020-12-14:15:40:49
        requires { http }
        rules {
            Unconditionally_Insert_Server_Header {
                actions {
                    0 {
                        http-header
                        response
                        insert
                        name Server
                        value "tcl:[class match -value [IP::server_addr]:[TCP::server_port] equals IP_Port_Server_Info_Mappings]"
                    }
                }
            }
        }
        status published
        strategy first-match
    }

    In general, Local Traffic Policies achieve better performance than iRules.

     

    If you do want to simply insert the server's IP address and port as the HTTP Server header's value, then your code is pretty spot on:

    when HTTP_RESPONSE {
        HTTP::header insert Server "[IP::server_addr]:[TCP::server_port]"
    }

    Note that for either iRule or Local Traffic Policy solution, the virtual server will need an HTTP-type profile assigned first.

     

  • On the same lines,  , sometimes passing server details over header are considered sensitive information's. In that case you'd need to hash them before you insert it.

    when HTTP_RESPONSE {
    set hash [b64encode [md5 "[IP::server_addr]:[TCP::server_port]"]]    
    HTTP::header insert Server "$hash"
    }

    In case your server is 1.1.1.1:443, the header will have Server: 7NPef5jNbRYGxqSIJ/QBtQ== as hashed information.

    To confirm, with below command you can get the hash value.

    echo -n '1.1.1.1:443' | openssl dgst -md5 -binary | base64

    Note, hashing is one-way function, so this can't be done reverse way to get the IP:443.

    Use accordingly.