Forum Discussion
iRule catching HTTP_REQUEST made to other Virtual Server
I'm experiencing a problem with apparently conflicting LTM iRules.
I have two Virtual Servers set up (let's name one
VS_TEST and the other VS_PREP). Each has a different iRule applied to it (iRule_TEST and iRule_PREP). These iRules perform the same function - they intercept incoming HTTP requests, extract some data, and then forward the data to an application running on the corresponding Pool (POOL_TEST, POOL_PREP) in the form of a HTTP GET. The application returns either Allow or Deny, informing the iRule whether to allow the request to pass through, or to reject it. Each Pool has only one node.
Normally these iRules behave correctly. A request made to
VS_TEST will be handled by iRule_TEST and send information to the application running on the single node in POOL_TEST.
There is a second type of request made to the Virtual Servers, let's call these password requests as they retrieve a password that is randomly generated by the server. I need to intercept the response by the sever and extract the password, and then send it to the same application as before. I add
HTTP_RESPONSE and HTTP_RESPONSE_DATA events to the iRules.
However, when I add
HTTP_RESPONSE and HTTP_RESPONSE_DATA events to both iRules, there is a conflict which depends on the order the iRules are updated.
For example, if I update
iRule_TEST first, followed by iRule_PREP:
- Requests made to
are handled byVS_TESTiRule_TEST
sends the data of the request to the single node iniRule_TEST
!POOL_PREP- Requests made to
are handled byVS_PREP
and the data of the request is sent to the single node iniRule_PREP
, as expected.POOL_PREP
How is this possible when both
POOL_TEST and the IP:port of its corresponding node are explicitly mentioned in iRule_TEST? The exact opposite happens if I update iRule_TEST first.
iRule_TEST
when RULE_INIT {
set ip:port of destination node (specific to TEST)
set static::serveripport "192.168.10.80:80"
}
when HTTP_REQUEST {
if {([HTTP::query] starts_with "message=")} {
This is a request we want to intercept
log local0. "Raw request: [HTTP::query]"
Extract the actual message
regexp {(message\=)(.*)} [HTTP::query] -> garbage query
Connect to node. Use catch to handle errors. Check if return value is not null.
if {[catch {connect -timeout 1000 -idle 30 -status conn_status $static::serveripport} conn_id] == 0 && $conn_id ne ""} {
Send TCP payload to application
set data "GET /Service.svc/checkmessage?message=$query"
set send_info [send -timeout 1000 -status send_status $conn_id $data]
Receive reply from application
set recv_info [recv -timeout 1000 -status recv_status $conn_id]
Allow or deny request based on application response
if {$recv_info contains "Allow"} {
pool POOL_TEST
} elseif {$recv_info contains "Deny"} {
reject
}
Tidy up
close $conn_id
} else {
reject
}
}
}
Update below
when HTTP_RESPONSE {
Collect all 200 responses
if {[HTTP::status == 200} {
set content_length [HTTP::header "Content-Length"]
HTTP::collect $content_length
}
}
when HTTP_RESPONSE_DATA {
if {[catch {binary scan [HTTP::payload] H* payload_hex} error] ne 0} {
log local0. "Error whilst binary scanning response: $error"
} else {
if {some hex string matches} {
collect password from response and set to $password
Connect to node. Use catch to handle errors. Check if return value is not null.
if {[catch {connect -timeout 1000 -idle 30 -status conn_status $static::serveripport} conn_id] == 0 && $conn_id ne ""} {
Send TCP payload to application
set data "GET /Service.svc/submitresponse?password=$password"
set send_info [send -timeout 1000 -status send_status $conn_id $data]
Tidy up
close $conn_id
}
}
HTTP::release
}
iRule_PREP is identical, save for references to POOL_TEST and the static::serveripport address.set static::serveripport "192.168.10.80:80"The above variable is global, static, and is evaluated each time the irule is updated, or whenever tmm starts (See Rule_Init ).
I hope that you haven't used the same name in both of your irules?
3 Replies
- BinaryCanary_19Historic F5 Account
set static::serveripport "192.168.10.80:80"The above variable is global, static, and is evaluated each time the irule is updated, or whenever tmm starts (See Rule_Init ).
I hope that you haven't used the same name in both of your irules?
- BinaryCanary_19Historic F5 Account
set static::serveripport "192.168.10.80:80"The above variable is global, static, and is evaluated each time the irule is updated, or whenever tmm starts (See Rule_Init ).
I hope that you haven't used the same name in both of your irules?
- FraserK_151071
Nimbostratus
D'oh! Yes I did. Thanks so much! :$
Recent Discussions
Related Content
* 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
