Forum Discussion

Emad's avatar
Emad
Icon for Cirrostratus rankCirrostratus
May 18, 2016

FQDN Node with Route Domains

How can we add route domain in FQDN based nodes. In Address based node it can be added with %1 but how this will be done in FQDN based nodes.

 

7 Replies

  • Currently this is not supported with FQDN nodes, though it might happen if FQDN nodes are created in an administrative partition with a nonzero route domain (I have not tested this).

    There is an RFE open for this, tracked as

    ID522465
    . This will be implemented in a future release. If you'd like to indicate interest, which helps us prioritize RFEs, please open an SR with F5 Support referencing this ID and asking to be linked to it.

  • Here's my attempt at it...

    
     Rule Name:        MY_RD_FQDN_IRULE
     Rule Date:        01/07/2016
     Rule Version:     1.0
    
     Rule Description: This iRule is designed to lookup an IP for an FQDN and then use the IP for the serverside connection.
                       Simply edit the RULE_INIT variables to modify for your needs.  
                       Test before using in any environment. This rule is provided *as-is* without warranty or liability. 
       
     Rule History:     1.0 - 01/07/2016 - C.Spathas (Ardenta) - Initial Version inspired by DevCentral
                       https://devcentral.f5.com/questions/dynamic-pool-members-with-dns-resolution
    
    when RULE_INIT {
    
         Set some static variables and lists
        set static::MY_RD_FQDN_GBLVAR "www.google.com"
        set static::MY_RD_FQDN_ROUTE_DOMAIN_GBLVAR "%1"
        set static::MY_RD_FQDN_DNS_SRV_GBLST {8.8.8.8 8.8.4.4}
    
         Set debug logging on/off (0 for none, 1 for drop/deny/error and 2 for all logging)
        set static::MY_RD_FQDN_DEBUG_GBLVAR 2
    
    }
    
    when CLIENT_ACCEPTED {
    
         Select a DNS server from the list and sppend the Route Domain
        set DNS_SERVER_LCLVAR "[lindex $static::MY_RD_FQDN_DNS_SRV_GBLST [expr {int(rand()*[llength $static::MY_RD_FQDN_DNS_SRV_GBLST])}]]$static::MY_RD_FQDN_ROUTE_DOMAIN_GBLVAR"
    
         Debug Logging
        if {$static::MY_RD_FQDN_DEBUG_GBLVAR==2}{log local0. "DNS Server selected was $DNS_SERVER_LCLVAR"}
    
         Perform the Lookup and append the Route Domain
        set FQDN_IP_LCLVAR "[lindex [RESOLV::lookup @$DNS_SERVER_LCLVAR -a $static::MY_RD_FQDN_GBLVAR] 0]$static::MY_RD_FQDN_ROUTE_DOMAIN_GBLVAR"
    
         Debug Logging
        if {$static::MY_RD_FQDN_DEBUG_GBLVAR==2}{log local0. "The resolved IP for FQDN $static::MY_RD_FQDN_GBLVAR is $FQDN_IP_LCLVAR"}
    
         Perform some rudimentary error checking
        if { $FQDN_IP_LCLVAR ne "" } {
    
             Use the FQDN IP as the node if there is one
            node $FQDN_IP_LCLVAR
    
             Debug Logging 
            if {$static::MY_RD_FQDN_DEBUG_GBLVAR==2}{log local0. "The connection for [IP::client_addr]:[TCP::client_port] was sent to $FQDN_IP_LCLVAR"}
    
        } else {
    
             If there is no FQDN IP then drop the connection
            drop
    
             Debug Logging         
            if {$static::MY_RD_FQDN_DEBUG_GBLVAR>0}{log local0. "No IP was resolved."}
        }
    
    }
    
  • On v14.1.2 I tested creating an fqdn node in an administrative partition with a nonzero route domain and it gets created in Common aka route domain.

  • had to work on this with a customer of mine yesterday... we came up with the following irule to deal with it..

    when RULE_INIT {
        set static::TESTdebug 1
        set static::TESTfqdn_pool TEST_snf_uat_22_pool
    }
    
    when CLIENT_ACCEPTED {
        # Only apply this logic to TCP port 22 (SFTP)
        if { [TCP::local_port] == 22 } {
            # Check if client IP Address is in the Data Group (BBDMS_SNF_Parallel_DG)
            if { [class match [IP::client_addr] equals BBDMS_SNF_Parallel_DG] } {
    
                # Get the list of active pool members
                set members [active_members -list $static::TESTfqdn_pool]
                set member_count [llength $members]
    
                if { $member_count >= 1 } {
                    # Loop through pool members using a dynamic index
                    if {[info exists static::poolndx]} {
                        # Increment index and loop back if necessary
                        set static::poolndx [expr ($static::poolndx + 1) % $member_count]
                    } else {
                        # Initialize the pool index on the first use
                        set static::poolndx 0
                    }
                    # Select the member based on the index
                    set membaddr [lindex [lindex $members $static::poolndx] 0]
                    # Log selected member (for debugging)
                    if { $static::TESTdebug > 0 } {
                        log local0. "Selected pool member: $membaddr%1549 port 22"
                    }
                    # Assign traffic to the selected node
                    node $membaddr%1549 22
                } else {
                    # No active members in the pool; optionally handle this case
                    log local0. "No active members in pool $static::TESTfqdn_pool"
                    reject
                }
            } else {
                # Fallback to default pool
                pool CBM_SFTP.f5.com_22_pool
            }
        }
    }
    

     

  • adding v2 as we had some issues with persistence so we needed to add source pool member persistent to make it work 

    when RULE_INIT {
        # Debug level (set to 1 for logging, or 0 to disable logging)
        set static::sftpdebug_pool 1
        # Pool name
        set static::sftpfqdn_pool sftp_snf_uat_22_pool
    }
    
    when CLIENT_ACCEPTED {
        # Reject the traffic if the ROUTE::domain is not 1549
        if { [ROUTE::domain] != 1549 } {
            reject
            return
        }
    
        # Only apply this logic to TCP port 22 (SFTP)
        if { [TCP::local_port] == 22 } {
            # Check if the client IP address is in the Data Group (sftp_snf_parallel_dg)
            if { [class match [IP::client_addr] equals sftp_snf_parallel_dg] } {
                # Check if a node is already assigned for this source IP
                set nodemember [table lookup -subtable sftpsource:[IP::client_addr] "" ]
    
                if { $static::sftpdebug_pool > 0 } {
                    log local0. "Selected previous member for [IP::client_addr]: $nodemember"
                }
    
                if { $nodemember == "" } {
                    # Get the list of active pool members
                    set members [active_members -list $static::sftpfqdn_pool]
                    set member_count [llength $members]
    
                    if { $member_count > 0 } {
                        # Implement round-robin selection based on a dynamic index
                        if {[info exists static::poolndx]} {
                            # Increment index and loop back if necessary
                            set static::poolndx [expr {($static::poolndx + 1) % $member_count}]
                        } else {
                            # Initialize the pool index on first use
                            set static::poolndx 0
                        }
    
                        # Select a member based on the index
                        set membaddr [lindex [lindex $members $static::poolndx] 0]
    
                        # Log selected member (for debugging)
                        if { $static::sftpdebug_pool > 0 } {
                            log local0. "Selected pool member: $membaddr%1549 port 22 (round-robin)"
                        }
    
                        # Store the selected node in the session table
                        set nodemember "$membaddr%1549:22"
                        table set -subtable sftpsource:[IP::client_addr] $nodemember "" 180
    
                        # Send traffic to the selected node
                        node $nodemember
                    } else {
                        # No active members in the pool
                        log local0. "No active members in pool $static::sftpfqdn_pool"
                        reject
                        return
                    }
                }
    
                # If a previous assignment exists, route traffic to the assigned node
                if { $static::sftpdebug_pool > 0 } {
                    log local0. "Routing to previously assigned pool member: $nodemember"
                }
                node $nodemember
            } else {
                # Fallback to the default pool
                if { $static::sftpdebug_pool > 1 } {
                    log local0. "Client IP [IP::client_addr] not in data group. Using fallback pool."
                }
                pool sftp.f5.com_22_pool
            }
        }
    }