Forum Discussion

Hamza_derbali's avatar
Hamza_derbali
Icon for Altostratus rankAltostratus
Sep 30, 2024

Converting Citrix NetScaler Transform Policy to F5 BIG-IP LTM

Hello everyone,

I’m currently migrating from Citrix NetScaler to F5 BIG-IP LTM and would appreciate your help in converting the following transform policy:

 

add transform profile x_transform_profile add transform policy x_policy true x_transform_profile

add transform action x_action x_transform_profile 10

set transform action x_action -priority 10 -reqUrlFrom "example.com/(.*)" -reqUrlInto "local.com/$1" -resUrlFrom "local.com/(.*)" -resUrlInto "example.com/$1" -cookieDomainFrom example.com -cookieDomainInto example.com

 

Thank you in advance for your assistance.

Best regards,

  • This seems like a good gen AI task, and it's seemed to output a realistic answer. You'll have to test this of course, but it should get you close.

     

    Me <explain the task>.

     

    GPT-4o:

    Let's break down the transform rule and explain it from the perspective of HTTP RFC 2616, which defines the HTTP/1.1 protocol.

    ### Transform Profile and Policy

    1. **Transform Profile and Policy Creation:**
       - `add transform profile x_transform_profile`
       - `add transform policy x_policy true x_transform_profile`

       This part creates a transform profile named `x_transform_profile` and a transform policy named `x_policy` that is always true (`true` condition). The policy is associated with the transform profile `x_transform_profile`.

    ### Transform Action

    2. **Adding and Setting Transform Action:**
       - `add transform action x_action x_transform_profile 10`
       - `set transform action x_action -priority 10 -reqUrlFrom "example.com/(.*)" -reqUrlInto "local.com/$1" -resUrlFrom "local.com/(.*)" -resUrlInto "example.com/$1" -cookieDomainFrom example.com -cookieDomainInto example.com`

       This part adds a transform action named `x_action` to the transform profile `x_transform_profile` with a priority of 10. Then, it sets the details of the transform action. Let's break down these details:

    ### URL Transformation

    3. **Request URL Transformation:**
       - `-reqUrlFrom "example.com/(.*)" -reqUrlInto "local.com/$1"`

       This rule states that for incoming HTTP requests, any URL matching the pattern `example.com/(.*)` will be transformed into `local.com/$1`. The `(.*)` is a regular expression that matches any sequence of characters, and `$1` refers to the first captured group in the regular expression.

       - For example, if the incoming request URL is `http://example.com/path/to/resource`, it will be transformed into `http://local.com/path/to/resource`.

    4. **Response URL Transformation:**
       - `-resUrlFrom "local.com/(.*)" -resUrlInto "example.com/$1"`

       This rule states that for outgoing HTTP responses, any URL matching the pattern `local.com/(.*)` will be transformed into `example.com/$1`.

       - For example, if the outgoing response URL is `http://local.com/path/to/resource`, it will be transformed into `http://example.com/path/to/resource`.

    ### Cookie Domain Transformation

    5. **Cookie Domain Transformation:**
       - `-cookieDomainFrom example.com -cookieDomainInto example.com`

       This rule specifies that cookies with the domain `example.com` should keep their domain as `example.com`. This seems redundant in this context, as it doesn't appear to change the cookie domain, but it might be part of a larger set of rules or a template where domains could vary.

    ### Summary

    From an HTTP RFC 2616 perspective, this transform rule effectively:

    - Modifies incoming request URLs from the format `http://example.com/...` to `http://local.com/...`.
    - Modifies outgoing response URLs from the format `http://local.com/...` back to `http://example.com/...`.
    - Ensures that cookies with the domain `example.com` remain unchanged.

    This transformation can be useful in scenarios where a reverse proxy or load balancer is used to internally route requests to a different domain (`local.com`) while keeping the external-facing domain (`example.com`) consistent for the client. It ensures that users interacting with `example.com` see URLs and cookies that match this domain, even though the backend systems see and handle `local.com` URLs.

     

    ---------------

    me:

    Now we understand the policy. Take off your Netscaler hat and put on a BIG-IP hat and you are now an experienced F5 iRules network administrator. 
    Write F5 BIG-IP iRules to implement the same thing as the Netscaler rules above.

    ---------------

    GPT-4o:

    We'll create an iRule that modifies the request URLs from example.com to local.com and the response URLs from local.com back to example.com. We'll also ensure that cookies with the domain example.com remain unchanged.

    when HTTP_REQUEST {
        # Transform incoming request URLs
        if { [HTTP::host] equals "example.com" } {
            set new_url [string map {"example.com" "local.com"} [HTTP::uri]]
            HTTP::uri $new_url
        }
    }
    
    when HTTP_RESPONSE {
        # Transform outgoing response URLs
        if { [HTTP::header "Location"] ne "" } {
            set location_header [HTTP::header "Location"]
            if { $location_header contains "local.com" } {
                set new_location [string map {"local.com" "example.com"} $location_header]
                HTTP::header replace "Location" $new_location
            }
        }
    
        # Ensure cookies with the domain example.com remain unchanged
        foreach cookie [HTTP::cookie names] {
            if { [HTTP::cookie domain $cookie] equals "example.com" } {
                HTTP::cookie domain $cookie "example.com"
            }
        }
    }

     

    Explanation

    1. HTTP_REQUEST Event:
      • The HTTP_REQUEST event is triggered when an HTTP request is received.
      • We check if the Host header equals example.com.
      • If it does, we modify the request URI by replacing example.com with local.com.
      • The HTTP::uri command is used to set the new request URI.
    2. HTTP_RESPONSE Event:
      • The HTTP_RESPONSE event is triggered when an HTTP response is being sent.
      • We check if the Location header is present and contains local.com.
      • If it does, we replace local.com with example.com in the Location header.
      • The HTTP::header replace command is used to set the new Location header.
    3. Cookie Domain Transformation:
      • We iterate over all cookies in the response.
      • If a cookie has the domain example.com, we ensure its domain remains example.com using the HTTP::cookie domain command.

     

  • This seems like a good gen AI task, and it's seemed to output a realistic answer. You'll have to test this of course, but it should get you close.

     

    Me <explain the task>.

     

    GPT-4o:

    Let's break down the transform rule and explain it from the perspective of HTTP RFC 2616, which defines the HTTP/1.1 protocol.

    ### Transform Profile and Policy

    1. **Transform Profile and Policy Creation:**
       - `add transform profile x_transform_profile`
       - `add transform policy x_policy true x_transform_profile`

       This part creates a transform profile named `x_transform_profile` and a transform policy named `x_policy` that is always true (`true` condition). The policy is associated with the transform profile `x_transform_profile`.

    ### Transform Action

    2. **Adding and Setting Transform Action:**
       - `add transform action x_action x_transform_profile 10`
       - `set transform action x_action -priority 10 -reqUrlFrom "example.com/(.*)" -reqUrlInto "local.com/$1" -resUrlFrom "local.com/(.*)" -resUrlInto "example.com/$1" -cookieDomainFrom example.com -cookieDomainInto example.com`

       This part adds a transform action named `x_action` to the transform profile `x_transform_profile` with a priority of 10. Then, it sets the details of the transform action. Let's break down these details:

    ### URL Transformation

    3. **Request URL Transformation:**
       - `-reqUrlFrom "example.com/(.*)" -reqUrlInto "local.com/$1"`

       This rule states that for incoming HTTP requests, any URL matching the pattern `example.com/(.*)` will be transformed into `local.com/$1`. The `(.*)` is a regular expression that matches any sequence of characters, and `$1` refers to the first captured group in the regular expression.

       - For example, if the incoming request URL is `http://example.com/path/to/resource`, it will be transformed into `http://local.com/path/to/resource`.

    4. **Response URL Transformation:**
       - `-resUrlFrom "local.com/(.*)" -resUrlInto "example.com/$1"`

       This rule states that for outgoing HTTP responses, any URL matching the pattern `local.com/(.*)` will be transformed into `example.com/$1`.

       - For example, if the outgoing response URL is `http://local.com/path/to/resource`, it will be transformed into `http://example.com/path/to/resource`.

    ### Cookie Domain Transformation

    5. **Cookie Domain Transformation:**
       - `-cookieDomainFrom example.com -cookieDomainInto example.com`

       This rule specifies that cookies with the domain `example.com` should keep their domain as `example.com`. This seems redundant in this context, as it doesn't appear to change the cookie domain, but it might be part of a larger set of rules or a template where domains could vary.

    ### Summary

    From an HTTP RFC 2616 perspective, this transform rule effectively:

    - Modifies incoming request URLs from the format `http://example.com/...` to `http://local.com/...`.
    - Modifies outgoing response URLs from the format `http://local.com/...` back to `http://example.com/...`.
    - Ensures that cookies with the domain `example.com` remain unchanged.

    This transformation can be useful in scenarios where a reverse proxy or load balancer is used to internally route requests to a different domain (`local.com`) while keeping the external-facing domain (`example.com`) consistent for the client. It ensures that users interacting with `example.com` see URLs and cookies that match this domain, even though the backend systems see and handle `local.com` URLs.

     

    ---------------

    me:

    Now we understand the policy. Take off your Netscaler hat and put on a BIG-IP hat and you are now an experienced F5 iRules network administrator. 
    Write F5 BIG-IP iRules to implement the same thing as the Netscaler rules above.

    ---------------

    GPT-4o:

    We'll create an iRule that modifies the request URLs from example.com to local.com and the response URLs from local.com back to example.com. We'll also ensure that cookies with the domain example.com remain unchanged.

    when HTTP_REQUEST {
        # Transform incoming request URLs
        if { [HTTP::host] equals "example.com" } {
            set new_url [string map {"example.com" "local.com"} [HTTP::uri]]
            HTTP::uri $new_url
        }
    }
    
    when HTTP_RESPONSE {
        # Transform outgoing response URLs
        if { [HTTP::header "Location"] ne "" } {
            set location_header [HTTP::header "Location"]
            if { $location_header contains "local.com" } {
                set new_location [string map {"local.com" "example.com"} $location_header]
                HTTP::header replace "Location" $new_location
            }
        }
    
        # Ensure cookies with the domain example.com remain unchanged
        foreach cookie [HTTP::cookie names] {
            if { [HTTP::cookie domain $cookie] equals "example.com" } {
                HTTP::cookie domain $cookie "example.com"
            }
        }
    }

     

    Explanation

    1. HTTP_REQUEST Event:
      • The HTTP_REQUEST event is triggered when an HTTP request is received.
      • We check if the Host header equals example.com.
      • If it does, we modify the request URI by replacing example.com with local.com.
      • The HTTP::uri command is used to set the new request URI.
    2. HTTP_RESPONSE Event:
      • The HTTP_RESPONSE event is triggered when an HTTP response is being sent.
      • We check if the Location header is present and contains local.com.
      • If it does, we replace local.com with example.com in the Location header.
      • The HTTP::header replace command is used to set the new Location header.
    3. Cookie Domain Transformation:
      • We iterate over all cookies in the response.
      • If a cookie has the domain example.com, we ensure its domain remains example.com using the HTTP::cookie domain command.

     

    • Hamza_derbali's avatar
      Hamza_derbali
      Icon for Altostratus rankAltostratus

      Thank you, Lucas_Thompson , for the detailed answer. Now, if I enable the "-onlyTransformAbsURLinBody ON" option in the transformation profile, do I also need to use a stream profile for both the request and the response? From my understanding, this option inspects the body of the response as well.

       

      • Lucas_Thompson's avatar
        Lucas_Thompson
        Icon for Employee rankEmployee

        I asked GPT-4o this question about Netscaler transform rules operating in the HTTP body, but it seemed certain that they only operate on headers and ignore the body. 

        The name of that option seems to contradict this though, so you'll probably have to do some testing or talk to a Netscaler expert.

  • Hiii Hamza

     

    if i understand the policy of Citrix 

    Requests to example.com are internally redirected to local.com, but the client continues to see example.com as the domain. Similarly, responses from local.com are transformed to appear as if they are coming from example.com. The cookies retain the original domain example.com, ensuring that clients do not experience any inconsistencies when accessing the service.

    you have 2 ways, iRule or policy

     

    example of iRule

    when HTTP_REQUEST {
        if {[HTTP::host] contains "example.com"} {
            HTTP::header replace Host "local.com"
            set new_uri [string map {"example.com" "local.com"} [HTTP::uri]]
            HTTP::uri $new_uri
        }
    }

    when HTTP_RESPONSE {
        if {[HTTP::header value "Location"] contains "local.com"} {
            set new_location [string map {"local.com" "example.com"} [HTTP::header value Location]]
            HTTP::header replace Location $new_location
        }

        if {[HTTP::header exists "Set-Cookie"] && [HTTP::header value "Set-Cookie"] contains "local.com"} {
            set new_cookie [string map {"local.com" "example.com"} [HTTP::header value "Set-Cookie"]]
            HTTP::header replace "Set-Cookie" $new_cookie
        }
    }