Forum Discussion

Preet_pk's avatar
Preet_pk
Icon for Cirrus rankCirrus
Jul 02, 2024

Convert Nginx rule to F5 irule

Hi Team,

I need some help in converting the below NGINX Rule to F5 iRule.

proxy_set_header Host $host; 
proxy_set_header X-Real-IP $remote_addr; 
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
proxy_set_header X-Forwarded-Proto $scheme; 
# WebSocket specific proxy_http_version 1.1; 
proxy_set_header Upgrade $http_upgrade; 
proxy_set_header Connection "upgrade"; 

 

2 Replies

  • Preet,

    Some of these will not have a direct translation because of the nuances of, and differences between, NGINX directives/variables and iRule commands.  But here is my best attempt at answering your question.

     

    proxy_set_header Host $host;

    because of the way the $host variable works in NGINX this could return one of (and in this order):

    1. the host value from the request line  <----  this would only be the case if this was a proxy-style request where the protocol and host were included in the request line
    2. the value of the Host header  <----  this wouldn't make any sense in the way it is used in your example as it would just set the Host header to the value it already had
    3. the server name matching a request (i.e. server/location directive that this request matched)  <---- this would rewrite the Host header with the server name it matched

    Equivalent irule commands would be, respectively:

    1. HTTP::header replace "host" [lindex [regexp -inline {http(?:s)?:\/\/(.*?)(?::.*)?\/} [HTTP::uri] ] 2]  <--- again this would only work if this was a proxy-style request.  Explanation:
      1. [lindex {some list} 2] return the second (2) item from a list
      2. [regexp -inline {regex} {string} ], match the provided regular expression against the string; -inline returns the matches and any capture groups as a list
      3. [HTTP::uri] returns the URI from the request line; in a proxy-style request this would include the protocol (http/https), host (www.host.com), and possibly port (:8080) as well as any path and query string (/myapp/login.html?user=bob)
    2. HTTP::header replace "host" [HTTP::host]   <---- Since the HTTP1.1 spec requires a Host header (and pretty much EVERYTHING is HTTP1.1 or higher), this is pointless as you are setting a header to the value it already has
    3. HTTP::header replace "host" [virtual name]. <---- there is no real iRule equivalent to the NGINX "server name" so the best I could come up with is IF you had named your virtual server whatever host name you wanted to include here you could get that name with the [virtual name] iRule command.

    proxy_set_header X-Real-IP $remote_addr;

       HTTP::header insert "X-Real-IP" [IP::client_addr]


    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 

        HTTP::header insert "X-Forwarded-For" [IP::client_addr]


    proxy_set_header X-Forwarded-Proto $scheme; 

       Typically, on a BIG-IP separate virtual servers are used for HTTP and HTTPS traffic.  There is no built in command to return the scheme.  However, there are multiple ways to infer if the connection was over http or https.  The most fool-proof way is to check the presence of a client SSL profile attached to the virtual server.

    set scheme http
    if { [PROFILE::exists clientssl] } {

        set scheme "https"

    }

    HTTP::header insert "X-Forwarded-Proto" $scheme


    # WebSocket specific proxy_http_version 1.1; 
    proxy_set_header Upgrade $http_upgrade;

        this doesn't appear to do anything because it is just setting the Upgrade header to the value of the Upgrade header


    proxy_set_header Connection "upgrade"; 

        HTTP::header replace Connection Upgrade

     

    Wrapping that all up into a single iRule:

    when HTTP_REQUEST {
      # proxy_set_header Host $host;
      HTTP::header replace "host" [lindex [regexp -inline {http(?:s)?:\/\/(.*?)(?::.*)?\/} [HTTP::uri] ] 2]
      # OR, depending on which you were trying to do
      HTTP::header replace "host" [virtual name]
    
      # proxy_set_header X-Real-IP $remote_addr;
      HTTP::header insert "X-Real-IP" [IP::client_addr]
    
      # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
      HTTP::header insert "X-Forwarded-For" [IP::client_addr]
    
      # proxy_set_header X-Forwarded-Proto $scheme;
      set scheme http
      if { [PROFILE::exists clientssl] } {
        set scheme "https"
      }
      HTTP::header insert "X-Forwarded-Proto" $scheme
    
      # proxy_set_header Connection "upgrade"; 
      HTTP::header replace Connection Upgrade
    }