Forum Discussion
Kai_Wilke
Aug 06, 2016MVP
Hi Squeezebox,
take a look to the iRule below. Its a polished version of your iRule with an added
[TABLE]
functionality to cache previous verification results and an additional filter to HTTP::retry
only request using a GET
method (the verification of other methods would have lots of implications).
when RULE_INIT {
set string to match for valid connection
set static::valid_string "Sure"
set static::table_cache_duration "10" ; seconds
}
when CLIENT_ACCEPTED {
set flag to control logical flow. 1 means lookup is pending.
set lookup 1
}
when HTTP_REQUEST {
If each request on the same connection must force a lookup,
re-initialize the value of the flag here
In this case, lookup result based on client IP is good for
the life of the connection, so we'll leave the flag alone here.
if { $lookup } then {
verify only GET request.
if { [HTTP::method] eq "GET" } then {
try to offload the verification of the current request with data of previous lookup results
if { [table lookup -notouch "is_allowed_[IP::client_addr]"] eq "" } then {
No previous request data is cached. Performing an online verification...
save the request so we can replay it to the LB server later;
set orig_request [HTTP::request]
inject lookup URI in place of original request;
HTTP::uri "/getAllowed?ip=[IP::client_addr]"
remove any cookie information for security purposes
HTTP::header remove "Cookie"
and send the out-of-band validation query to the DB_pool.
pool geo_pool
} else {
The client is verified using cached results.
set lookup 0
}
} else {
Current request is not a GET request. Do not verify the request to reduce complexity of collection and replay of HTTP::payload data.
set lookup 0
}
}
}
when HTTP_RESPONSE {
If lookup flag is still on in response event, this is the response
to the lookup, so we collect entire payload (up to 1MB limit)
both to evaluate the DB server response and to prevent this response
from being returned to the client.
Already-validated connections will bypass the rest of the rule.
if { $lookup } then {
if { ( [HTTP::header value "Content-Length"] ne "" ) and
( [HTTP::header value "Content-Length"] < 1048576) } then {
HTTP::collect [HTTP::header "Content-Length"]
} else {
HTTP::collect 1048576
}
}
}
when HTTP_RESPONSE_DATA {
HTTP_RESPONSE_DATA will only be triggered for a DB lookup.
(All other requests have already been forwarded to the LB pool.)
If response from DB indicates connection is valid, reset the
lookup flag & replay the request to the LB server.
Otherwise, reject the connection
if { [HTTP::payload] contains $static::valid_string} then {
Cache the OK response to offload subsequent requests
table set "is_allowed_[IP::client_addr]" "1" indefinite $static::table_cache_duration
Replay the origianl request
set lookup 0
pool reg_pool
HTTP::retry $orig_request
} else {
log "rejected"
reject
}
}
Note: If written the iRule out of my mind. If the syntax isn't working correctly, then post back the error logs to see whats going wrong...
Cheers, Kai