Forum Discussion

Kirk_Bauer_1018's avatar
Kirk_Bauer_1018
Icon for Nimbostratus rankNimbostratus
Sep 07, 2007

Selective SNAT rule, looking for suggestions

I wrote this rule for a customer who has 8 VLANs with real servers, and each pool may have servers from multiple VLANs. In addition sometimes the "client" comes from one of the VLANs as well, so I needed the ability to SNAT only when the client is in the same network as the real server. I am using this:

 

 

when LB_SELECTED {

 

if { [IP::addr [IP::remote_addr] equals [LB::server addr]/22] } {

 

snat automap

 

}

 

}

 

 

This can be associated with all virtual servers and only has an effect when the real server chosen is in the same subnet as the client. It also works fine when pool members are in varying subnets.

 

 

My only issue is that I had to hard-code the netmask of /22. Fortunately in this case all of their VLANs have the same subnet mask, but is there a way to programmatically determine the subnet for the VLAN that a particular real server is on?

4 Replies

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    As far as I know there's no way to programmatically read this information. You could always build a class with associations (a list of which IPs are in which VLANs, etc.)

     

     

    Colin
  • This is more or less the approach I have taken. I wanted to make the rule itself as portable as possible, and the best way I could think to do this was to use the VLAN tags as a reference to a data group that contained a network definition. It's a little bit convoluted logically, but seems to work just like I would expect. At the moment there is no logic for handling circumstances where more than one subnet is being routed on the same VLAN, but that is not applicable in my environment so the less code to execute the better.

     

     

    Also, I've elected to SNAT using the VIP address itself rather than use automap as that will give a better indication in the webserver logs whether the connection was related to an LTM monitor or whether the client was actually SNAT'ed. Anyway here is the rule:

     

     

     

     

    when RULE_INIT {
     This rule enables SNAT for client connections that originate on the same VLAN as
     the currently selected LB server. It assumes that a data group has been created for
     each VLAN on which it will be used - if an applicable data group is not available for
     a given VLAN, no SNATing will take place. Data groups should be named like so:
     vlan_local_ - where  is the VLAN's tag id, i.e "vlan_local_1234"
     The contents of the data group should contain an associated network definition:
     class vlan_local_1234  {
     network 10.9.8.0 mask 255.255.255.0
     }
    }
    when LB_SELECTED {
    set vlandg "::vlan_local_[LINK::vlan_id]"
    catch {
    if { [matchclass [LB::server addr]  equals  [set $vlandg]] } {
    snat [IP::local_addr]
    }
    }
    }

     

     

    And here is a debug version of the rule if you want to watch the LTM logs to make sure it's actually working:

     

     

    when RULE_INIT {
     This rule enables SNAT for client connections that originate on the same VLAN as
     the currently selected LB server. It assumes that a data group has been created for
     each VLAN on which it will be used - if an applicable data group is not available for
     a given VLAN, no SNATing will take place. Data groups should be named like so:
     vlan_local_ - where  is the VLAN's tag id, i.e "vlan_local_1234"
     The contents of the data group should contain an associated network definition:
     class vlan_local_1234  {
     network 10.9.8.0 mask 255.255.255.0
     }
    }
    when LB_SELECTED {
    set snatstatus "FALSE"
    set vlandg "::vlan_local_[LINK::vlan_id]"
    catch {
    if { [ matchclass [ LB::server addr ]  equals  [  set $vlandg ] ] } {
    snat [IP::local_addr]
    set snatstatus "TRUE"
    }
    }
    log local0. "SNAT: $snatstatus, CLIENT: [IP::client_addr] , SERVER: [LB::server addr] , VIRTUAL: [virtual name], VLAN: [LINK::vlan_id], VIP: [IP::local_addr]"
    }

     

     

    Thanks,

     

    Nathan
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Also, I've elected to SNAT using the VIP address itself rather than use automap as that will give a better indication in the webserver logs whether the connection was related to an LTM monitor or whether the client was actually SNAT'ed.

     

     

    Hi Nathan -

     

     

    I like your "SNAT to local VS address" approach, will probably use that in future, but just thought I'd clarify one minor thing: If you are running a redundant pair, all monitors will be sourced from the non-floating selfIPs, while SNAT automap will only use the floating ones, so you already have some natural separation there...

     

     

    Thanks for the contrib!

     

    /deb