Forum Discussion
Is there a way to trigger an iRule twice?
Im attempting to clone request/response data and send it off to a pool for later analysis. I couldn't use the traditional cloning method so I used a sideband server.
I have two iRules:
The first iRule (A) sends request and response traffic to a sideband server. The second iRule (B) is associated with the sideband server and modifies the data coming in prior to sending it to the pool.
The flow is currently: Request comes in, triggers iRule (A), goes to sideband server, triggers iRule (B), goes to pool Response from production application comes in, triggers iRule (A), however it never goes to the sideband and i see no indication that it triggered iRule (B).
How can I get the production response traffic to also be sent to the sideband server and modified by the associated iRule (B)? I've tried creating a second sideband server with the same iRule (B), but to no success.
11 Replies
- Kevin_Stewart
Employee
Two questions:
-
How are you triggering both iRules? Can I assume that you're side banding to a separate VIP and iRule B is on that VIP?
-
Could you elaborate on why clone pools don't work for you? You're potentially creating substantial latency with a sideband call for every request and response.
-
- mcaballe_135435
Nimbostratus
I couldn't use the regular cloning pool because the IDS application requires me to modify the URI of all the traffic coming in to /ids/sink. I couldn't accomplish this with the VS option to clone. The side band is a separate VIP and iRule B does reside on that VIP.
Within iRule A associated with the production virtual server: HTTP_REQUEST * Force to HTTP 1.0 to prevent chunking * Find content length and start collecting * Get header HTTP_REQUEST_DATA * create sideband server connection * send header and payload to sideband server HTTP_RESPONSE * Force to HTTP 1.0 for chunking * Get content length and start collecting HTTP_RESPONSE_DATA * Get header info * Add POST /IDS/SINK line (needed by the sink application) * Send Post, Headers, payload to sideband server
- nitass
Employee
triggers iRule (A), however it never goes to the sideband and i see no indication that it triggered iRule (B).
have you tried tcpdump?
i think you send production response traffic to sideband server through existing connection (which is established in request). is irule B triggered on existing connection?
- mcaballe_135435
Nimbostratus
I can see that the request makes it to the sideband and is modified by iRule B and sent on to the pool. I've tried using the existing sideband connection to send the response but I never see the traffic get modified by irule B or make it to the pool associated with the sideband.
- nitass
Employee
I've tried using the existing sideband connection to send the response but I never see the traffic get modified by irule B or make it to the pool associated with the sideband.
can you post the irule B?
tmsh list ltm rule (irule B) - mcaballe_135435
Nimbostratus
when HTTP_REQUEST { log local0. "Original URI: [HTTP::uri]" HTTP::uri "/ids/sink"
print to see if the URI was changed log local0. "New URI: [HTTP::uri]"
print to see what is sent to this irule and forwarded to the pool HTTP::collect [HTTP::header Content-Length] log local0. "[HTTP::header Content-Length]" log local0. "[HTTP::request]"
Send to pool pool sink_pool
} local0. "[HTTP::request]"
Send to pool pool sink_pool
}
- mcaballe_135435
Nimbostratus
when HTTP_REQUEST {log local0. "Original URI: [HTTP::uri]" HTTP::uri "/ids/sink"
print to see if the URI was changed log local0. "New URI: [HTTP::uri]"
print to see what is sent to this irule and forwarded to the pool HTTP::collect [HTTP::header Content-Length] log local0. "[HTTP::header Content-Length]" log local0. "[HTTP::request]"
Send to pool pool sink_pool
}
- Kevin_Stewart
Employee
I've actually done something similar to this. Give this a try:
proc send_to_sideband { data server } { set sbserver [connect -protocol TCP -timeout 100 -idle 5 -status conn_status $server] send -status send_status -timeout 100 $sbserver $data return [recv -status recv_status -timeout 300 $sbserver] } when RULE_INIT { set static::SBSERVER "10.80.0.65:8888" } when HTTP_REQUEST { HTTP::header remove Accept-Encoding if { [HTTP::payload] eq "" } { set sb [call send_to_sideband [HTTP::request] $static::SBSERVER] } else { HTTP::collect [HTTP::header Content-Length] } } when HTTP_REQUEST_DATA { set sb [call send_to_sideband "[HTTP::request]\r\n\r\n[HTTP::payload]" $static::SBSERVER] } when HTTP_RESPONSE { if { [HTTP::header exists Content-Length] } { HTTP::collect [HTTP::header Content-Length] } } when HTTP_RESPONSE_DATA { set version [HTTP::version] switch [HTTP::status] { "200" { set status "[HTTP::status] OK" } "204" { set status "[HTTP::status] No Content" } "301" { set status "[HTTP::status] Moved Permanently" } "302" { set status "[HTTP::status] Found" } "304" { set status "[HTTP::status] Not Modified" } "307" { set status "[HTTP::status] Temporary Redirect" } "400" { set status "[HTTP::status] Bad Request" } "401" { set status "[HTTP::status] Unauthorized" } "402" { set status "[HTTP::status] Payment Required" } "403" { set status "[HTTP::status] Forbidden" } "404" { set status "[HTTP::status] Not Found" } "405" { set status "[HTTP::status] Method Not Allowed" } "500" { set status "[HTTP::status] Internal Server Error" } "501" { set status "[HTTP::status] Not Implemented" } "502" { set status "[HTTP::status] Bad Gateway" } "503" { set status "[HTTP::status] Service Unavailable" } } foreach x [HTTP::header names] { append hdr "$x: [HTTP::header $x]\r\n" } set sb [call send_to_sideband "HTTP/$version $status\r\n$hdr\r\n[HTTP::payload]" $static::SBSERVER] }So here's the thing. In the HTTP_REQUEST event, I'm either sending the sideband request if the payload is empty (like with a typical GET request) using just [HTTP::request] - the full HTTP message up to the end of the headers, or collecting on the Content-Length and then doing the sideband request with both [HTTP::request] and [HTTP::payload]. The sideband VIP will get this, and because it's a properly formatted HTTP request, will trigger its own HTTP_REQUEST event. When the real server responds, we don't have the benefit of an [HTTP::response] command that contains all of the HTTP response message up to the end of the headers, so you have to build it from scratch from the available variables. So then we take the rebuilt headers and payload and make another sideband request. This time however, the sideband iRule shouldn't trigger its HTTP_REQUEST event because the incoming data isn't a valid HTTP request. If you've formatted the data correctly it may trigger the HTTP_RESPONSE event (because it's actually a response), but then the more reliable method may simply be (potentially in both directions) to just look at the data at the TCP layer.
when CLIENT_ACCEPTED { TCP::collect } when CLIENT_DATA { log local0. [TCP::payload] TCP::release TCP::collect } - mcaballe_135435
Nimbostratus
Ahh. Ok. I tried to format the response like a request in hopes that it would trigger the http_request event on the sideband. So should I do that in an http_response event in the irule associated with the sideband (aka irule B)? If I do the tcp layer method, can I still change the uri when it hits the sideband? I'm not too familiar with the procs. I'm running 11.3 and thought it was an 11.4 and newer feature.
- Kevin_Stewart
Employee
-
You can just move all of the sideband logic down into the event and skip the proc.
-
You can replace TCP payload content just as easily as HTTP content, though you do have to be more mindful of things like payload length if you alter the payload. Otherwise, a properly formatted sideband call of the response data should trigger the HTTP_RESPONSE event in the sideband VIP.
-
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)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