Forum Discussion
Rob_78590
Nimbostratus
Aug 25, 2009iRule for SNAT for Host IPs & Supernets based on specific customer
Hi everyone! We currently have an iRule setup to SNAT to a particular IP depending on which customer it is. We specify the customer's host address in the Data Group List and associate it to our IP that we would like to SNAT to. The iRule listed below currently works for host IPs, however, it does not support Supernets. Does anyone know how to modify the below iRule to also include Supernets for customers who may have a large block of addresses?
when CLIENT_ACCEPTED {
set syn_snat [findclass [IP::local_addr] $::syniverse_snat " "]
if { $syn_snat ne ""} {
snat $syn_snat
}
}
9 Replies
- The_Bhattman
Nimbostratus
Can you post the structure of the datagroup?
CB - hoolio
Cirrostratus
I'd guess the current format is just a host and the corresponding SNAT IP:
client IP | SNAT IP
1.1.1.1 2.2.2.2
Unfortunately, there isn't a simple way to do subnet evaluations against a two-field datagroup. Normally you could use matchclass to evaluate a client IP or subnet against a datagroup of a type "address". But that doesn't allow you to easily configure a corresponding SNAT address. You could loop through the datagroup as a TCL list, use IP::addr (Click here) to evaluate the client IP against the subnet (in CIDR format) and then get the corresponding SNAT IP. It wouldn't be as efficient as using a native class querying command line matchclass, but it should provide the functionality.
So the class would be a string class with this format:
1.1.1.0/24 2.2.2.2
3.1.1.0/20 3.3.3.3
And you could use a rule like this:when CLIENT_ACCEPTED { log local0. "[IP::client_addr]:[TCP::client_port]: New connection. Using class: $::ip_snat_class" Loop through each line in the datagroup foreach line $::ip_snat_class { Log the current line by field log local0. "\$line: $line, IP: [lindex $line 0], SNAT: [lindex $line 1]" Check if the client IP equals the current line's subnet if {[IP::addr [client_addr] equals [lindex $line 0]]}{ log local0. "[IP::client_addr]:[TCP::client_port]: Matched [lindex $line 0], using SNAT [lindex $line 1]" Use the SNAT IP snat [lindex $line 1] Exit the loop as we've found a match break } } }
Which logs this:
: 1.2.2.3:37646: New connection. Using class: {1.2.0.0/16 4.4.4.4} {1.1.1.0/24 2.2.2.2} {3.4.5.0/24 3.3.3.3}
: $line: 1.2.0.0/16 4.4.4.4, IP: 1.2.0.0/16, SNAT: 4.4.4.4
: 1.2.2.3:37646: Matched 1.2.0.0/16, using SNAT 4.4.4.4
Aaron - Rob_78590
Nimbostratus
Hi Aaron (Hoolio),
Thanks for the reply. Yes, the current format is as follows:
client IP | SNAT IP
1.1.1.1 2.2.2.2
So, if I understand correctly, we can use the rule you recommended to specify the network & mask in the Data Group List and then specify the SNAT IP, right? If yes, then by using your iRule, I assume this would support host routes, by adding a /32, in addition to a range of addresses depending on the mask. Am I thinking correctly?
Thanks,
Rob - hoolio
Cirrostratus
Hi Rob,
Yep, I expect host entries specified with a /32 mask would work fine. Though just specifying the IP address should work too with IP::addr. The class could use either the first or second line's format:
Subnet | SNAT IP
1.1.1.1/32 2.2.2.2
1.1.1.1 2.2.2.2
3.3.3.0/24 4.4.4.4
The example I posted doesn't actually SNAT the connection, but you can add that in using 'snat [lindex $line 1]' after the log statement. If you are able to test this please reply back with the results. We can then add this as an example to the IP::addr wiki page and/or the codeshare.
Thanks,
Aaron - Rob_78590
Nimbostratus
Hi Aaron,
Wouldn't it be easier to just modify my current iRule by replacing [IP::local_addr] with [IP::addr]? By doing that, my iRule would be as follows:
when CLIENT_ACCEPTED {
set syn_snat [findclass [IP::addr] $::my_snat " "]
if { $syn_snat ne ""} {
snat $syn_snat
}
}
In my Data Group List called "my_snat", I would specify the various formats that we previously discussed. This should provide the results I need, right? - hoolio
Cirrostratus
I don't think so. The IP::addr command can be used to evaluate whether an IP address or subnet equals another IP address or subnet.
You couldn't use it in combination with findclass. But give it a try if you feel like it. I assume you'll get a parser error when trying to save the rule.
Aaron - Rob_78590
Nimbostratus
Hi Aaron,
I'll give your iRule a try. I'll let you know what the results are. For the Data Group List, I just want to confirm that the string your using is arbitrarily called "ip_snat_class", right?
Also, you stated that, in order to SNAT, I would have to add the syntax 'snat [lindex $line 1]' after the log statement. However, there are a couple of log statements, so I'm not exactly sure how it would be placed in the iRule. Just to make sure I do it correcty, can you rewrite the iRule to include the syntax 'snat [lindex $line 1]' after the log statement?
Thanks,
Rob - hoolio
Cirrostratus
Hi Rob,
Yeah, you can name the datagroup/class anything you want. Just update the iRule reference to the class.
I edited the post above to include the snat command. It's just before the break statement to exit the foreach loop after a match is found in the datagroup. Hope that makes sense.
Thanks,
Aaron - Rob_78590
Nimbostratus
Hi Aaron,
One of our engineers modified the iRule a bit, and it works great for host IPs as well as supernets. Here is the iRule;
when CLIENT_ACCEPTED {
Loop through each line in the datagroup
foreach line $::syniverse_snat {
Check if the local IP equals the current line's subnet
if {[IP::addr [IP::local_addr] equals [lindex $line 0]]}{
log local0. "[IP::local_addr]:[TCP::local_port]: Matched [lindex $line 0], using SNAT [lindex $line 1]"
Use the SNAT IP
snat [lindex $line 1]
Exit the loop as we've found a match
break
}
}
}
Thanks a lot for your help!
Rob
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects