Forum Discussion

Guillaume_Rouss's avatar
Guillaume_Rouss
Icon for Nimbostratus rankNimbostratus
Aug 19, 2020

logging original header value, before modification by HTTP profile

Hello.

 

The HTTP::header command in a irule returns the value of this header, at the time the irule is evaluated. As a consequence, any header set or modified by an HTTP profile, such as X-Forwarded-For, now has a value different from the original received request. I also tried HTTP::request, with the same result.

 

Is there any way to log the original value for this header ?

  • Hello Guillaume.

    Actually, the XFF headers insertion occurs when HTTP protocol is parsed, which means before HTTP_REQUEST event.

    Your only chance is to capture TCP::payload.

    when CLIENT_ACCEPTED {
        TCP::collect
    }
    when CLIENT_DATA {
        set LogString "Client [IP::client_addr]:[TCP::client_port]"
        log local0. "============================================="
        log local0. "$LogString (request_pre)"
        foreach rec [split [TCP::payload] "\r\n"] {
            if { $rec ne "" } {
                log local0. $rec
            }
        }
        TCP::release
        log local0. "============================================="
    }
    when HTTP_REQUEST {
       set LogString "$LogString -> [HTTP::host][HTTP::uri]"
       log local0. "============================================="
       log local0. "$LogString (request) - request: [HTTP::method]"
       foreach aHeader [HTTP::header names] {
          log local0. "$aHeader: [HTTP::header value $aHeader]"
       }
       log local0. "============================================="
    }
    when HTTP_REQUEST_RELEASE {
       log local0. "============================================="
       log local0. "$LogString (request_post) - request: [HTTP::method]"
       foreach aHeader [HTTP::header names] {
          log local0. "$aHeader: [HTTP::header value $aHeader]"
       }
       log local0. "============================================="
    }

    This an example:

    <CLIENT_DATA>: =============================================
    <CLIENT_DATA>: Client 10.130.40.41:53563 (request_pre)
    <CLIENT_DATA>: GET / HTTP/1.1
    <CLIENT_DATA>: User-Agent: curl/7.19.7
    <CLIENT_DATA>: Host: 10.130.40.50
    <CLIENT_DATA>: Accept: */*
    <CLIENT_DATA>: =============================================
     
    <HTTP_REQUEST>: =============================================
    <HTTP_REQUEST>: Client 10.130.40.41:53563 -> 10.130.40.50/ (request) - request: GET
    <HTTP_REQUEST>: User-Agent: curl/7.19.7
    <HTTP_REQUEST>: Host: 10.130.40.50
    <HTTP_REQUEST>: Accept: */*
    <HTTP_REQUEST>: X-Forwarded-For: 10.130.40.41
    <HTTP_REQUEST>: =============================================
     
    <HTTP_REQUEST_RELEASE>: =============================================
    <HTTP_REQUEST_RELEASE>: Client 10.130.40.41:53563 -> 10.130.40.50/ (request_post) - request: GET
    <HTTP_REQUEST_RELEASE>: User-Agent: curl/7.19.7
    <HTTP_REQUEST_RELEASE>: Host: 10.130.40.50
    <HTTP_REQUEST_RELEASE>: Accept: */*
    <HTTP_REQUEST_RELEASE>: X-Forwarded-For: 10.130.40.41
    <HTTP_REQUEST_RELEASE>: =============================================

    Take into account that if you use TLS, you should repeat the same but in CLIENT_SSL_DATA event.

    https://clouddocs.f5.com/api/irules/CLIENTSSL_DATA.html

    Regards,

    Dario.

  • Hello Guillaume.

    Actually, the XFF headers insertion occurs when HTTP protocol is parsed, which means before HTTP_REQUEST event.

    Your only chance is to capture TCP::payload.

    when CLIENT_ACCEPTED {
        TCP::collect
    }
    when CLIENT_DATA {
        set LogString "Client [IP::client_addr]:[TCP::client_port]"
        log local0. "============================================="
        log local0. "$LogString (request_pre)"
        foreach rec [split [TCP::payload] "\r\n"] {
            if { $rec ne "" } {
                log local0. $rec
            }
        }
        TCP::release
        log local0. "============================================="
    }
    when HTTP_REQUEST {
       set LogString "$LogString -> [HTTP::host][HTTP::uri]"
       log local0. "============================================="
       log local0. "$LogString (request) - request: [HTTP::method]"
       foreach aHeader [HTTP::header names] {
          log local0. "$aHeader: [HTTP::header value $aHeader]"
       }
       log local0. "============================================="
    }
    when HTTP_REQUEST_RELEASE {
       log local0. "============================================="
       log local0. "$LogString (request_post) - request: [HTTP::method]"
       foreach aHeader [HTTP::header names] {
          log local0. "$aHeader: [HTTP::header value $aHeader]"
       }
       log local0. "============================================="
    }

    This an example:

    <CLIENT_DATA>: =============================================
    <CLIENT_DATA>: Client 10.130.40.41:53563 (request_pre)
    <CLIENT_DATA>: GET / HTTP/1.1
    <CLIENT_DATA>: User-Agent: curl/7.19.7
    <CLIENT_DATA>: Host: 10.130.40.50
    <CLIENT_DATA>: Accept: */*
    <CLIENT_DATA>: =============================================
     
    <HTTP_REQUEST>: =============================================
    <HTTP_REQUEST>: Client 10.130.40.41:53563 -> 10.130.40.50/ (request) - request: GET
    <HTTP_REQUEST>: User-Agent: curl/7.19.7
    <HTTP_REQUEST>: Host: 10.130.40.50
    <HTTP_REQUEST>: Accept: */*
    <HTTP_REQUEST>: X-Forwarded-For: 10.130.40.41
    <HTTP_REQUEST>: =============================================
     
    <HTTP_REQUEST_RELEASE>: =============================================
    <HTTP_REQUEST_RELEASE>: Client 10.130.40.41:53563 -> 10.130.40.50/ (request_post) - request: GET
    <HTTP_REQUEST_RELEASE>: User-Agent: curl/7.19.7
    <HTTP_REQUEST_RELEASE>: Host: 10.130.40.50
    <HTTP_REQUEST_RELEASE>: Accept: */*
    <HTTP_REQUEST_RELEASE>: X-Forwarded-For: 10.130.40.41
    <HTTP_REQUEST_RELEASE>: =============================================

    Take into account that if you use TLS, you should repeat the same but in CLIENT_SSL_DATA event.

    https://clouddocs.f5.com/api/irules/CLIENTSSL_DATA.html

    Regards,

    Dario.

  • Thank for the details, It confirms there is no simple way at BigIP level. I'll just send modified header value, and take care of it later in log processing.

     

    Regards.

    • Dario_Garrido's avatar
      Dario_Garrido
      Icon for MVP rankMVP

      You are welcome. Don't forget to mark this answer above as 'the best' to help other people to find it ;-).

       

      Regards,

      Dario.