Web servers at times need client IP for security / logging purpose. Use of a proxy between client and server may hide this detail based on security policies. There are various methods available with Netscaler for client IP header insertion; but they work only if either the client device is directly sending the request or proxy is providing this data in HTTP header. But in secured environments generally proxies are not allowed to alter HTTP header. e.g. If you are using SRIP (Simple Routing Information Protocol), by design a proxy device will only send the packets and not view or modify application layer headers and so cannot insert a HTTP header containing actual client IP address in HTTP request send by proxy to Netscaler VIP.
We can configure proxy device to put client IP in to option field of TCP header. TCP option field is used if data offset (which specify header length of TCP packet) is greater than 5 byte. Option field typically contains
- Option-Kind : One byte in size it is the only mandatory field, indicates kind of option
- Option Length : One byte in size, optional element which gives length of the option field
- Option Data
For list of available option-kinds please refer : http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xml
Taking an example from such configured TCP packet
’1c’ – indicates Option-Kind
07 – indicates length of the Option filed in TCP header
01 – is version number inserted by used proxy
‘ cf ed 79 4f’ – indicates IP (18.104.22.168) in hex-decimal format.
In such scenario NetScaler receives the client IP in TCP options and is expected to insert it as a HTTP header for the backend server. Tricky job but this is where our AppExpert policies come to rescue and enable us to play around with TCP packets from headers to payload. You can use the advance policy expression to read the Client IP inserted in TCP option and then Rewrite action to insert it as HTTP header. Here is the expression details.
- CLIENT.TCP.OPTIONS.TYPE(<type>) returns the value of the TCP option whose kind is specified as the argument as a string of bytes in Big endian format
- <text>.GET_SIGNED32(<n>, <endianness>) Treats the text string returned by the prefix as a string of bytes, extracts 32 bits starting at byte offset n, and converts the extracted bit sequence to a 32-bit signed integer
- <number>.TYPECAST_IP_ADDRESS_AT converts the number to an IP address
For error handling one can use checks like
- CLIENT.TCP.OPTIONS.TYPE(0x1c).EXISTS which returns a Boolean stating weather the option-kind is set or not
- CLIENT.TCP.OPTIONS.TYPE(0x1c).GET_UNSIGNED8(0) == 1 which check the version set by proxy
This was a way to send and retrieve data using TCP option field. We can now use client IP with various policies in Netscaler. Stay tuned for second part of this blog on how to use it with NetScaler policies.