Forum Discussion

MarcoP's avatar
MarcoP
Icon for Nimbostratus rankNimbostratus
Jul 20, 2022

iRule with JSESSIONID including the server id with jvmRoute

Dears,

unfortunately I did not find a fitting post to my problem:

We have two or more servers they creating a JSESSIONID where the id of the server is added on the end like so:

 

7B0DE3926CF23C27DFF9C80BE604B009.serverID0
5C38A6262816E6E3A6BBB0B3ABB42D3A.serverID1

 

(we are using the -DjvmRoute=... on the tomcat)

Is it possible, that every JSESSIONID with the ending serverID0 is always routing to server 0 and serverID1 to server 1?

The rootcause is, that if the routing switches for a user, they logged in 3 days before, they has to loggin again, although there is a valid security context on tomcat available on the "right" server...

5 Replies

  • xuwen's avatar
    xuwen
    Icon for Cumulonimbus rankCumulonimbus

     

    # first create 3 pool,name is pool_node0, pool_node1, pool_default
    # pool_node0 member 10.1.1.10:80 monitor tcp
    
    # pool_node1 member 20.1.1.20:80 monitor tcp
    
    # pool_default member 10.1.1.10:80 20.1.1.20:80 monitor tcp
    
     
    
    iRuels code:
    
     
    
    when RULE_INIT {
    
      array set static::pool_array {
    
        0 pool_node0
    
        1 pool_node1
    
      }
    
    }
    
    when HTTP_REQUEST {
    
      if { [HTTP::cookie exists "JSESSIONID"] } {
    
        set node_x [findstr [HTTP::cookie "JSESSIONID"] "serverID" 8 1]
    
        log local0. "node_x is $node_x"
    
        if { [active_members [lindex [array get static::pool_array $node_x] 1]] == 0 } {
    
          pool pool_default
    
        } else {
    
          pool [lindex [array get static::pool_array $node_x] 1]
    
        }
    
      } else {
    
        pool pool_default
    
      }
    
    }

     

  • xuwen's avatar
    xuwen
    Icon for Cumulonimbus rankCumulonimbus

    PLAN B:

    Firstly, create 2 pool:

    pool_web member is 10.10.10.1:80 10.10.10.2:80

    pool_default is standby(its member is 20.20.20.1:80 20.20.20.2:80) when pool_web all members is down

    Dynamically add elements to the array according to pool member select

    # create pool_web member is  10.10.10.1:80 10.10.10.2:80
    # create pool_default is standby(its member is 20.20.20.1:80 20.20.20.2:80) when pool_web all members is down
    
    when RULE_INIT priority 500 {
        array set static::pool_array {}
    }
    when HTTP_RESPONSE priority 500 {
        set node_ip [IP::server_addr]
        set node_port [TCP::server_port]
        log local0. "node_ip is $node_ip, port is $node_port"
        if { [HTTP::cookie exists "JSESSIONID"] } {
            # serverID0,serverID1
            set node_x [findstr [HTTP::cookie "JSESSIONID"] "serverID" 8 1]
            log local0. "node_x is $node_x"
            # dynamic add element in array ,key is ID, value is pool member
            set static::pool_array($node_x) "$node_ip:$node_port"
            log local0. "response event pool array is [array get static::pool_array]"
        }
    }
    when HTTP_REQUEST priority 500 {
        if { [HTTP::cookie exists "JSESSIONID"] } {
            set server_x [findstr [HTTP::cookie "JSESSIONID"] "serverID" 8 1]
            log local0. "server_x is $server_x"
            if { [active_members pool_web] == 0 } {
                log local0. "exists cookie, select slave pool pool_default"
                pool pool_default
            } else {
                # 0 10.10.10.1:80
                # 1 10.10.10.2:80
                if { [array get static::pool_array $server_x] != "" } {
                    set mem_ip [getfield [lindex [array get static::pool_array $server_x] 1] ":" 1]
                    set mem_port [getfield [lindex [array get static::pool_array $server_x] 1] ":" 2]
                    if { [LB::status pool pool_web member $mem_ip $mem_port] eq "up" } {
                        pool pool_web member $mem_ip $mem_port
                    } else {
                        pool pool_web
                    }
                } else {
                    reject
                    log local0. "client send fake invalid cookie JSESSIONID!"
                }
            }
        } else {
            if { [active_members pool_web] == 0 } {
                pool pool_default
                log local0. "no cookie, select slave pool pool_default"
            } else {
                pool pool_web
            }
        }
        log local0. "request event pool array is [array get static::pool_array]"
    }

     

  • xuwen's avatar
    xuwen
    Icon for Cumulonimbus rankCumulonimbus

    plan C:

    Creating the universal persistence profile

    To create a universal persistence profile and reference the persistence iRule you created in the previous procedure, perform the following procedure:

    1. Log in to the Configuration utility.
    2. Navigate to Local Traffic > Profiles.
    3. From the Persistence menu, click Create.
    4. Type a name for the universal persistence profile.
    5. For Persistence, click Universal.
    6. For Configuration, select the iRule check box, then click the persistence iRule you created.
    7. Click Finished.

    iRules code:

     

     

    when HTTP_RESPONSE priority 500 {
        if { [HTTP::cookie exists "JSESSIONID"] } {
            # serverID0,serverID1, length is 9
            set node_x [findstr [HTTP::cookie "JSESSIONID"] "serverID" 0 9]
            log local0. "node_x is $node_x"
            # persist add uie, key is serverIDX, timeout is 1800s
            persist add uie $node_x 1800
        }
    }
    when HTTP_REQUEST priority 500 {
        if { [HTTP::cookie exists "JSESSIONID"] } {
            set server_x [findstr [HTTP::cookie "JSESSIONID"] "serverID" 0 9]
            set value [persist lookup uie $server_x]
            if { $value != "" } {
                persist uie $server_x
            }
        }
    }

     

     

  • I wrote this one a while ago (there is room for improvement with the array access):

    when RULE_INIT {
        array set static::srvid_node {
            node1 172.29.32.160
            node2 172.29.32.161
            node3 172.29.32.162
            node4 172.29.32.163
        }
        set static::debug_map_srvid 1
    }
    when HTTP_REQUEST {
        set original_request "[IP::client_addr]:[HTTP::method]:[HTTP::uri]:HTTP/[HTTP::version]"
        if {([HTTP::cookie exists JSESSIONID])} {
            set session_id [HTTP::cookie value JSESSIONID]
            set node_id [getfield ${session_id} . 2]
            set node_ip [getfield [array get static::srvid_node ${node_id}] " " 2]
            if {(${node_ip} ne "")} {
                if {(${static::debug_map_srvid} > 0)} { log local0. "info: valid header-cookie JSESSIONID found (${session_id}) in request (${original_request}); mapping to ${node_ip}" }
            } else {
                log local0. "error: broken header-cookie JSESSIONID found (${session_id}) in request (${original_request}); balancing to default pool ([LB::server pool])"
                pool [LB::server pool]
                return
            }
        } elseif {([findstr [HTTP::path] JSESSIONID 11] ne "")} {
            set session_id [findstr [HTTP::path] JSESSIONID 11]
            set node_id [getfield ${session_id} . 2]
            set node_ip [getfield [array get static::srvid_node ${node_id}] " " 2]
            if {(${node_ip} ne "") and (${static::debug_map_srvid} > 0)} {
                log local0. "info: valid url-cookie JSESSIONID found (${session_id}) in request (${original_request}); mapping to ${node_ip}"
            } else {
                log local0. "error: broken url-cookie JSESSIONID found (${session_id}) in request (${original_request}); balancing to default pool ([LB::server pool])"
                pool [LB::server pool]
                return
            }
        } else {
            if {(${static::debug_map_srvid} > 0)} { log local0. "info: no addressed node found in request (${original_request}); balancing to default pool ([LB::server pool])" }
            pool [LB::server pool]
            return
        }
        if {([LB::status pool [LB::server pool] member ${node_ip} 80] equals "down")} {
            log local0. "warning: addressed node (${node_ip}) in request (${original_request}) is unavailable; sending 503"
            HTTP::respond 503 noserver Server "test service" Connection Close Date "[clock format [clock seconds] -format {%a, %b %d %Y %H:%M:%S %Z} -gmt 1]"
            return
        } else {
            pool [LB::server pool] member ${node_ip}:80
            return
        }
    }
    
    when HTTP_RESPONSE {
        if {([HTTP::cookie exists JSESSIONID]) and ($static::debug_map_srvid > 0) and ([info exists original_request])} {
             log local0. "info: response cookie JSESSIONID ([HTTP::cookie value JSESSIONID]) found in response for request (${original_request})"
        }
    }
    
    when LB_FAILED {
        # Ausloesung des Events bei Nichtverfuegbarkeit innerhalb Monitoring Timeout
        if {${static::debug_map_srvid} > 0} {
             log local0. "error: selected server not available (${node_ip}:80) for request (${original_request}); sending 503"
        }
        HTTP::respond 503 noserver Server "test service" Connection Close Date "[clock format [clock seconds] -format {%a, %b %d %Y %H:%M:%S %Z} -gmt 1]"
        return
    }

     

  • MarcoP's avatar
    MarcoP
    Icon for Nimbostratus rankNimbostratus

    Many tanks so far for the suggestions - will check it with my IT guy 😄

    You are awsome!