Forum Discussion
Kai_Wilke
Aug 08, 2016MVP
Hi Squeezebox,
good to know that the iRules is (more or less) working for you and that you've found the remaining glitches by your own. I've also found a remaining bug, which is fixed in the version below...
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
set get_request 0
}
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
pool reg_pool
}
set get_request 1
} 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 get_request 0
pool reg_pool
}
}
}
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 and $get_request } 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: The bugfix makes sure that just the non-GET requests can bypass the IP validation (added the variable
and additional checks). In the previous version of my iRule it was possible, to unlock the full communication by using a single non-GET request.$get_request
Cheers, Kai