whereis¶
Description¶
Returns the geographic location of a specific IP address.
For more information on using whereis in LTM, you can check Jason Rahm’s article
Legal usage notes¶
The data is purchased by F5 for use on BIG-IP systems and products for
traffic management. The key to understanding EULA compliance is to
figure out where the geolocation decision is being made. It is a
direct violation of the EULA to use F5’s data to embed geolocation
information or codes representing geolocation information into the
requests such that another application or server could make the
decision on what to do with that data. Customers wishing to use
geolocation data on their webservers or in their applications to make
decisions in those products should reach out to their account team.
F5’s traffic management products have a lot of power and flexibility
and can make lots of decisions about traffic using the geolocation
data on the BIG-IP. For example, a geolocation lookup can be used to
route traffic requests to a different site, different server,
different URL, or even substitute a different image, object, etc in
the stream. The key is that the BIG-IP is making use of the data to
make a decision to take some action. These are all allowed and in
fact, intended usage of the geolocation data. Passing the data looked
up to another system or displaying it back publicly is a violation of
the basic data EULA. To summarize, all usage of the data must remain
local to the system with the following two exceptions:
- Location can be placed in an encrypted cookie for reference ONLY by other BIG-IP devices
- Logging data can contain location info and collected into a central logging solution for analysis of F5 logs.
Use of geolocation data that falls outside of the use cases described
in this article may be permitted under a separate license agreement
between you and our third party licensor. In the future, F5 expects
to make expanded data sets available with fewer restrictions on
direct use cases. If you are unsure if your use case is permitted
under your license, please contact your sales engineer.
Syntax¶
As of 10.1.0, the maximum length of the returned list is 8 fields. If
more than 8 fields are needed, call whereis a second time with the
remaining parameters.
Note: In GTM, prior to version 10, even when the country and continent
keywords are specified the list of {Continent Country} is still
returned. In earlier versions just use whereis and lindex to extract
the appropriate field for your use case. An example is provided below.
Note: In GTM, as of version 11.0, the ldns option can be used instead
of an IP address.
Note: Prior to version 10.1, only “country” and “continent” parameters
are valid.
whereis <ip> [country | continent | state | abbrev | city | zip | area_code |
latitude | longitude | isp | org | country_cf | state_cf | city_cf | proxy_type]+
whereis <ip>¶
- In GTM, returns a Tcl list containing continent followed by country code. In LTM, returns a Tcl list containing continent, country code, region name (if available), and city (if available). GTM: {Asia JP} LTM: {NA US Washington {}}
whereis <ip> country¶
- Returns a string containing the two-letter country code (JP)
- Country codes are defined in ISO-3166:
- Country Decoding Table
whereis <ip> abbrev¶
- Returns a string containing the state abbreviation (WA) - notice this does not work on 12.1.x BZ621374 - “abbrev” argument in “whereis” iRule returns nothing
whereis <ip> latitude¶
Returns a string (not a floating point) containing the latitude. To convert this value to degrees, divide it by 10000.0 (include the decimal point to avert truncation of the result:
set lat_deg [expr {[whereis [IP::client_addr] latitude] / 10000.0}]
)
whereis <ip> longitude¶
Returns a string (not a floating point) containing the longitude. To convert this value to degrees, divide it by 10000.0 (include the decimal point to avert truncation of the result:
set lon_deg [expr {[whereis [IP::client_addr] longitude] / 10000.0}]
)
whereis <ip> country_cf¶
whereis <ip> state_cf¶
whereis <ip> city_cf¶
whereis <ip> proxy_type¶
- Returns a string containing the proxy type, or “unknown” if no information is available.
whereis <ip> continent country state¶
- Returns a list containing the continent, country and state in that order.
whereis <ip> continent ISP state latitude¶
- Returns a string continent, ISP, state and latitude, in that order.
Note: Any combination or order of place parameters is valid, however
only 8 values will be returned at once. Note: Some or all of these
data may not be available for a given IP address. Unless otherwise
specified, in such an event an empty string is returned for a string
value, or a zero is returned for a numeric value. Note: Some of these
data are not available unless a geographic IP database has been loaded
onto your system. Please contact F5 Networks to obtain this database.
Examples¶
Checks the geographical location of each new DNS request, choosing
“asia_pool” for requests from LDNS’s with an address homed in Asia and
sending all other requests to “general_pool”:
when DNS_REQUEST {
if {[whereis [IP::client_addr]] contains "Asia"} {
pool asia_pool
} else {
pool general_pool
}
}
Version 9.x continent / country extraction:
when DNS_REQUEST {
log local0. "IP [IP::client_addr] is in \
continent [lindex [whereis [IP::client_addr]] 0] and \
country [lindex [whereis [IP::client_addr]] 1]"
}
Which logs the following:
IP x.x.x.x is in continent North America and country US
Version 10.x continent / country extraction:
when DNS_REQUEST {
log local0. "IP [IP::client_addr] is in \
continent [whereis [IP::client_addr] continent] \
and country [whereis [IP::client_addr] country]"
}
Which logs the following:
IP x.x.x.x is in continent North America and country US
Procedure to convert the latitude/longitude returned integers to
degrees, with example iRule calling it.
proc geoloc_mod {latitude longitude} {
return [list [expr {$latitude / 10000.}] [expr {$longitude / 10000.}]]
}
when HTTP_REQUEST {
set lat [whereis [IP::client_addr] latitude]
set lon [whereis [IP::client_addr] longitude]
if { [string is integer $lat] && [string is integer $lon] } {
#use proc to convert geolocation from strings to degrees, store in a list
set geoloc_deg [call geoloc_mod $lat $lon]
}
log local0. "Latitude: [lindex $geoloc_deg 0], Longititude: [lindex $geoloc_deg 1]"
}
Version 10.1 LTM:
when CLIENT_ACCEPTED {
log local0. "Got client: [whereis [IP::client_addr] country continent state city zip]"
}
Version 10.1+ LTM country based greylisting
# ========================================================================================
# For clients coming from a country in a greylist data group,
# Limit each client IP address to 1800 concurrent connections over a 180 second window
# If the client closes the connection, the count is immediately decremented.
# Else the count is decremented after the window times out for that connection.
#
# Greylist countries must be listed in the data group as the ISO3166 2 character
# http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm
when RULE_INIT {
# Max number of connections for a client over an interval
set static::max_conns 1800
# Timeout for still counting a connection that has not been closed yet
set static::interval 180
# Name of data group containing 2 character ISO3166 country codes to limit connections for
set static::greylist_dg "greylist_country_codes_dg"
# Syslog pool
set static::syslog_pool "udp_syslog_pool"
# Syslog protocol (must be exactly TCP or UDP in uppercase)
set static::syslog_proto "UDP"
}
when CLIENT_ACCEPTED {
# Exit the iRule and do not check the connection rate if the client is not from a greylist country
set country [whereis [IP::client_addr] country]
if {$country ne ""}{
# Check if the country is not in the grelist data group
if {[class match $country equals $static::greylist_dg]}{
# Exit this iRule event to prevent non-greylist IPs from being limited
return
}
}
# Set a subtable name with a standard prefix and the client IP
set tbl "connlimit:[IP::client_addr]"
# Check if the subtable has over X entries
if { [table keys -subtable $tbl -count] >= $static::max_conns } {
# Send a remote syslog message using local0.notice <133>
# see RFC 3164 Section 4.1.1 - "PRI Part" for more info
#HSL::send [HSL::open -proto $static::syslog_proto -pool $static::syslog_pool] "<190> [info hostname] [IP::local_addr]: Hit connection limit: [IP::client_addr]"
# Drop the connection
# drop
# Or apply a rateclass
# rateclass rateclass1
} else {
# Add the client IP:port to the client IP-specific subtable
# with a max lifetime of X seconds.
# Use a key of the client IP:port
set key "[IP::client_addr][TCP::client_port]"
table set -subtable $tbl $key "ignored" $static::interval
}
}
when CLIENT_CLOSED {
# When the client connection is closed, remove the table entry
table delete -subtable $tbl $key
}